Cloudflare
A cloudflared Deployment runs in-cluster, creating an encrypted tunnel to the Cloudflare edge using a remotely-managed (token-based) tunnel, as recommended by the official Cloudflare guide.
Remotely-Managed Tunnel (Recommended)
Prerequisites
- Cloudflare account with Zero Trust enabled
- A domain zone added to Cloudflare
cloudflaredCLI installed locally- Cluster can reach Cloudflare on port
7844
Step 1: Create a Tunnel in the Dashboard
- Go to Zero Trust → Networks → Cloudflare Tunnels
- Select Create a tunnel
- Choose Cloudflared and name it (e.g.
k8s-tunnel) - Copy the tunnel token (e.g.
eyJhIjoi...)
Step 2: Store the Token
kubectl create ns cloudflare-tunnel
kubectl -n cloudflare-tunnel create secret generic tunnel-token \
--from-literal=token=<YOUR_TUNNEL_TOKEN>
Step 3: Deploy cloudflared
The Deployment runs 2 replicas for HA.
Tip
Each replica connects to Cloudflare with the same tunnel token — no need for separate tunnels per pod. See the Cloudflare HA guide for details.
Configuration: cloudflare-k8s/deployment.yaml
- Routes traffic based on Public hostnames configured in the Cloudflare dashboard
- Each replica exposes a
/readyendpoint on port2000for liveness checks - ICMP support is enabled via
net.ipv4.ping_group_rangesysctl
Step 4: Deploy httpbin (Test App)
Deploy a sample httpbin application to verify tunnel connectivity:
This creates a Deployment (2 replicas) and ClusterIP service named httpbin-service in the cloudflare-tunnel namespace.
Step 5: Configure Public Hostnames
In the Cloudflare dashboard under the tunnel, add Public hostnames:
| Hostname | Service |
|---|---|
lab.example.com | http://traefik.kube-system.svc:80 |
*.lab.example.com | http://traefik.kube-system.svc:80 |
For direct testing without Traefik, point a hostname straight at httpbin:
| Hostname | Service |
|---|---|
httpbin.lab.example.com | http://httpbin-service.cloudflare-tunnel.svc:80 |
Traffic flows: User → Cloudflare Edge → cloudflared pod → Service → Pod
Step 6: Verify
Expected output:Test the httpbin endpoint:
Terraform — Tunnel Routes & Zero Trust
The cloudflare-k8s/ Terraform workspace manages private network routes and Gateway rules for the tunnel:
Resources created:
| Resource | Purpose |
|---|---|
cloudflare_argo_tunnel | Zero Trust tunnel definition |
cloudflare_tunnel_route | Routes Kubernetes API IPs through the tunnel |
cloudflare_teams_list | IP list for the API server |
cloudflare_teams_rule | Bypass HTTP inspection for kubectl traffic |
Note
The Terraform-managed tunnel (cloudflare_argo_tunnel) is separate from the dashboard-created tunnel used by the Deployment. Update main.tf to reference the correct tunnel ID if you want Terraform to manage tunnel routes for the dashboard-created tunnel.
Cloudflare Operator (Alternative)
A separate operator that manages DNS records and tunnels declaratively via Custom Resources:
Deploy MkDocs
Build and deploy MkDocs to Cloudflare Pages manually:
Prerequisites
A Cloudflare API token with these permissions:
- Account → Cloudflare Pages → Edit
- Account → Account Settings → Read
To create the token:
- Go to Cloudflare Dashboard → My Profile → API Tokens
- Click Create Token → Custom token
- Name:
k8s-labs-pages-deploy - Permissions:
- Account → Cloudflare Pages → Edit
- Account → Account Settings → Read
- Account Resources: Include your account
- Copy the token
Export it locally:
Deploy
Source: adyanth/cloudflare-operator