Question: How do I set up ExternalDNS with Amazon EKS?

I want to set up ExternalDNS with my Amazon Elastic Kubernetes Service (Amazon EKS).

Short descriptionExternalDNS is a pod that runs in your Amazon EKS cluster. To use ExternalDNS as a plugin with Amazon EKS, set up AWS Identity and Access Management (IAM) permissions. These permissions must allow Amazon EKS access to Amazon Route 53.Note: Before starting the following resolution, make sure that a domain name and a Route 53 hosted zone exist.

ResolutionSet up IAM permissions and deploy ExternalDNS1.    Set up IAM permissions to give the ExternalDNS pod permissions to create, update, and delete Route 53 records in your AWS account.IAM policy:{  "Version": "2012-10-17",  "Statement": [    {      "Effect": "Allow",      "Action": [        "route53:ChangeResourceRecordSets"      ],      "Resource": [        "arn:aws:route53:::hostedzone/*"      ]    },    {      "Effect": "Allow",      "Action": [        "route53:ListHostedZones",        "route53:ListResourceRecordSets"      ],      "Resource": [        "*"      ]    }  ]}Note: You can also adjust the preceding policy to allow updates to explicit hosted zone IDs.2.    Use the preceding policy to create an IAM role for the service account:eksctl create iamserviceaccount --name SERVICE_ACCOUNT_NAME --namespace NAMESPACE --cluster CLUSTER_NAME --attach-policy-arn IAM_POLICY_ARN --approveNote: Replace SERVICE_ACCOUNT_NAME with your service account's name, NAMESPACE with your namespace, CLUSTER_NAME with your cluster's name, and IAM_POLICY_ARN with your IAM policy's ARN.To check the name of your service account, run the following command:kubectl get saExample output:NAME           SECRETS   AGEdefault        1         23hexternal-dns   1         23hIn the preceding example output, external-dns is the name that was given to the service account when it was created.3.    Deploy ExternalDNS.Check if RBAC is turned on in your Amazon EKS cluster:kubectl api-versions | grep rbac.authorization.k8s.ioNote: Before you apply the following manifests, check for the latest version of ExternalDNS (from the GitHub website).Run the following command:kubectl apply DEPLOYMENT_MANIFEST_FILE_NAME.yamlNote: Replace DEPLOYMENT_MANIFEST_FILE_NAME with your deployment manifest's file name.If RBAC is turned on, then use the following manifest to deploy ExternalDNS:apiVersion: rbac.authorization.k8s.io/v1kind: ClusterRolemetadata:  name: external-dnsrules:- 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/v1kind: ClusterRoleBindingmetadata:  name: external-dns-viewerroleRef:  apiGroup: rbac.authorization.k8s.io  kind: ClusterRole  name: external-dnssubjects:- kind: ServiceAccount  name: external-dns  namespace: default---apiVersion: apps/v1kind: Deploymentmetadata:  name: external-dnsspec:  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 filesIf RBAC isn't turned on, then use the following manifest to deploy ExternalDNS:apiVersion: apps/v1kind: Deploymentmetadata:  name: external-dnsspec:  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.    Verify that the deployment was successful:kubectl get deploymentsExample output:NAME           READY   UP-TO-DATE   AVAILABLE   AGEexternal-dns   1/1     1            1           85mYou can also check the logs to verify that the records are up to date:kubectl logs external-dns-9f85d8d5b-sx5fgExample output:........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"........Verify that ExternalDNS is working1.    Create a service that's exposed as LoadBalancer and that can be routed externally through the domain name that's hosted on Route 53:kubectl apply SERVICE_MANIFEST_FILE_NAME.yamlNote: Replace SERVICE_MANIFEST_FILE_NAME with your service manifest's file name.Manifest:apiVersion: v1kind: Servicemetadata:  name: nginx  annotations:    external-dns.alpha.kubernetes.io/hostname: DOMAIN_NAMEspec:  ports:    - port: 80      targetPort: 80      protocol: TCP  type: LoadBalancer  selector:    app: nginx---apiVersion: apps/v1kind: Deploymentmetadata:  name: nginxspec:  selector:    matchLabels:      app: nginx  template:    metadata:      labels:        app: nginx    spec:      containers:        - image: nginx          name: nginx          ports:            - containerPort: 80              name: httpNote: Replace DOMAIN_NAME with your domain's name.2.    Check that the NGINX service was created with the LoadBalancer type:kubectl get svcExample output:NAME         TYPE           CLUSTER-IP      EXTERNAL-IP                                                              PORT(S)        AGEkubernetes   ClusterIP      10.100.0.1      <none>                                                                   443/TCP        26hnginx        LoadBalancer   10.100.234.77   a1ef09255d52049f487e05b4f74faea6-954147917.us-west-1.elb.amazonaws.com   80:30792/TCP   74mNote: The service automatically creates a Route 53 record for the hosted zone.Check the logs to verify that the Route 53 record was created:kubectl logs external-dns-9f85d8d5b-sx5fgExample output:.........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".........For more information and examples for ExternalDNS, see Setting up ExternalDNS for services on AWS (on the GitHub website) and Set up ExternalDNS (on the Kubernetes website).