CloudflareGatewayParameters (short name: cgp) provides typed configuration
for Gateways managed by this controller. It is referenced via
.spec.infrastructure.parametersRef from a Gateway.
The following example shows a CloudflareGatewayParameters that configures DNS record management and tunnel patches:
apiVersion: cloudflare-gateway-controller.io/v1
kind: CloudflareGatewayParameters
metadata:
name: my-params
namespace: default
spec:
secretRef:
name: cloudflare-creds
dns:
zones:
- name: "example.com"
tunnel:
patches:
- op: replace
path: /spec/template/spec/nodeSelector
value:
kubernetes.io/os: linuxThe Secret referenced by .spec.secretRef.name must contain the Cloudflare API
credentials:
apiVersion: v1
kind: Secret
metadata:
name: cloudflare-creds
namespace: default
type: Opaque
stringData:
CLOUDFLARE_API_TOKEN: "your-api-token-here"
CLOUDFLARE_ACCOUNT_ID: "your-account-id-here"As with all other Kubernetes config, a CloudflareGatewayParameters needs
apiVersion, kind, and metadata fields. The name of a
CloudflareGatewayParameters object must be a valid
DNS subdomain name.
A CloudflareGatewayParameters also needs a
.spec section.
The .spec.secretRef field is optional and references a Secret in the same
namespace containing Cloudflare API credentials.
spec:
secretRef:
name: cloudflare-credsThe .spec.secretRef.name field is required when .spec.secretRef is set.
The Secret must contain CLOUDFLARE_API_TOKEN and CLOUDFLARE_ACCOUNT_ID keys.
When .spec.secretRef is not set, the controller resolves credentials through
the fallback chain described in the Gateway
documentation.
The .spec.dns field configures DNS CNAME record management. By default (when
the dns field is omitted), DNS management is enabled for all hostnames in
attached HTTPRoutes — each hostname's zone is resolved dynamically via the
Cloudflare API.
There are three modes:
All hostnames (default) — omit the dns field entirely:
spec: {}Specific zones — list the zones to manage:
spec:
dns:
zones:
- name: "example.com"
- name: "other.com"Only hostnames that are single-level subdomains of a configured zone get CNAME
records (e.g. app.example.com matches zone example.com, but
deep.sub.example.com does not).
Disabled — set an empty zones list:
spec:
dns:
zones: []When DNS is enabled, the controller creates CNAME records for matching hostnames in the attached HTTPRoutes.
The .spec.tunnel field is optional and configures Cloudflare tunnel settings.
The .spec.tunnel.minReadySeconds field controls the minimum number of seconds
a newly created tunnel pod must be Ready before the Deployment controller
considers it Available and terminates the old pod during a rolling update.
spec:
tunnel:
minReadySeconds: 30Defaults to 600 (10 minutes) when absent. This matches the Cloudflare
recommendation for rotating tunnel tokens without service disruption. The
controller sets progressDeadlineSeconds to minReadySeconds + 60, so
Kubernetes will report ProgressDeadlineExceeded if the new pod does not
become Ready within that window.
In practice, lower values work well. The project's own e2e test performs a
rolling update across 3 Deployments with minReadySeconds=30 and zero
traffic disruption.
The .spec.tunnel.token field configures tunnel token management.
spec:
tunnel:
token:
rotation:
enabled: true
schedule:
cron: "0 18 * * 4"
timeZone: America/Los_AngelesWhen automatic token rotation is enabled, the controller rotates the tunnel token via the Cloudflare API on a cron schedule, updates the in-cluster Secret, and performs a rolling restart of the tunnel pods so they pick up the new token.
Rotation is best-effort: the controller checks the schedule during each reconciliation and rotates if the token was last rotated before the most recent cron trigger.
The token rotation fields are:
rotation.enabled(optional): Whether automatic rotation is active. Defaults totruewhen therotationstruct is present.rotation.schedule(optional): Cron-based schedule for automatic rotation.schedule.cron(required): Standard 5-field cron expression.schedule.timeZone(optional): IANA time zone name. Defaults toUTC.- When absent, defaults to every Thursday at 6 PM America/Los_Angeles time.
On-demand rotation can also be triggered via cfgwctl rotate gateway token,
regardless of whether automatic rotation is configured. See the
Gateway annotation for details.
The .spec.tunnel.patches field is optional and specifies
RFC 6902 JSON Patch operations
applied to the cloudflared Deployment.
Patches run after the controller builds the base Deployment but before
replica placement fields (affinity, zone, nodeSelector) are applied on top.
This means:
- Patches can target any field of the base Deployment, including tunnel container fields (resources, probes, etc.).
- Replica placement always takes priority over user patches — setting affinity or nodeSelector via patches will be overwritten by the replica config.
- Patch errors are terminal — the controller stops retrying until the CloudflareGatewayParameters resource is updated.
spec:
tunnel:
patches:
- op: replace
path: /spec/template/spec/nodeSelector
value:
kubernetes.io/os: linux
- op: add
path: /spec/template/spec/tolerations
value:
- key: "CriticalAddonsOnly"
operator: "Exists"Each patch operation has the following fields:
op(required): Patch operation. One ofadd,remove,replace,move,copy,test.path(required): JSON Pointer path for the operation.from(optional): Source path formoveandcopyoperations.value(optional): Value foradd,replace, andtestoperations.
The .spec.tunnel.replicas field configures multiple replicas of the tunnel pods
for high availability. There are no guarantees about how requests from Cloudflare
will be distributed among replicas, but the embedded reverse proxy improves load
balancing when proxying to backend Services.
There are three behaviors:
Single replica (default) — omit the replicas field entirely. The controller
creates one Deployment named gateway-<gatewayName>-primary.
Scale to zero — set an explicitly empty list:
spec:
tunnel:
replicas: []No Deployments are created.
Multiple replicas — list each replica with a unique name:
spec:
tunnel:
replicas:
- name: alpha
zone: us-east-1a
- name: beta
zone: eu-west-1aEach entry creates a separate Deployment named
gateway-<gatewayName>-<replicaName>. All replicas share the same tunnel,
Secret, and ConfigMap resources.
Each replica has the following fields:
name(required): Identifies the replica. Must be 1–63 characters, lowercase alphanumeric with hyphens (DNS label format). Names must be unique within the list.zone(optional): Shorthand fortopology.kubernetes.io/zonenode affinity. Mutually exclusive withaffinity.nodeSelector(optional): Map of label key-value pairs for node selection.affinity(optional): Full Kubernetes affinity spec for pod placement. Mutually exclusive withzone.
Replica placement fields (affinity, zone, nodeSelector) are applied after
base Deployment construction and user patches, so they always take priority.
The .spec.tunnel field configures the tunnel container, which embeds both
cloudflared and the reverse proxy in a single container.
The .spec.tunnel.resources field configures compute resource requirements
for the tunnel container. When absent, the controller uses defaults
(requests: 50m CPU, 64Mi memory; limits: 500m CPU, 256Mi memory). When set,
the provided values replace the defaults entirely.
spec:
tunnel:
resources:
requests:
cpu: 100m
memory: 128Mi
limits:
cpu: "1"
memory: 512MiThe .spec.tunnel.autoscaling field configures vertical pod autoscaling
for the tunnel container.
spec:
tunnel:
autoscaling:
enabled: true
minAllowed:
cpu: 50m
memory: 64Mi
maxAllowed:
cpu: "2"
memory: 1Gi
controlledResources: [cpu, memory]
controlledValues: RequestsAndLimitsWhen autoscaling.enabled is true, the controller creates a
VerticalPodAutoscaler
(VPA) resource for each Deployment replica. The VPA produces resource
recommendations and applies them automatically using the InPlaceOrRecreate
update mode.
The autoscaling fields are:
enabled(required): Whether to enable VPA for the tunnel container.minAllowed(optional): Minimum recommended resources (floor).maxAllowed(optional): Maximum recommended resources (ceiling).controlledResources(optional): Which resource types to autoscale. Allowed values arecpuandmemory. Defaults to both.controlledValues(optional): Which resource values to autoscale.RequestsAndLimits(default) scales both;RequestsOnlyscales only requests.
The VPA CRD must be installed in the cluster for autoscaling to work. If the CRD is not installed, VPA creation will fail and the error will be reported in the Gateway status.