Cloudflare Tunnel on Kubernetes — Complete Guide
Cloudflare Tunnel on Kubernetes provides secure ingress to your cluster without provisioning cloud load balancers or exposing node IP addresses to the internet.
What You Will Learn
You will learn how to deploy cloudflared as a Kubernetes deployment, configure tunnel ingress for multiple services, and use the Cloudflare Tunnel Helm chart for production-ready deployments.
Why It Matters
Traditional Kubernetes ingress requires a cloud load balancer with a public IP, which costs money and creates an attack surface. Cloudflare Tunnel replaces this with an outbound-only connection that requires no public IP and no inbound firewall rules.
Real-World Use Case
A fintech startup running Kubernetes on bare-metal servers used Cloudflare Tunnel to expose their API and dashboard services. They eliminated the need for a cloud load balancer, reduced monthly infrastructure costs by 60%, and added Cloudflare Access authentication without changing their application code.
Tunnel Architecture on Kubernetes
Cloudflared runs as a pod that establishes outbound connections to Cloudflare, routing traffic to Kubernetes services based on ingress rules.
flowchart LR A[User] -->|HTTPS| B[Cloudflare Edge] B -->|Tunnel| C[cloudflared Pod] C -->|Cluster IP| D[Service: api] C -->|Cluster IP| E[Service: dashboard] C -->|Cluster IP| F[Service: docs] G[Internet] -.->|No Inbound| H[K8s Nodes]
Deploying with kubectl
Create a Kubernetes deployment and secret for cloudflared.
# Create a namespace
kubectl create namespace cloudflare-tunnel
# Store tunnel credentials as a Kubernetes secret
kubectl create secret generic tunnel-credentials \
--from-file=credentials.json=$HOME/.cloudflared/my-tunnel.json \
-n cloudflare-tunnel
# Deploy cloudflared
kubectl apply -f - << 'EOF'
apiVersion: apps/v1
kind: Deployment
metadata:
name: cloudflared
namespace: cloudflare-tunnel
spec:
replicas: 2
selector:
matchLabels:
app: cloudflared
template:
metadata:
labels:
app: cloudflared
spec:
containers:
- name: cloudflared
image: cloudflare/cloudflared:latest
args:
- tunnel
- --config
- /etc/cloudflared/config/config.yaml
- run
volumeMounts:
- name: config
mountPath: /etc/cloudflared/config
- name: creds
mountPath: /etc/cloudflared/credentials
volumes:
- name: config
configMap:
name: tunnel-config
- name: creds
secret:
secretName: tunnel-credentials
EOF
Expected output:
deployment.apps/cloudflared created
Configuring Tunnel Ingress
Create a ConfigMap that maps hostnames to Kubernetes services.
kubectl create configmap tunnel-config -n cloudflare-tunnel \
--from-literal=config.yaml="
tunnel: my-tunnel
credentials-file: /etc/cloudflared/credentials/credentials.json
ingress:
- hostname: api.example.com
service: http://api-service.default.svc.cluster.local:8080
- hostname: dashboard.example.com
service: http://dashboard-service.default.svc.cluster.local:80
- service: http_status:404
"
Expected output:
configmap/tunnel-config created
Using the Helm Chart
The Cloudflare Tunnel Helm chart simplifies production deployments with built-in health checks and autoscaling.
# Add the Helm repository
helm repo add cloudflare-tunnel https://cloudflare.github.io/helm-charts
helm repo update
# Install the chart
helm upgrade --install tunnel cloudflare-tunnel/cloudflare-tunnel \
--namespace cloudflare-tunnel --create-namespace \
--set tunnelName=my-tunnel \
--set credentials.existingSecret=tunnel-credentials \
--set ingress[0].hostname=api.example.com \
--set ingress[0].service=http://api-service.default.svc.cluster.local:8080
Expected output:
NAME: tunnel
LAST DEPLOYED: Mon Jun 23 10:00:00 2025
NAMESPACE: <a href="/web-servers-hosting/cloudflare/">Cloudflare</a>-tunnel
STATUS: deployed
Common Mistakes
| Mistake | Consequence |
|---|---|
| Using nodePort instead of ClusterIP services | Tunnel bypassed, exposing node IPs |
| Not setting resource limits | cloudflared pods consume all node memory |
| Running single replica | Tunnel downtime during pod restarts |
| Forgetting to update DNS records | Hostnames do not resolve to the tunnel |
| Storing credentials in ConfigMap instead of Secret | Credentials are stored in plain text |
Practice Questions
- Why should cloudflared use ClusterIP services rather than NodePort services for routing?
- What is the advantage of running multiple cloudflared replicas in a Kubernetes deployment?
- How does the Helm chart handle tunnel credentials more securely than raw kubectl manifests?
Challenge
Deploy a complete stack on Kubernetes: an Nginx web server, a ConfigMap for its content, and a Cloudflare Tunnel that exposes it. Use the Helm chart for the tunnel and verify that the site is accessible through Cloudflare but not through any node IP directly.
Real-World Task
Your organisation runs a Kubernetes cluster with three internal Microservices: an API, a dashboard, and a documentation site. Deploy Cloudflare Tunnel to expose all three services through a single tunnel. Each service must be accessible on its own subdomain. Configure the tunnel to use two replicas for high availability and verify that traffic fails over when one replica is deleted.
FAQ
{{< faq "Can Cloudflare Tunnel replace a Kubernetes Ingress Controller?">}} Cloudflare Tunnel can replace an Ingress Controller for internet-facing traffic. It handles TLS termination at the Cloudflare edge and routes traffic directly to Kubernetes services. However, it does not replace internal ingress controllers like ingress-nginx for east-west traffic within the cluster. Use tunnels for external exposure and keep ingress controllers for internal routing. {{< /faq >}}
{{< faq "How do I handle TLS certificates with Cloudflare Tunnel on Kubernetes?">}} Cloudflare Tunnel terminates TLS at the Cloudflare edge, so you do not need TLS certificates on your Kubernetes cluster. Configure Full or Full (Strict) SSL mode in the Cloudflare dashboard. The tunnel encrypts traffic between Cloudflare and cloudflared, so the entire path is encrypted end-to-end without certificate management on your cluster. {{< /faq >}}
Built by the developers of Doda Browser, DodaZIP, and Durga Antivirus Pro — security-first tools for the modern web.
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro