Skip to content

Latest commit

 

History

419 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Cloudflare Kubernetes Gateway

Manage Kubernetes ingress traffic with Cloudflare Tunnels via the Gateway API.

Prerequisites

Getting Started

  1. Install cloudflare-kubernetes-gateway with Kustomize:

    kubectl apply -k github.com/pl4nty/cloudflare-kubernetes-gateway//config/default?ref=v0.10.1
  2. Create a Cloudflare API token with these permissions:

    • For User Tokens, Account > Cloudflare Tunnel > Edit and Zone > DNS > Edit
    • For Account Tokens, Entire Account > Cloudflare One / Zero Trust > Argo Tunnel (Legacy) > Edit and All Domains > DNS & Zones > DNS > Edit
  3. Create a Secret with your Cloudflare Account ID and API token:

    Secret manifest
    # kubectl create secret generic -n cloudflare-gateway cloudflare-gateway-token --from-literal=ACCOUNT_ID=<account-id> --from-literal=TOKEN=<api-token>
    apiVersion: v1
    kind: Secret
    metadata:
      name: cloudflare-gateway-token
      namespace: cloudflare-gateway
    type: Opaque
    stringData:
      ACCOUNT_ID: <account-id>
      TOKEN: <api-token>
  4. Create a GatewayClass for this controller, referencing the Secret:

    GatewayClass manifest
    apiVersion: gateway.networking.k8s.io/v1
    kind: GatewayClass
    metadata:
      name: cloudflare
    spec:
      controllerName: github.com/pl4nty/cloudflare-kubernetes-gateway
      parametersRef:
        group: ""
        kind: Secret
        namespace: cloudflare-gateway
        name: cloudflare-gateway-token
  5. Create a Gateway from the GatewayClass; each Gateway corresponds to a Cloudflare Tunnel. In most cases you should only need one per cluster.

    Gateway manifest
    apiVersion: gateway.networking.k8s.io/v1
    kind: Gateway
    metadata:
      name: gateway
      namespace: cloudflare-gateway
    spec:
      gatewayClassName: cloudflare
      # listeners are not used but need to be present
      listeners:
      - name: http
        protocol: HTTP
        port: 80
  6. Manage traffic with HTTPRoutes.

    HTTPRoute example manifest
    apiVersion: gateway.networking.k8s.io/v1
    kind: HTTPRoute
    metadata:
      name: example-route
      namespace: default
    spec:
      parentRefs:
      - name: gateway
        namespace: cloudflare-gateway
      hostnames:
      - example.com
      rules:
      - backendRefs:
        - name: example-service
          port: 80
  7. (optional) Install Prometheus ServiceMonitors to collect controller and cloudflared metrics:

    kubectl apply -k github.com/pl4nty/cloudflare-kubernetes-gateway//config/prometheus?ref=v0.10.1

Features

The v1 Core spec is not yet supported, as some features (eg header-based routing) aren't available with Tunnels. The following features are supported:

  • HTTPRoute hostname and path matching
  • HTTPRoute Service backendRefs without filtering or weighting
  • Gateway gatewayClassName and listeners only
  • GatewayClass Core fields

Warning

Currently, DNS records are not deleted when route hostnames are modified or when routes are deleted. Requests to orphaned hostnames respond with an HTTP 404 Not Found, rather than a DNS lookup failure. For more details, see #206.

Configuring cloudflared

By default, a Cloudflare Tunnel client (cloudflared) runs for each Gateway, as a Deployment in the Gateway's namespace.

It can be configured with a ConfigMap referenced from the Gateway:

Gateway manifest
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
  name: gateway
  namespace: cloudflare-gateway
spec:
  gatewayClassName: cloudflare
  listeners:
  - name: http
    protocol: HTTP
    port: 80
  infrastructure:
    parametersRef:
      group: ""
      kind: ConfigMap
      name: gateway
ConfigMap manifest
apiVersion: v1
kind: ConfigMap
metadata:
  name: gateway
  namespace: cloudflare-gateway
data:
  # Disables the internal cloudflared deployment entirely. Separate clients must be deployed
  disableDeployment: "true" # string

  # The following are literal strings in yaml format that are passed directly through to the deployment spec
  # Values are examples, not the defaults

  # DeploymentSpec.replicas
  replicas: "1" # string
  # PodSpec.nodeSelector
  nodeSelector: |
    disktype: ssd
  # PodSpec.affinity
  affinity: |
    nodeAffinity:
      preferredDuringSchedulingIgnoredDuringExecution:
      - weight: 1
        preference:
          matchExpressions:
          - key: disktype
            operator: In
            values:
            - ssd
  # PodSpec.tolerations
  tolerations: |
    - key: "key1"
      operator: "Equal"
      value: "value1"
      effect: "NoSchedule"
  # PodSpec.containers[gateway].resources
  resources: |
    requests:
      memory: "64Mi"
      cpu: "250m"
    limits:
      memory: "128Mi"
      cpu: "500m"

  # Set as the TUNNEL_LOGLEVEL environment variable
  loglevel: "info"

Additional cloudflared clients can be deployed (guide) to customise parameters that aren't exposed in the Gateway config, and traffic will be load-balanced between them and the built-in client. The Gateway controller creates a Secret with the same name as the Gateway containing the token for the Cloudflare Tunnel, which can be passed directly to envFrom in custom deployments.

See also:

License

Copyright (c) 2023-2026 Tom Plant, Elias Elwyn, and contributors, MIT License.

This project is compliant with REUSE v3.3.

About

Manage Kubernetes traffic with Cloudflare Tunnels

Topics

Resources

Contributing

Stars

319 stars

Watchers

4 watching

Forks

Releases

Packages

Used by

Contributors

Languages