Skip to main content

Cloudflared Chart Usage Guide

Cloudflared is a tool from Cloudflare to create secure tunnels from your Kubernetes cluster to the Cloudflare network, exposing services without opening public ports.

Why Use This Chart?

  • Secure Access: Expose Kubernetes services securely without opening public ports
  • No Ingress Required: Bypass traditional ingress controllers and load balancers
  • Global Network: Leverage Cloudflare's global network for optimal performance
  • Community Maintained: Open-source Helm chart with active community support
  • Easy Deployment: Simple Helm-based deployment with comprehensive configuration options

Prerequisites

Before deploying the Cloudflared Tunnel chart, ensure you have:

  1. Kubernetes Cluster: Version 1.21 or later
  2. Helm: Version 3.0 or later
  3. Cloudflare Account: With a domain added and configured
  4. Cloudflared CLI: For tunnel setup and management

Quick Start

1. Add the Helm Repository

helm repo add community-charts https://community-charts.github.io/helm-charts
helm repo update

2. Create a Tunnel

# Authenticate with Cloudflare
cloudflared tunnel login

# Create a tunnel
cloudflared tunnel create my-tunnel

# Configure DNS (optional)
cloudflared tunnel route dns my-tunnel example.com

3. Prepare Tunnel Files

# Encode credentials file
base64 -b 0 -i ~/.cloudflared/*.json

# Encode certificate file
base64 -b 0 -i ~/.cloudflared/cert.pem

4. Create Values File

Create a values.yaml file:

# Tunnel configuration
tunnelConfig:
name: "my-tunnel"
logLevel: "info"
protocol: "auto"
retries: 5
connectTimeout: "30s"
gracePeriod: "30s"

# Tunnel secrets (replace with your encoded values)
tunnelSecrets:
base64EncodedConfigJsonFile: "your-base64-encoded-credentials"
base64EncodedPemFile: "your-base64-encoded-certificate"

# Ingress rules
ingress:
- hostname: example.com
service: http://your-service.namespace.svc.cluster.local:80

- service: http_status:404

5. Install the Chart

helm install my-cloudflared community-charts/cloudflared \
-f values.yaml \
-n <your-namespace> \
--create-namespace

6. Verify Installation

# Check pod status
kubectl get pods -l app.kubernetes.io/name=cloudflared

# Check tunnel logs
kubectl logs -f deployment/my-cloudflared

# Test access
curl https://example.com

Deployment Modes

Deploy to all nodes for high availability:

replica:
allNodes: true

Deployment Mode

Deploy specific number of replicas:

replica:
allNodes: false
count: 3

Basic Configuration Examples

Simple Web Application

tunnelConfig:
name: "web-app-tunnel"
logLevel: "info"

tunnelSecrets:
base64EncodedConfigJsonFile: "your-credentials"
base64EncodedPemFile: "your-certificate"

ingress:
- hostname: app.example.com
service: http://web-service.default.svc.cluster.local:80

- service: http_status:404

Multi-Service Application

tunnelConfig:
name: "multi-service-tunnel"
logLevel: "info"

tunnelSecrets:
base64EncodedConfigJsonFile: "your-credentials"
base64EncodedPemFile: "your-certificate"

ingress:
- hostname: app.example.com
service: http://frontend-service.default.svc.cluster.local:3000

- hostname: api.example.com
service: http://api-service.default.svc.cluster.local:8080

- hostname: admin.example.com
service: http://admin-service.default.svc.cluster.local:8080

- service: http_status:404

Development Environment

replica:
allNodes: false
count: 1

tunnelConfig:
name: "dev-tunnel"
logLevel: "debug"

tunnelSecrets:
base64EncodedConfigJsonFile: "your-credentials"
base64EncodedPemFile: "your-certificate"

ingress:
- hostname: dev.example.com
service: http://dev-service.default.svc.cluster.local:3000

- hostname: dev-api.example.com
service: http://dev-api-service.default.svc.cluster.local:8080

- service: http_status:404

resources:
limits:
cpu: "200m"
memory: "128Mi"
requests:
cpu: "100m"
memory: "64Mi"

Common Operations

Upgrading the Chart

# Update repository
helm repo update

# Upgrade installation
helm upgrade my-cloudflared community-charts/cloudflared \
-f values.yaml \
-n <your-namespace>

Scaling the Deployment

# Scale to specific number of replicas
kubectl scale deployment my-cloudflared --replicas=3

# Or update values and upgrade
helm upgrade my-cloudflared community-charts/cloudflared \
--set replica.count=3 \
-n <your-namespace>

Rolling Back

# Rollback to previous version
helm rollback my-cloudflared -n <your-namespace>

# Or rollback to specific revision
helm rollback my-cloudflared 2 -n <your-namespace>

Uninstalling

# Uninstall the chart
helm uninstall my-cloudflared -n <your-namespace>

# Delete tunnel (optional)
cloudflared tunnel delete my-tunnel

Monitoring and Health Checks

Health Check Endpoint

The tunnel provides a health check endpoint:

# Check tunnel health
kubectl exec -it <pod-name> -- curl http://localhost:2000/ready

# Check metrics
kubectl exec -it <pod-name> -- curl http://localhost:2000/metrics

Prometheus Monitoring

Enable Prometheus monitoring:

podAnnotations:
prometheus.io/scrape: "true"
prometheus.io/port: "2000"
prometheus.io/path: "/metrics"

Log Monitoring

# Follow tunnel logs
kubectl logs -f deployment/my-cloudflared

# Check specific log levels
kubectl logs deployment/my-cloudflared | grep -i "error\|warn"

Security Considerations

Network Policies

Create network policies to restrict access:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: cloudflared-network-policy
spec:
podSelector:
matchLabels:
app.kubernetes.io/name: cloudflared
policyTypes:
- Ingress
- Egress
ingress:
- from:
- namespaceSelector:
matchLabels:
name: kube-system
ports:
- protocol: TCP
port: 2000
egress:
- to:
- namespaceSelector:
matchLabels:
name: default
ports:
- protocol: TCP
port: 80
- protocol: TCP
port: 443

RBAC Configuration

Configure proper RBAC:

serviceAccount:
create: true
name: "cloudflared-service-account"
annotations:
eks.amazonaws.com/role-arn: "arn:aws:iam::123456789012:role/cloudflared-role"

Best Practices

1. Use DaemonSet for High Availability

replica:
allNodes: true

2. Configure Resource Limits

resources:
limits:
cpu: "500m"
memory: "256Mi"
requests:
cpu: "200m"
memory: "128Mi"

3. Enable Monitoring

podAnnotations:
prometheus.io/scrape: "true"
prometheus.io/port: "2000"
prometheus.io/path: "/metrics"

4. Use Specific Hostnames

ingress:
- hostname: app.example.com
service: http://app-service.default.svc.cluster.local:80

- hostname: api.example.com
service: http://api-service.default.svc.cluster.local:8080

5. Always Include Error Handler

ingress:
# Your service rules here
- service: http_status:404 # Required

Troubleshooting

Common Issues

  1. Pod Not Starting: Check tunnel credentials and configuration
  2. Service Not Accessible: Verify ingress rules and service endpoints
  3. High Latency: Optimize protocol and connection settings
  4. Authentication Errors: Regenerate tunnel credentials

Debug Commands

# Check pod status
kubectl get pods -l app.kubernetes.io/name=cloudflared

# Check tunnel logs
kubectl logs -f deployment/my-cloudflared

# Check tunnel status
kubectl exec -it <pod-name> -- cloudflared tunnel info my-tunnel

# Test service connectivity
kubectl exec -it <pod-name> -- curl http://service-name.namespace.svc.cluster.local:port

Next Steps