DEV Community

Jello
Jello

Posted on

Using external-dns on Kubernetes - Cloudflare

Image description

When the load balancer's IP address changes, our goal is to avoid the need for manual updates on Cloudflare. Instead, we aim to employ a monitoring service that will automatically ensure the continuity of our DNS records despite these IP changes.

Initially, let's set up external DNS. To do this, you will need the following information from Cloudflare:

  • API KEY
  • ZONE ID

We need to create a secret that external-dns can use to access the Cloudflare API.

apiVersion: v1
kind: Secret
metadata:
  name: cloudflare-api-token-secret
  namespace: default
type: Opaque
stringData:
   api-token: ${CLOUDFLARE_API_TOKEN}
Enter fullscreen mode Exit fullscreen mode

RBAC Configuration

This RBAC configuration grants the external-dns ServiceAccount permissions to interact with namespaces and specific resources in the gateway.networking.k8s.io API group.

apiVersion: v1
kind: ServiceAccount
metadata:
  name: external-dns
  namespace: default
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: external-dns
rules:
- apiGroups: [""]
  resources: ["namespaces"]
  verbs: ["get","watch","list"]
- apiGroups: ["gateway.networking.k8s.io"]
  resources: ["gateways","httproutes","grpcroutes","tlsroutes","tcproutes","udproutes"]
  verbs: ["get","watch","list"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: external-dns
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: external-dns
subjects:
- kind: ServiceAccount
  name: external-dns
  namespace: default
Enter fullscreen mode Exit fullscreen mode

Deploying external-dns

  • In the deployment replace the $ZONE_ID with the zone ID from cloudflare
  • secretKeyRef refers to the cloudflare-api-token-secret that we created earlier
  • Pay attention to --source=gateway-httproute as this flag defines what resource will be monitored for DNS changes
apiVersion: apps/v1
kind: Deployment
metadata:
  name: external-dns
spec:
  strategy:
    type: Recreate
  selector:
    matchLabels:
      app: external-dns
  template:
    metadata:
      labels:
        app: external-dns
    spec:
      serviceAccountName: external-dns
      containers:
      - name: external-dns
        image: registry.k8s.io/external-dns/external-dns:v0.13.5
        imagePullPolicy: Always
        args:
        - --source=gateway-httproute
        - --zone-id-filter=$ZONE_ID
        - --provider=cloudflare
        - --cloudflare-proxied
        - --policy=upsert-only
        - --log-level=debug
        env:
          - name: CF_API_TOKEN
            valueFrom:
              secretKeyRef:
                name: cloudflare-api-token-secret
                key: api-token
Enter fullscreen mode Exit fullscreen mode

Verify that the deployment is ready and now we can annotate the services that we want to update the dns records for.

  • The HTTPRoute resource defines a routing configuration for incoming HTTP requests with a specific host and path. When a request matches the defined conditions, it will be directed to the test-app1 backend service running on port 80. This allows for fine-grained control over how incoming traffic is directed within a Kubernetes cluster.
  • ⚠️ Important Note: Make sure that the CNAME/A name is not already created so external dns can create the record and take ownership from the start.
apiVersion: gateway.networking.k8s.io/v1beta1
kind: HTTPRoute
metadata:
  name: test-app-1
spec:
  parentRefs:
  - name: fine-ops-gateway
    sectionName: https
  hostnames:
    - "fe-1.fine-ops.com"
  rules:
    - matches:
      - path:
          type: PathPrefix
          value: /
        method: GET
      backendRefs:
      - name: test-app1
        port: 80
Enter fullscreen mode Exit fullscreen mode

Verify that the route was created be executing kubectl get httproutes

After we have applied the HTTP resource lets see if external-dns has created a new DNS record for us.Looking at the logs of the pod kubectl logs external-dns-548f86c768-82szq we can see that

  • external-dns dected the HTTP Resource and created a new A record: Image description
  • Double-checking also from the DNS cloudflare dashboard : Image description

Top comments (1)

Collapse
 
michaelthamm profile image
Michael Thamm

This helped me a lot in my quest to learn k8s. Thanks for the plethora of images in your blog