如何使用 Amazon EKS 設定 ExternalDNS?

上次更新日期:2022 年 3 月 1 日

我要使用 Amazon Elastic Kubernetes Service (Amazon EKS) 來設定 ExternalDNS。

簡短描述

ExternalDNS 是在您的 Amazon EKS 叢集中執行的 Pod。若要以外掛程式的形式來使用 ExternalDNS (搭配 Amazon EKS),您必須設定 AWS Identity and Access Management (IAM) 來允許 Amazon EKS 存取 Amazon Route 53。

附註:請確保網域名稱和 Route 53 託管區域存在。

解決方案

設定 IAM 許可並部署 ExternalDNS

1.    設定 IAM 許可來提供 ExternalDNS Pod 許可,以便於您的 AWS 帳戶中建立、更新和刪除 Route 53 記錄。

IAM 政策:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "route53:ChangeResourceRecordSets"
      ],
      "Resource": [
        "arn:aws:route53:::hostedzone/*"
      ]
    },
    {
      "Effect": "Allow",
      "Action": [
        "route53:ListHostedZones",
        "route53:ListResourceRecordSets"
      ],
      "Resource": [
        "*"
      ]
    }
  ]
}

附註:您也可以調整前述政策以允許更新明確託管區域 ID。

2.    使用前述政策為服務帳戶建立 IAM 角色:

eksctl create iamserviceaccount --name SERVICE_ACCOUNT_NAME --namespace NAMESPACE --cluster CLUSTER_NAME --attach-policy-arn IAM_POLICY_ARN --approve

附註:請以服務帳戶的名稱來取代 SERVICE_ACCOUNT_NAME、以命名空間來取代 NAMESPACE、以叢集名稱來取代 CLUSTER_NAME,並以 IAM 政策的 ARN 來取代 IAM_POLICY_ARN

若要檢查服務帳戶的名稱,請執行下列命令:

kubectl get sa

範例輸出:

NAME           SECRETS   AGE
default        1         23h
external-dns   1         23h

在前述的範例輸出中,external-dns 是建立服務帳戶時為其指定的名稱。

3.    部署 ExternalDNS。

檢查 RBAC 是否已在 Amazon EKS 叢集中啟用:

kubectl api-versions | grep rbac.authorization.k8s.io

附註:套用下列資訊清單之前,請先檢查最新版 ExternalDNS (從 GitHub 網站)。

執行下列命令:

kubectl apply DEPLOYMENT_MANIFEST_FILE_NAME.yaml

附註:以部署資訊清單檔案名稱來取代 DEPLOYMENT_MANIFEST_FILE_NAME

如果啟用了 RBAC,請使用下列資訊清單來部署 ExternalDNS:

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: k8s.gcr.io/external-dns/external-dns:v0.10.2
        args:
        - --source=service
        - --source=ingress
        - --domain-filter=external-dns-test.my-org.com # will make ExternalDNS see only the hosted zones matching provided domain, omit to process all available hosted zones
        - --provider=aws
        - --policy=upsert-only # would prevent ExternalDNS from deleting any records, omit to enable full synchronization
        - --aws-zone-type=public # only look at public hosted zones (valid values are public, private or no value for both)
        - --registry=txt
        - --txt-owner-id=my-hostedzone-identifier
      securityContext:
        fsGroup: 65534 # For ExternalDNS to be able to read Kubernetes and AWS token files

如果未啟用 RBAC,請使用下列資訊清單來部署 ExternalDNS:

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:
      containers:
      - name: external-dns
        image: k8s.gcr.io/external-dns/external-dns:v0.10.2
        args:
        - --source=service
        - --source=ingress
        - --domain-filter= <Your_R53_Domain_Name>  # will make ExternalDNS see only the hosted zones matching provided domain, omit to process all available hosted zones
        - --provider=aws
        - --policy=upsert-only # would prevent ExternalDNS from deleting any records, omit to enable full synchronization
        - --aws-zone-type=public # only look at public hosted zones (valid values are public, private or no value for both)
        - --registry=txt
        - --txt-owner-id=<Your_R53_HostedZone_Id>

4.    驗證部署是否成功:

kubectl get deployments

範例輸出:

NAME           READY   UP-TO-DATE   AVAILABLE   AGE
external-dns   1/1     1            1           85m

您也可以檢查日誌以驗證記錄是否為最新狀態:

kubectl logs external-dns-9f85d8d5b-sx5fg

範例輸出:

....
....
time="2022-02-10T20:22:02Z" level=info msg="Instantiating new Kubernetes client"
time="2022-02-10T20:22:02Z" level=info msg="Using inCluster-config based on serviceaccount-token"
time="2022-02-10T20:22:02Z" level=info msg="Created Kubernetes client https://10.100.0.1:443"
time="2022-02-10T20:22:09Z" level=info msg="Applying provider record filter for domains: [<yourdomainname>.com. .<yourdomainname>.com.]"
time="2022-02-10T20:22:09Z" level=info msg="All records are already up to date"
....
....

驗證 ExternalDNS 是否正常運作

1.    建立一個公開為 LoadBalancer 且可透過 Route 53 上託管的網域名稱從外部路由的服務:

kubectl apply SERVICE_MANIFEST_FILE_NAME.yaml

附註: 以服務資訊清單檔案名稱取代 SERVICE_MANIFEST_FILE_NAME

資訊清單:

apiVersion: v1
kind: Service
metadata:
  name: nginx
  annotations:
    external-dns.alpha.kubernetes.io/hostname: DOMAIN_NAME
spec:
  ports:
    - port: 80
      targetPort: 80
      protocol: TCP
  type: LoadBalancer
  selector:
    app: nginx

---
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
              name: http

附註:以網域名稱取代 DOMAIN_NAME

2.    檢查建立的 NGINX 服務是否具有 LoadBalancer 類型:

kubectl get svc

範例輸出:

NAME         TYPE           CLUSTER-IP      EXTERNAL-IP                                                              PORT(S)        AGE
kubernetes   ClusterIP      10.100.0.1      <none>                                                                   443/TCP        26h
nginx        LoadBalancer   10.100.234.77   a1ef09255d52049f487e05b4f74faea6-954147917.us-west-1.elb.amazonaws.com   80:30792/TCP   74m

附註:該服務會自動為託管區域建立 Route 53 記錄。

檢查日誌以驗證是否已建立 Route 53 記錄:

kubectl logs external-dns-9f85d8d5b-sx5fg

範例輸出:

...
...
...
time="2022-02-10T21:22:43Z" level=info msg="Applying provider record filter for domains: [<domainname>.com. .<domainname>.com.]"
time="2022-02-10T21:22:43Z" level=info msg="Desired change: CREATE <domainname>.com A [Id: /hostedzone/Z01155763Q6AN7CEI3AP6]"
time="2022-02-10T21:22:43Z" level=info msg="Desired change: CREATE <domainname>.com TXT [Id: /hostedzone/Z01155763Q6AN7CEI3AP6]"
time="2022-02-10T21:22:43Z" level=info msg="2 record(s) in zone xxx.com. [Id: /hostedzone/Z01155763Q6AN7CEI3AP6] were successfully updated"
time="2022-02-10T21:23:43Z" level=info msg="Applying provider record filter for domains: [<domainname>.com. .<domainname>.com.]"
time="2022-02-10T21:23:43Z" level=info msg="All records are already up to date"
...
...
...

若要進一步了解如何設定與驗證 ExternalDNS,請參閱為 AWS 上的服務設定 ExternalDNS (來自 GitHub 網站)。


此文章是否有幫助?


您是否需要帳單或技術支援?