ExternalDNS berguna untuk membuat record DNS untuk services ataupun inggress di penyedia layanan DNS. Untuk mengupdate DNS jadi lebih mudah, karena semuanya bisa dijalankan lewat deployment di Kubernetes.

Bila anda memiliki banyak ingress/services yang di akan di expose agar bisa diakses dari luar cluster ExternalDNS akan sangat membantu, karena untuk mengganti DNS cukup mengupdate file YAML.

Buat Token API di Cloudflare

Setelah login ke dashboard Cloudflare, buka https://dash.cloudflare.com/profile/api-tokens, kalo manual klik bisa lewat My Profile -> API Token
create api token on cloudflare

klik Create Token, pilih Edit zone DNS template
use edit dns template

Pada API Permission

#VERBACTION
ZONEDNSEDIT
ZONEZONEREAD

Pada Zone Resources kita akan membatasi token yang dibuat hanya bisa mengakses satu domain saja. Cara ini jauh lebih aman, dibanding memberikan akses ke seluruh domain di akun anda.

#VERBACTION
IncludeSpecific zone[NAMA DOMAIN]

permission api cloudflare
klik Continue to summary

permission summary cloudflare
akhiri dengan klik Create Token

Pada halaman berikutnya, salin/copy token yang muncul disini, simpan dengan baik karena akan hanya satu kali ditampilkan
the cloudflare token

Kubernetes

Mari kita buat file deployment untuk external-dns, beri nama cloudflare-external-dns.yaml

apiVersion: v1
kind: ServiceAccount
metadata:
  name: external-dns
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: external-dns
rules:
- apiGroups: [""]
  resources: ["services","endpoints","pods"]
  verbs: ["get","watch","list"]
- apiGroups: ["extensions","networking.k8s.io"]
  resources: ["ingresses"]
  verbs: ["get","watch","list"]
- apiGroups: [""]
  resources: ["nodes"]
  verbs: ["list", "watch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: external-dns-viewer
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: external-dns
subjects:
- kind: ServiceAccount
  name: external-dns
  namespace: default
---
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.14.2
        args:
        - --source=service
        - --source=ingress
        - --domain-filter=DOMAINCOM
        - --provider=cloudflare
        - --cloudflare-dns-records-per-page=200
        env:
        - name: CF_API_TOKEN
          value: "XXXXXXX"

Pada source kita membuat dua value service dan ingress agar External DNS mengenali kedua jenis object tersebut dan akan membuatkan domain/subdomain di Cloudflare sesuai dengan annotation yang kita buat nantinya.
Ganti CF_API_TOKEN dengan token dari Cloudflare and DOMAINCOM dengan nama domain anda.

Deploy object tersebut ke namespace infra, bila anda tidak perlu menggunakan namespace tertentu ganti dengan infra dengan default

kubectl apply -f cloudflare-external-dns.yaml -n infra
# output
serviceaccount/external-dns created
clusterrole.rbac.authorization.k8s.io/external-dns created
clusterrolebinding.rbac.authorization.k8s.io/external-dns-viewer created
deployment.apps/external-dns created

pastikan tidak ada error pada pod external-dns dengan mengecek log

$ kubectl logs -l app=external-dns -n infra 
time="2024-06-20T11:40:12Z" level=info msg="config: {APIServerURL:  WebhookServer:false TraefikDisableLegacy:false TraefikDisableNew:false}"
time="2024-06-20T11:40:12Z" level=info msg="Instantiating new Kubernetes client"
time="2024-06-20T11:40:12Z" level=info msg="Using inCluster-config based on serviceaccount-token"
time="2024-06-20T11:40:12Z" level=info msg="Created Kubernetes client https://10.96.0.1:443"

Buat Subdomain Baru

Untuk testing kita akan membuat service yang menggunakan annotation external-dns.alpha.kubernetes.io/hostname
Buat file nginx.yaml yang berisi

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx
spec:
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - image: nginx
        name: nginx
        ports:
        - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: nginx-1
  annotations:
    external-dns.alpha.kubernetes.io/hostname: NGINX-1.DOMAINCOM
    external-dns.alpha.kubernetes.io/ttl: "130"
spec:
  selector:
    app: nginx
  type: NodePort
  ports:
    - protocol: TCP
      port: 80
      targetPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: nginx-2
  annotations:
    external-dns.alpha.kubernetes.io/hostname: NGINX-2.DOMAINCOM
    external-dns.alpha.kubernetes.io/ttl: "130"
spec:
  selector:
    app: nginx
  type: NodePort
  ports:
    - protocol: TCP
      port: 80
      targetPort: 80

disini kita akan membuat 2 sub domain NGINX-1.DOMAINCOM dan NGINX-2.DOMAINCOM. Deploy object tersebut ke Kubernetes

kubectl apply -f nginx.yaml -n infra
# output
deployment.apps/nginx created
service/nginx created
service/host2 created

cek log dari External DNS, akan muncul log yang menginformasikan record tersebut berhasil dibuat

time="2024-06-20T11:53:02Z" level=info msg="Changing record." action=CREATE record=nginx-1.DOMAINCOM ttl=130 type=A zone=5d47fd91f8a58cba30d9fc8dxa0caklxb0
time="2024-06-20T11:53:03Z" level=info msg="Changing record." action=CREATE record=nginx-2.DOMAINCOM ttl=130 type=A zone=5d47fd91f8a58cba30d9fc8dxa0caklxb0
time="2024-06-20T11:53:03Z" level=info msg="Changing record." action=CREATE record=nginx-1.DOMAINCOM ttl=1 type=TXT zone=5d47fd91f8a58cba30d9fc8dxa0caklxb0
time="2024-06-20T11:53:03Z" level=info msg="Changing record." action=CREATE record=a-nginx-1.DOMAINCOM ttl=1 type=TXT zone=5d47fd91f8a58cba30d9fc8dxa0caklxb0
time="2024-06-20T11:53:04Z" level=info msg="Changing record." action=CREATE record=nginx-2.DOMAINCOM ttl=1 type=TXT zone=5d47fd91f8a58cba30d9fc8dxa0caklxb0
time="2024-06-20T11:53:04Z" level=info msg="Changing record." action=CREATE record=a-nginx-2.DOMAINCOM ttl=1 type=TXT zone=5d47fd91f8a58cba30d9fc8dxa0caklxb0
time="2024-06-20T11:54:02Z" level=info msg="All records are already up to date"

Mengamankan Token Cloudflare

Token Cloudflare yang saat ini kita gunakan, bisa dilihat oleh semua user (read only) yang memiliki akses melihat deployment.

$ kubectl get deployment/external-dns -o yaml | grep CF_API_TOKEN -A1
# output
- name: CF_API_TOKEN
        value: XXXXXXXX

Cara untuk mengamankannya adalah dengan membuat object secret. Jalankan perinta dibawah ini

kubectl create secret generic cloudflare-token --from-literal=apiKey=XXXX -n infra

lalu buka kembali file cloudflare-external-dns.yaml

        env:
        - name: CF_API_TOKEN
          value: "XXXXXXX"

menjadi

        env:
        - name: CF_API_TOKEN
          valueFrom:
            secretKeyRef:
              name: cloudflare-token
              key: apiKey

lalu deploy ulang

kubectl apply -f cloudflare-external-dns.yaml -n infra

Leave a comment

Your email address will not be published. Required fields are marked *