--- apiVersion: apps/v1 kind: Deployment metadata: name: cloudflared namespace: cloudflared spec: replicas: 3 # With required anti-affinity and 3 worker nodes, a surge pod can never # schedule — replace in place instead. strategy: type: RollingUpdate rollingUpdate: maxSurge: 0 maxUnavailable: 1 selector: matchLabels: app: cloudflared template: metadata: labels: app: cloudflared spec: affinity: podAntiAffinity: requiredDuringSchedulingIgnoredDuringExecution: - labelSelector: matchLabels: app: cloudflared topologyKey: kubernetes.io/hostname containers: - name: cloudflared image: cloudflare/cloudflared:latest # Always pull so :latest actually tracks upstream instead of a # per-node cached digest imagePullPolicy: Always args: - tunnel - --no-autoupdate - --metrics - 0.0.0.0:2000 # Reconnects retry forever; --retries caps the backoff interval # (1s * 2^retries, jittered). 1 = retry every ~2s max, no # exponential growth. - --retries - "1" - run env: - name: TUNNEL_TOKEN valueFrom: secretKeyRef: name: tunnel-token key: token securityContext: runAsNonRoot: true runAsUser: 65532 allowPrivilegeEscalation: false capabilities: drop: - ALL seccompProfile: type: RuntimeDefault ports: - name: metrics containerPort: 2000 protocol: TCP livenessProbe: httpGet: path: /ready port: 2000 initialDelaySeconds: 10 periodSeconds: 10 # Tolerate long edge outages: let cloudflared's own fast retry # loop reconnect instead of killing the pod into CrashLoopBackOff # (which backs off exponentially up to 5m). failureThreshold: 30 resources: requests: memory: "64Mi" cpu: "50m" limits: memory: "256Mi" cpu: "200m" restartPolicy: Always