iT邦幫忙

2025 iThome 鐵人賽

DAY 18
0
Cloud Native

EKS in Practice:IaC × GitOps 實戰 30 天系列 第 18

[Day 18] DNS 小精靈:ExternalDNS 自動綁定網域

  • 分享至 

  • xImage
  •  

前言

Day 17,我們透過 AWS Load Balancer Controller,讓 Kubernetes 的 Service / Ingress 可以自動建立對應的 ALB 或 NLB。雖然流量入口已經打通,但還有一個缺口:DNS 解析

若每次建立 Ingress / Service,都要手動到 Route53 建立記錄,顯然既麻煩又容易出錯。這就是今天的主角 —— ExternalDNS

ExternalDNS 是什麼?為什麼需要它?

ExternalDNS 是一個 Kubernetes Controller,會自動觀察叢集裡的 Service 和 Ingress,然後在 DNS 提供者(AWS Route53、Cloudflare…等)建立或刪除對應的 DNS record。

  • 它是什麼:一個專門幫 K8s 資源和 DNS 提供者溝通的控制器。
  • 為什麼需要:讓 Ingress 與 DNS 紀錄自動同步,不必手動維護 Route53。

舉例:

  • 你建立一個帶有 host: argocd.example.com 的 Ingress。
  • ExternalDNS 會偵測到這個規則,並在指定的 Route53 Hosted Zone 裡,自動建立一筆 argocd.example.com → NLB/ALB 的 CNAME/A記錄。
  • 刪掉 Ingress 時,DNS 記錄也會跟著刪掉。

架構設計:為什麼只部署在 central cluster?

我們的 DNS 並不是由專案帳號直接管理,而是放在另一個專用的 AWS Account。

  • 如果在所有 project cluster 都裝 ExternalDNS,就代表任何人隨便寫一個 Ingress,就可能在 Route53 Hosted Zone 生成一筆記錄 → 權限太大、風險過高。
  • 為了避免這種情況,我們只在 central cluster 部署 ExternalDNS,統一控管 DNS record。
  • 這樣做的好處是 降低風險:project cluster 雖然能建 Ingress,但不會直接改 DNS,必須透過 central cluster 來完成。

因此,這邊我們不會使用 ApplicationSet,而是單純用 Application 在 central cluster 安裝 ExternalDNS。

ExternalDNS Application

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: external-dns
  namespace: argocd
spec:
  project: infra
  source:
    repoURL: https://kubernetes-sigs.github.io/external-dns
    chart: external-dns
    targetRevision: 1.14.5
    helm:
      releaseName: external-dns
      valueFiles:
        - infra-charts/external-dns/values.yaml
  destination:
    name: in-cluster
    namespace: kube-system
  syncPolicy:
    syncOptions:
      - serverSideApply=true

values.yaml 說明

以下是我們實際使用的 values(精簡版):

serviceAccount:
  create: true
  name: external-dns
  annotations:
    eks.amazonaws.com/role-arn: arn:aws:iam::DNSACCOUNT00:role/external-dns

rbac:
  create: true

interval: 5m
policy: sync
registry: txt
provider: aws

tolerations:
  - operator: Exists

extraArgs:
  - --annotation-filter=external-dns.alpha.kubernetes.io/exclude notin (true)

resources:
  requests:
    cpu: 10m
    memory: 50Mi
  limits:
    memory: 50Mi

txtOwnerId: example-internal
txtPrefix: example-internal-edns-
domainFilters:
  - example.com
  • IRSA 綁定:透過 eks.amazonaws.com/role-arn 綁到 DNS 管理帳號的 IAM Role。
  • registry: txt:使用 TXT record 做狀態鎖,避免多個 ExternalDNS instance 互相踩到。
  • annotation-filter:只處理沒有 external-dns.alpha.kubernetes.io/exclude: true 的 Ingress,避免誤加記錄。細節可以看這項 comment
  • domainFilters:只允許管理指定的網域,確保不會誤動其他網域的 DNS。

別忘了我們的 ArgoCD!

有了前面幾個幫我們打通網路的工具(ingress-nginx / load balancer controller / external-dns)之後,我們終於可以拿 ArgoCD 建立 ingress,並且用 domain name 正正當當的連進去看、不用再使用 port forward 了!

我們只需要在 ArgoCD 的 value file 中加入以下的設定,並再次使用 terraform apply

server:
  ingress:
    enabled: true
    ingressClassName: nginx
    hosts:
      - argocd.example.com

Helm chart 就會自動再生成一個 ingress,內容如下:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: argo-cd-argocd-server
  namespace: argocd
spec:
  ingressClassName: nginx
  rules:
  - host: argocd.example.com
    http:
      paths:
      - backend:
          service:
            name: argo-cd-argocd-server
            port:
              number: 443
        path: /
        pathType: Prefix

於是 ExternalDNS 會偵測到多了這個 ingress,並將這個 ingress 對應的 record 更新到 hosted zone 中:

https://ithelp.ithome.com.tw/upload/images/20250918/20119667EdPCBEQ0Yi.jpg

接著打開我們註冊到 A record 中的 ArgoCD URL,就可以看到熟悉的 UI 了:

https://ithelp.ithome.com.tw/upload/images/20250918/20119667DSnAZJY6ZP.jpg


小結

今天我們安裝了 ExternalDNS,讓 Kubernetes 的 Ingress / Service 自動和 Route53 同步:

  • 自動化:不用再手動進 Route53 建立記錄。
  • 集中治理:只在 central cluster 部署 ExternalDNS,避免 project cluster 擁有過大權限。
  • 安全控制:透過 annotation-filter 與 domainFilters,確保只有需要的 Ingress 會觸發 DNS 更新。

到這裡,從 Pod → Service → Ingress → NLB/ALB → DNS 的完整流量鏈路已經打通。

Day 19,我們會進一步介紹 Monitoring(Prometheus & Grafana),讓這些基礎設施不只會動,還能被觀察 👀


上一篇
[Day 17] 蓋橋鋪路:讓 Service 與 ALB/NLB 自動接上 AWS
下一篇
[Day 19] 叢集的千里眼:Prometheus & Grafana 讓一切被看見
系列文
EKS in Practice:IaC × GitOps 實戰 30 天20
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言