> ## Content Index
> Fetch the complete content index at: https://anantafatur.dev/llms.txt
> Use this file to discover other available public pages before exploring further.

# Bypassing Cloudflare DNS to Speed Up Git Clone in Jenkins
- URL: https://anantafatur.dev/bypass-cloudflare-dns-git-clone-jenkins/
- Published: 2026-08-22T18:11:04.000Z
- Updated: 2026-08-22T18:11:04.000Z
- Description: I diagnosed a painfully slow git clone in a Jenkins pipeline by tracing DNS resolution through Cloudflare and AWS, then eliminated the latency by resolving the domain directly to the GitLab VM's private IP using Kubernetes hostAliases.
- Author: Ananta

## The problem: a 12-minute git clone

I maintain a Jenkins pipeline that runs terraform operations on Tencent Kubernetes Engine (TKE). Jenkins itself runs as a Docker container on a CVM, version 2.568.2 LTS, with the Kubernetes executor spawning runner pods on TKE. Every run starts with a git clone from our self-hosted GitLab at `<gitlab-domain>`. Looking at the pipeline logs, the checkout stage was taking forever.

Here is a typical run before I made any changes:

```
19:05:29  [ Run Log ] [ Stage ] [ Checkout SCM ] START
[Pipeline] checkout
19:07:14  The recommended git tool is: NONE
19:17:33  using credential <gitlab-credential>
19:17:33  Cloning the remote Git repository
19:17:33  Using shallow clone with depth 1
19:18:01  Cloning repository git@<gitlab-domain>:<org>/<project>.git
19:18:09   > git init /home/jenkins/agent/workspace/<org>/<project> # timeout=10
19:18:12  Fetching upstream changes from git@<gitlab-domain>:<org>/<project>.git
19:18:12   > git --version # timeout=10
19:18:12   > git --version # 'git version 2.47.3'
19:18:12  using GIT_SSH to set credentials <gitlab-credential>
19:18:14  Verifying host key using known hosts file, will automatically accept unseen keys
19:18:14   > git fetch --tags --force --progress --depth=1 -- git@<gitlab-domain>:<org>/<project>.git +refs/heads/*:refs/remotes/origin/* # timeout=10
19:20:11  Avoid second fetch
19:20:12  Checking out Revision <commit-sha> (origin/master)

```

Look at the gaps. 1 minute 45 seconds between START and "The recommended git tool is: NONE." Another 10 minutes before "using credential." The actual git fetch took nearly 2 minutes. Total: almost 15 minutes for a shallow clone.

After the DNS changes, the same pipeline looked like this:

```
00:34:19  [ Run Log ] [ Stage ] [ Checkout SCM ] START
[Pipeline] checkout
00:34:19  The recommended git tool is: NONE
00:34:21  using credential <gitlab-credential>
00:34:21  Cloning the remote Git repository
00:34:21  Using shallow clone with depth 1
00:34:21  Cloning repository git@<gitlab-domain>:<org>/<project>.git
00:34:21   > git init /home/jenkins/agent/workspace/<org>/<project> # timeout=10
00:34:21  Fetching upstream changes from git@<gitlab-domain>:<org>/<project>.git
00:34:21   > git --version # timeout=10
00:34:21   > git --version # 'git version 2.47.3'
00:34:21  using GIT_SSH to set credentials <gitlab-credential>
00:34:21  Verifying host key using known hosts file, will automatically accept unseen keys
00:34:21   > git fetch --tags --force --progress --depth=1 -- git@<gitlab-domain>:<org>/<project>.git +refs/heads/*:refs/remotes/origin/* # timeout=10
00:34:24  Avoid second fetch
00:34:24  Checking out Revision <commit-sha> (origin/master)

```

5 seconds. Total.

But here is the catch: I cannot say for sure that the DNS changes caused this improvement. I still do not know the root cause.

I had no idea what was causing the slowness. So I did the first thing I could think of: I looked at the DNS resolution path. Maybe the multi-hop DNS chain was adding latency to every git operation.

---

## The DNS resolution chain

Our GitLab instance lives on an EC2 instance in AWS. It sits behind an Application Load Balancer (ALB). The domain `<gitlab-domain>` is registered on Cloudflare in DNS-only mode, which means Cloudflare just returns the ALB's IPs.

Every time the Jenkins runner pod on TKE resolves `<gitlab-domain>`, this chain runs:

