Advanced Configuration
This guide covers advanced configuration options for production deployments and specialized use cases.
High Availability Configuration
Multi-Node Deployment
Deploy Cloudflared to all nodes for high availability:
replica:
allNodes: true
updateStrategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 1
tolerations:
- effect: NoSchedule
operator: Exists
Pod Anti-Affinity
Ensure pods are distributed across nodes:
affinity:
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
labelSelector:
matchExpressions:
- key: app.kubernetes.io/name
operator: In
values:
- cloudflared
topologyKey: kubernetes.io/hostname
Node Affinity
Deploy to specific node types:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: node-type
operator: In
values:
- edge
- ingress
Performance Optimization
Resource Configuration
Optimize resource allocation for high-traffic scenarios:
resources:
limits:
cpu: "1000m"
memory: "512Mi"
requests:
cpu: "500m"
memory: "256Mi"
Connection Pooling
Configure connection pooling for better performance:
tunnelConfig:
protocol: "http2" # Use HTTP/2 for better performance
retries: 10
connectTimeout: "15s"
gracePeriod: "30s"
Keep-Alive Settings
Optimize keep-alive connections:
ingress:
- hostname: example.com
service: http://web-service.default.svc.cluster.local:80
originRequest:
keepAliveConnections: 200
keepAliveTimeout: 120s
connectTimeout: 10s
readTimeout: 60s
Security Enhancements
Network Policies
Create restrictive network policies:
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
- to:
- namespaceSelector:
matchLabels:
name: kube-system
ports:
- protocol: TCP
port: 53
Pod Security Standards
Configure pod security standards:
podSecurityContext:
fsGroup: 65532
fsGroupChangePolicy: "OnRootMismatch"
runAsUser: 65532
runAsGroup: 65532
runAsNonRoot: true
sysctls:
- name: net.ipv4.ping_group_range
value: "0 2147483647"
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
add:
- NET_RAW
readOnlyRootFilesystem: true
runAsNonRoot: true
privileged: false
runAsUser: 65532
runAsGroup: 65532
RBAC Configuration
Configure proper RBAC:
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: cloudflared-tunnel-role
rules:
- apiGroups: [""]
resources: ["services", "endpoints"]
verbs: ["get", "list", "watch"]
- apiGroups: [""]
resources: ["pods"]
verbs: ["get", "list"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: cloudflared-tunnel-binding
subjects:
- kind: ServiceAccount
name: my-cloudflared
namespace: default
roleRef:
kind: ClusterRole
name: cloudflared-tunnel-role
apiGroup: rbac.authorization.k8s.io
Monitoring and Observability
Prometheus Integration
Enable Prometheus monitoring:
podAnnotations:
prometheus.io/scrape: "true"
prometheus.io/port: "2000"
prometheus.io/path: "/metrics"
prometheus.io/scheme: "http"
Custom Metrics
Configure custom metrics collection:
tunnelConfig:
metricsUpdateFrequency: "5s"
logLevel: "info"
transportLogLevel: "warn"
Health Checks
Configure comprehensive health checks:
livenessProbe:
httpGet:
path: /ready
port: 2000
initialDelaySeconds: 30
periodSeconds: 10
timeoutSeconds: 5
failureThreshold: 3
readinessProbe:
httpGet:
path: /ready
port: 2000
initialDelaySeconds: 10
periodSeconds: 5
timeoutSeconds: 3
failureThreshold: 3
Log Aggregation
Configure log aggregation:
podAnnotations:
fluentbit.io/parser: "cloudflared"
logging.kubernetes.io/format: "json"
Custom Environment Variables
Additional Environment Variables
extraEnvVars:
- name: TUNNEL_METRICS
value: "0.0.0.0:2000"
- name: TUNNEL_ORIGIN_CA_POOL
value: "/etc/ssl/certs/ca-certificates.crt"
- name: TUNNEL_PROTOCOL
value: "http2"
Using Existing Secrets
extraSecretNamesForEnvFrom:
- name: cloudflared-config
optional: false
Custom Volumes and Configurations
Additional Volumes
volumes:
- name: custom-config
configMap:
name: cloudflared-custom-config
- name: ssl-certs
secret:
secretName: ssl-certificates
volumeMounts:
- name: custom-config
mountPath: /etc/cloudflared/custom
readOnly: true
- name: ssl-certs
mountPath: /etc/ssl/certs
readOnly: true
Custom Configuration Files
Create custom configuration files:
apiVersion: v1
kind: ConfigMap
metadata:
name: cloudflared-custom-config
data:
custom-rules.yaml: |
# Custom routing rules
- hostname: custom.example.com
service: http://custom-service.default.svc.cluster.local:8080
Load Balancing and Traffic Management
Multiple Tunnel Instances
Deploy multiple tunnel instances for load balancing:
# Primary tunnel
replica:
allNodes: false
count: 3
# Secondary tunnel for backup
nameOverride: "cloudflared-backup"
fullnameOverride: "cloudflared-backup"
tunnelConfig:
name: "backup-tunnel"
Traffic Splitting
Configure traffic splitting between services:
ingress:
- hostname: example.com
service: http://web-service-1.default.svc.cluster.local:80
originRequest:
loadBalancer:
pool: web-pool-1
- hostname: example.com
service: http://web-service-2.default.svc.cluster.local:80
originRequest:
loadBalancer:
pool: web-pool-2
Disaster Recovery
Backup Configuration
Create backup tunnel configurations:
# Primary configuration
tunnelConfig:
name: "primary-tunnel"
retries: 5
connectTimeout: "30s"
# Backup configuration
nameOverride: "cloudflared-backup"
tunnelConfig:
name: "backup-tunnel"
retries: 10
connectTimeout: "60s"
Geographic Distribution
Deploy tunnels across different regions:
# US region
nodeSelector:
region: us-west-1
# EU region
nameOverride: "cloudflared-eu"
nodeSelector:
region: eu-west-1
Custom Init Containers
Pre-flight Checks
Add init containers for pre-flight checks:
initContainers:
- name: tunnel-check
image: cloudflare/cloudflared:latest
command:
- /bin/sh
- -c
- |
cloudflared tunnel info my-tunnel || exit 1
env:
- name: TUNNEL_TOKEN
valueFrom:
secretKeyRef:
name: tunnel-credentials
key: credentials.json
Service Account Configuration
Custom Service Account
serviceAccount:
create: true
name: "cloudflared-service-account"
annotations:
eks.amazonaws.com/role-arn: "arn:aws:iam::123456789012:role/cloudflared-role"
iam.gke.io/gcp-service-account: "cloudflared@project.iam.gserviceaccount.com"
Custom Labels and Annotations
Pod Labels
podLabels:
app.kubernetes.io/component: tunnel
environment: production
team: infrastructure
cost-center: networking
Pod Annotations
podAnnotations:
prometheus.io/scrape: "true"
prometheus.io/port: "2000"
prometheus.io/path: "/metrics"
backup.kubernetes.io/enabled: "true"
backup.kubernetes.io/schedule: "daily"
monitoring.kubernetes.io/enabled: "true"
Complete Production Example
Here's a comprehensive production configuration:
# High availability deployment
replica:
allNodes: true
# Image configuration
image:
repository: cloudflare/cloudflared
pullPolicy: IfNotPresent
# Update strategy
updateStrategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 1
# Tunnel configuration
tunnelConfig:
name: "production-tunnel"
logLevel: "info"
transportLogLevel: "warn"
protocol: "http2"
retries: 10
connectTimeout: "15s"
gracePeriod: "30s"
metricsUpdateFrequency: "5s"
autoUpdateFrequency: "24h"
noAutoUpdate: true
warpRouting: false
# Tunnel secrets
tunnelSecrets:
base64EncodedConfigJsonFile: "your-base64-encoded-credentials"
base64EncodedPemFile: "your-base64-encoded-certificate"
# Ingress rules
ingress:
- hostname: app.example.com
service: http://web-service.default.svc.cluster.local:80
originRequest:
connectTimeout: 10s
readTimeout: 60s
keepAliveConnections: 200
keepAliveTimeout: 120s
- hostname: api.example.com
service: http://api-service.default.svc.cluster.local:8080
originRequest:
connectTimeout: 10s
readTimeout: 30s
- hostname: "*.example.com"
service: http://wildcard-service.default.svc.cluster.local:80
- service: http_status:404
# Resources
resources:
limits:
cpu: "1000m"
memory: "512Mi"
requests:
cpu: "500m"
memory: "256Mi"
# Security
podSecurityContext:
fsGroup: 65532
fsGroupChangePolicy: "OnRootMismatch"
runAsUser: 65532
runAsGroup: 65532
runAsNonRoot: true
sysctls:
- name: net.ipv4.ping_group_range
value: "0 2147483647"
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
add:
- NET_RAW
readOnlyRootFilesystem: true
runAsNonRoot: true
privileged: false
runAsUser: 65532
runAsGroup: 65532
# Node selection
nodeSelector:
kubernetes.io/os: linux
node-type: edge
# Tolerations
tolerations:
- effect: NoSchedule
operator: Exists
# Affinity
affinity:
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
labelSelector:
matchExpressions:
- key: app.kubernetes.io/name
operator: In
values:
- cloudflared
topologyKey: kubernetes.io/hostname
# Service account
serviceAccount:
create: true
name: "cloudflared-service-account"
annotations:
eks.amazonaws.com/role-arn: "arn:aws:iam::123456789012:role/cloudflared-role"
# Monitoring
podAnnotations:
prometheus.io/scrape: "true"
prometheus.io/port: "2000"
prometheus.io/path: "/metrics"
backup.kubernetes.io/enabled: "true"
backup.kubernetes.io/schedule: "daily"
# Labels
podLabels:
app.kubernetes.io/component: tunnel
environment: production
team: infrastructure
# Termination
terminationGracePeriodSeconds: 30
Next Steps
- Learn about tunnel setup
- Configure ingress rules
- Learn about troubleshooting common issues
- Review configuration options