In this article, we are going to learn how to setup external dns in your cluster. External DNS helps you to automatically manages the DNS records of your ingresses and services, saving you so much time!. In a nutshell, external DNS is a pod that runs in your EKS cluster and monitors all of your ingresses. When it detects an ingress with a defined host, it automatically retrieves the hostname as well as the endpoint and generates a record in Route53 for that resource. If the host is updated or destroyed, external DNS will immediately update Route53. Let's get started.

Create IAM Policy

First, we need to create an IAM policy that allows external DNS to access Route53. Go to IAM -> Policies -> Create Policy. Then click on Create Policy. Select the JSON tab and paste the following policy.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"route53:ChangeResourceRecordSets"
],
"Resource": [
"arn:aws:route53:::hostedzone/*"
]
},
{
"Effect": "Allow",
"Action": [
"route53:ListHostedZones",
"route53:ListResourceRecordSets"
],
"Resource": [
"*"
]
}
]
}

or you can create the following policy using AWS CLI also. First, create a file called external-dns-policy.json and paste the above policy.

Then run the following command to create the policy.

1
aws iam create-policy --policy-name <your-policy-name> --policy-document file://external-dns-policy.json

You can check whether the policy is created using the following command.

1
aws iam list-policies --scope Local

Now we have finished creating the policy. Next, we need to create a service account for external DNS by attaching the policy we created earlier.

Create Service Account

Now we need to create a service account for the external-dns to use. This service account will be assigned the IAM policy we created in the previous step. To create a service account, run the following command.

1
eksctl create iamserviceaccount --name SERVICE_ACCOUNT_NAME --namespace NAMESPACE --cluster CLUSTER_NAME --attach-policy-arn IAM_POLICY_ARN --approve --override-existing-serviceaccounts

Note: Replace the following values in the above command:

  • SERVICE_ACCOUNT_NAME: The name of the service account you want to create. For example, external-dns.
  • NAMESPACE: The namespace you want to create the service account in. For example, default.
  • CLUSTER_NAME: The name of the EKS cluster you want to create the service account in.
  • IAM_POLICY_ARN: The ARN of the IAM policy you created in the previous step.

  • To check if the service account was created successfully, run the following command:

    1
    kubectl get sa -n NAMESPACE

    Create Role and RoleBinding

    Now we need to create a role and role binding for the service account we created in the previous step. To create a role and role binding you can use the following YAML file.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    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: SERVICE_ACCOUNT ### Service Account Name which we created in previous step
    namespace: NAMESPACE ### Namespace where we created the service account

    Then run the following command to create the role and role binding.

    1
    kubectl apply -f <your-file-name>.yaml

    Install External DNS

    Now we are ready to install external DNS. To install external DNS, we need to create a deployment. To create a deployment, you can use the following YAML file.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    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.13.4 ### You can find the latest version of the image here: https://github.com/kubernetes-sigs/external-dns/releases
    args:
    - --source=service
    - --source=ingress
    - --domain-filter=YOUR_DOMIAN_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=HOSTED_ZONE_ID
    securityContext:
    fsGroup: 65534 # For ExternalDNS to be able to read Kubernetes and AWS token files

    You can find original template from here and you can find more information about the parameters from [here]and you can find more configuration options for the ExternalDNS deployment here

    Then run the following command to create the deployment.

    1
    kubectl apply -f external-dns-deployment.yaml

    Test External DNS

    Now we have finished installing external DNS. Let's test it. Let's create simple deployment and service to test external DNS. To create a deployment and service, you can use the following YAML file.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    apiVersion: v1
    kind: Service
    metadata:
    name: nginx
    annotations:
    external-dns.alpha.kubernetes.io/hostname: nginx.example.com ### This is the domain name which we want to point to the nginx service
    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

    Now run the following command to create the deployment and service.

    1
    kubectl apply -f nginx-deployment.yaml

    Now you can check whether the external DNS has created the DNS record for the nginx service. To check that, go to Route53 -> Hosted Zones -> YOUR_DOMAIN_NAME. You can see that external DNS has created the DNS record for the nginx service.

    Conclusion

    In this article, we learned how to setup external dns in your cluster. I hope you enjoyed this article. You can find the all the related commands for this tutorial from here. If you have any issue regarding this tutorial, mention your issue in the comment section or reach me through my E-mail.

    Happy Coding