Cloudflare Tunnel as an alternative to Kubernetes ingress

Introduction
Kubernetes Ingress is the most popular way to expose Kubernetes resources publicly. However, in some cases, you might prefer not to use an Ingress—for example, if you want to avoid load balancer costs or lack a publicly accessible IP address. Cloudflare Tunnel offers an ideal solution for these scenarios.
Prerequisites
- A K8s cluster.
- Cloudflare Zero Trust.
- Cloudflare Tunnel client (cloudflared) installed.
Step-by-step
-
Log into Cloudflare account using cloudflared command
cloudflared login
-
Create a Tunnel
cloudflared tunnel create TUNNEL_NAME Tunnel credentials written to /root/.cloudflared/c068bf40-4a63-4de5-9ba7-3a565d4eae40.json.
-
Create a secret to store the tunnel credentials
With SealedSecret:
kubectl -n K8S_NAMESPACE create secret generic tunnel-credentials --dry-run=client \ --from-file=credentials.json=/root/.cloudflared/c068bf40-4a63-4de5-9ba7-3a565d4eae40.json \ -o yaml | kubeseal --format=yaml > sealed-secret.yaml
Or K8s normal secret:
kubectl -n K8S_NAMESPACE create secret generic tunnel-credentials \ --from-file=credentials.json=/root/.cloudflared/c068bf40-4a63-4de5-9ba7-3a565d4eae40.json
-
Chose you hostname & configure your DNS
Suppose you want to expose your application at
app.mydomain.com
. In Cloudflare DNS, add a CNAME record named app pointing to your Cloudflare Tunnel hostname, e.g.,c068bf40-4a63-4de5-9ba7-3a565d4eae40.cfargotunnel.com
. You'll also need to configure the tunnel ingress with the desired hostname (app.mydomain.com) in the next step. -
Deploy and configure
cloudflared
using HelmWith FluxCD:
apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: name: cloudflared namespace: K8S_NAMESPACE spec: interval: 24h chart: spec: chart: cloudflared version: '^0.1.1' sourceRef: kind: HelmRepository name: k8sonlab namespace: K8S_NAMESPACE interval: 24h values: cloudflare: tunnelName: TUNNEL_NAME tunnelId: c068bf40-4a63-4de5-9ba7-3a565d4eae40 secretName: tunnel-credentials ingress: - hostname: app.mydomain.com service: http://app.K8S_NAMESPACE:3000 --- apiVersion: source.toolkit.fluxcd.io/v1 kind: HelmRepository metadata: name: k8sonlab namespace: usa-idl-prod spec: interval: 24h url: https://charts.ar80.eu
Or with Heml CLI:
helm repo add k8sonlab https://charts.ar80.eu helm repo update helm install cloudflared k8sonlab/cloudflared \ --version 0.1.1 \ --namespace K8S_NAMESPACE \ --create-namespace \ --set cloudflare.tunnelName=TUNNEL_NAME \ --set cloudflare.tunnelId=c068bf40-4a63-4de5-9ba7-3a565d4eae40 \ --set cloudflare.secretName=tunnel-credentials \ --set cloudflare.ingress[0].hostname=app.mydomain.com \ --set cloudflare.ingress[0].service=http://app.K8S_NAMESPACE:3000
-
Verify
You can visit
app.mydomain.com
to confirm that the tunnel is functioning properly.
Conclusion
Using Cloudflare Tunnel to expose your Kubernetes services is straightforward, simple, and secure. Additionally, you also benefit from Cloudflare's features such as caching, CDN, and DDoS protection.