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
klik Create Token
, pilih Edit zone DNS template
Pada API Permission
# | VERB | ACTION |
---|---|---|
ZONE | DNS | EDIT |
ZONE | ZONE | READ |
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.
# | VERB | ACTION |
---|---|---|
Include | Specific zone | [NAMA DOMAIN] |
akhiri dengan klik Create Token
Pada halaman berikutnya, salin/copy token yang muncul disini, simpan dengan baik karena akan hanya satu kali ditampilkan
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