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}
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
Deploying external-dns
- In the deployment replace the $ZONE_ID with the zone ID from cloudflare
-
secretKeyRef
refers to thecloudflare-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
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
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:
- Double-checking also from the DNS cloudflare dashboard :
Top comments (1)
This helped me a lot in my quest to learn k8s. Thanks for the plethora of images in your blog