Skip to main content
search

© 2021 Excellerate. All Rights Reserved

DevOps Engineers are responsible for deploying Helm charts for Kubernetes applications on different environments including AWS. However, after deploying helm charts, we need to manually add DNS records in the AWS Route 53 service to start the application. Adding such records manually is tedious and we can automate this process using ExternalDNS.

What is ExternalDNS?

ExternalDNS is Kubernetes cluster internal DNS server. ExternalDNS allows you to control DNS records dynamically using the Kubernetes services and Ingresses with DNS providers for e.g., AWS Route 53 service.

What is a HelmFile?

HelmFile allows you to declare the definition of all Kubernetes clusters in a single YAML file by bundling multiple helm releases i.e., multiple helm charts in a single YAML file. It keeps a directory of chart value files with version control. It also allows you to build a release specification depending on the type of environment (develop, test, production). More information about the helmfile can be found here.

Deploy External DNS on Kubernetes Cluster Using Helmfile (AWS EKS)

Prerequisites:

Create an IAM policy and Role which allows Kubernetes pods to assume the AWS IAM roles.

This policy allows ExternalDNS to update the Route53 Resource Record Sets and Hosted Zones. You can customize this policy as per your requirement.

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

Then, create an IAM Role which is assumed by the ExternalDNS Pod. After creating the role, please attach the IAM Policy to the IAM role created earlier.

Please refer to the appropriate documentation if you are using kiam or Kube2iam.

Deploy ExternalDNS on AWS EKS using helmfile

Helm chart for ExternalDNS is available on Github. We are modifying the chart and converting it into a helmfile.

Create the helmfile named as externaldns.yaml

In the podAnnotations section, add the IAM role created earlier.

# helmfile -f externaldns.yaml diff 
repositories: 
- name: external-dns 
  url: https://kubernetes-sigs.github.io/external-dns/ 
 
 
releases: 
- name: external-dns 
  namespace: kube-system 
  chart: external-dns/external-dns 
  version: 1.7.0 
  values: 
  - podAnnotations: 
      iam.amazonaws.com/role: “<IAM role ARN>” 
  wait: true 
  timeout: 120

You can modify values.yaml in the helmchart according to your requirements by adding parameters for ExternalDNS,
sources:

  • – service
  • – ingress

domain-filter: test.devops.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 # public or private hosted zones.

Run or test the syntax using diff command,

helmfile -f externaldns.yaml diff

If satisfied with the diff, run a sync or apply,

helmfile -f externaldns.yaml apply

Once deployed check if the pod is running,

kubectl get pods -n kube-system

Deploy a Kubernetes RabbitMQ application using helm file

In this example, we will deploy a RabbitMQ application and see how ExternalDNS works with ALB ingress objects. Once deployed it will dynamically add DNS records based on the hostname and ALB ingress.

The Helm chart for RabbitMQ is available on Github. We are modifying the chart and converting it into a helmfile.

Create the helmfile named rabbitmq.yaml

# helmfile -f rabbitmq.yaml diff 
repositories: 
- name: bitnami 
  url: https://charts.bitnami.com/bitnami 
 
 
releases: 
- name: rabbitmq 
  namespace: devops 
  chart: bitnami/rabbitmq 
  version: 8.24.12 
  values: 
  - auth: 
      username: “rabbitmq” 
      password: “rabbitmq” 
      erlangCookie: “ajhdkhhihkds” 
    persistence: 
      enabled: true 
    service: 
      type: NodePort 
    ingress: 
      enabled: true 
      path: /* 
      hostname: rabbitmq.devops.test.com 
      annotations: 
        kubernetes.io/ingress.class: alb 
        external-dns.alpha.kubernetes.io/hostname: rabbitmq.devops.test.com 
        alb.ingress.kubernetes.io/actions.response-404: | 
          {"Type":"fixed-response","FixedResponseConfig":{"ContentType":"text/plain","StatusCode":"404","MessageBody":"devops - 404 Page not found"}} 
        alb.ingress.kubernetes.io/actions.ssl-redirect: '{"Type": "redirect", "RedirectConfig": { "Protocol": "HTTPS", "Port": "443", "StatusCode": "HTTP_301"}}' 
        alb.ingress.kubernetes.io/certificate-arn: “arn:aws:acm:us-west-2:738379792:certificate/97394d-72255-6fd1b-a59e-79b9a80w42451” 
        alb.ingress.kubernetes.io/listen-ports: '[{"HTTPS":443}]' 
        alb.ingress.kubernetes.io/load-balancer-attributes: access_logs.s3.enabled=true, access_logs.s3.bucket=devops-elb-logs,access_logs.s3.prefix=devops 
        alb.ingress.kubernetes.io/scheme: internet-facing 
        alb.ingress.kubernetes.io/security-groups: sg-08043e2c21117694234 
        alb.ingress.kubernetes.io/subnets: subnet-b5f64bff,subnet-431e40,subnet-564e90,subnet-58863b8 
        alb.ingress.kubernetes.io/group.name: devops 
  wait: true 
  timeout: 600

In podAnnotations please add external DNS annotation external-dns.alpha.kubernetes.io/hostname to create a record for the resulting ALB.

The above Kubernetes pod will create an (IPv4) ALB in AWS which will forward traffic to the RabbitMQ application.

Run or test the syntax using diff command:-

helmfile -f rabbitmq.yaml diff

If satisfied with the diff, run a sync or apply.

helmfile -f rabbitmq.yaml apply

Once it is deployed check the pod is running.

kubectl get pods

If the source is ingress, then ExternalDNS will create DNS records based on the hosts specified in the ingress objects. The above example will result in one alias record being created i.e rabbitmq.devops.test.com which is the alias of ALB that is associated with the ingress object.

About the author

Suraj Kamble is a DevOps engineer at Excellarate. He has expertise in tools and technologies such as Docker, Kubernetes, terraform, Jenkins, CloudFormation, Gitlab and Bitbucket CICD, Sumologic, Datadog, Grafana and Prometheus. Suraj holds a bachelor’s degree in computer engineering from the Savitribai Phule Pune University.

Leave a Reply