![DNS resolution chain before optimization: Jenkins CVM to TKE runner to gitlab-domain through Cloudflare DNS to AWS ALB to EC2 GitLab VM](https://anantafatur.dev/content/images/2026/08/dns-before.png)

That's a DNS lookup through Cloudflare and a hop through the ALB before the git client can even start transferring data. For a shallow clone, the DNS overhead might be a significant fraction of the total time.

But here is the thing. Our TKE cluster has private network connectivity to AWS. The GitLab VM has a private IP address. So why are we going through the public internet at all?

## Verifying the private path

I hopped into a debug pod in the same TKE namespace and started testing.

First, I checked the DNS resolution from the pod:

```
debug-pod:~# nslookup <gitlab-domain>
<gitlab-domain> has address <alb-ip-1>
<gitlab-domain> has address <alb-ip-2>

```

As expected, the domain resolves to the public ALB IPs. Then I tested the GitLab VM's private IP directly:

```
debug-pod:~# for port in 22 80 443 8080 8443 2443; do
  timeout 2 nc -zv <gitlab-vm-private-ip> $port 2>&1
done
Connection to <gitlab-vm-private-ip> 22 port [tcp/ssh] succeeded!
Connection to <gitlab-vm-private-ip> 80 port [tcp/http] succeeded!
nc: connect to <gitlab-vm-private-ip> port 443 (tcp) failed: Connection refused
nc: connect to <gitlab-vm-private-ip> port 8080 (tcp) failed: Connection refused

```

Port 22 (SSH) and port 80 (HTTP) were open. Port 443 (HTTPS) was closed. This made sense because the ALB was terminating TLS and forwarding HTTP to the VM on port 80.

My pipeline uses SSH for git clone, which hits port 22\. So if I could make the pod resolve `<gitlab-domain>` to the VM's private IP, the SSH clone would work fine.

But before going all-in on DNS, I wanted to rule out the basics. I ran a git clone from a jumphost to confirm that GitLab connectivity was fine from our Tencent network:

```
[root@<jenkins-server> ~]# time git clone --depth 1 git@<gitlab-domain>:<org>/<project>.git /tmp/speed-test

Cloning into '/tmp/speed-test'...
remote: Enumerating objects: 90, done.
remote: Counting objects: 100% (90/90), done.
remote: Compressing objects: 100% (78/78), done.
remote: Total 90 (delta 11), reused 57 (delta 9), pack-reused 0 (from 0)
Receiving objects: 100% (90/90), 93.84 KiB | 1000.00 KiB/s, done.
Resolving deltas: 100% (11/11), done.

real 0m2.564s
user 0m0.032s
sys  0m0.030s

```

2.5 seconds. GitLab was reachable. The Tencent-to-AWS network path was fine. The problem was specific to how Jenkins was doing the clone.

But there was a catch. The pipeline also uses the GitLab API over HTTPS with `GITLAB_HOST = 'https://<gitlab-domain>'` for things like MR change detection and commit status updates. Those would hit port 443, which is closed on the VM.

---

## The fix: hostAliases plus HTTP

The Kubernetes pod spec has a field called `hostAliases` (see the [Kubernetes docs](https://kubernetes.io/docs/tasks/network/customize-hosts-file-for-pods/)). It injects entries directly into `/etc/hosts` in all containers in the pod. The OS resolves the domain from `/etc/hosts` before ever hitting DNS. No Cloudflare, no ALB.

I added this to the pod template YAML:

```yaml
spec:
  hostAliases:
    - ip: "<gitlab-vm-private-ip>"
      hostnames:
        - "<gitlab-domain>"

```

I could have used the ALB's public IPs from the `dig` output, but I wasn't sure if those IPs were fixed. AWS ALB IPs can change. The EC2 private IP is static, so I went with that directly. Safer.

Now when the pod resolves `<gitlab-domain>`, it goes straight to the VM's private IP over the internal network.

For the GitLab API calls, I changed `GITLAB_HOST` from `https://` to `http://` in every pipeline file that referenced it. Since port 80 is open on the VM and the traffic stays within the private network, this felt safe enough for our setup.

```groovy
// Uses HTTP because the pod resolves <gitlab-domain> to the
// GitLab VM's private IP via hostAliases, bypassing the ALB.
// Port 80 is open on the VM over the private network.
GITLAB_HOST = 'http://<gitlab-domain>'

```

## The new resolution path

After the change, the DNS resolution chain for the pipeline pod is effectively gone:

![DNS resolution after optimization: gitlab-domain resolves via /etc/hosts hostAliases directly to VM private IP on ports 22 and 80](https://anantafatur.dev/content/images/2026/08/dns-after.png)

No Cloudflare DNS. No ALB. No internet egress. Every git operation resolves in microseconds from the local `/etc/hosts` file.

---

## Closing

I still do not know exactly what was making the git clone take 12 minutes. There might be something else going on with the network or the GitLab server itself. The DNS optimization was the first thing I thought to try, and honestly, it was worth a shot.

The `hostAliases` approach is simple, but it has a tradeoff. If the GitLab VM's private IP ever changes, the pipeline will break until someone updates the YAML template. In my case, the VM has a fixed private IP, so this is unlikely. But it is worth documenting.

While I was at it, I also updated the Jenkins URL in the cloud configuration to use the CVM's private IP instead of the public domain. This way the TKE runner connects to the Jenkins master via JNLP over the private network too. Same idea: keep internal traffic off the public DNS path.

For now, the git clone issue is fixed. But I still do not know what actually fixed it. Before I tried the DNS approach, I restarted the Jenkins and nginx containers and the issue went away. However, on another occasion, restarting the containers did nothing. So I tried this DNS approach. Because the error is intermittent, it is hard to reproduce. If it comes back, my next move is to upgrade the Jenkins Git plugin version. Maybe there is a bug there.