Best Practices How-tos kubernetes Tanzu Mission Control tutorials

Automatically Manage DNS for Kubernetes with ExternalDNS and Tanzu Mission Control Catalog

If you have ever deployed Kubernetes services, you understand the pain of having to maintain DNS records for an ever-growing number of internal and external services. ExternalDNS helps address this pain and reduces the amount of toil required for manual record keeping by programmatically updating DNS servers. Before we get into the details of how that works, let’s quickly review what functionality the ExternalDNS package provides:

“Inspired by Kubernetes DNS, Kubernetes' cluster-internal DNS server, ExternalDNS makes Kubernetes resources discoverable via public DNS servers. Like KubeDNS, it retrieves a list of resources (services, ingresses, etc.) from the Kubernetes API to determine a desired list of DNS records. Unlike KubeDNS, however, it is not a DNS server itself, but merely configures other DNS providers accordingly—e.g. AWS Route 53 or Google Cloud DNS.”

This guide focuses on using the VMware Tanzu Mission Control Catalog for deploying and configuring the ExternalDNS package, specifically for Route53 on Amazon Web Services (AWS).

Note that these steps are not covered in this post and should be completed before proceeding:

  • Create a permissions policy that allows external DNS updates

  • Create a new user in IAM

  • Create a subdomain on the hosted zone

  • Have your user API access and secret key available

To perform the AWS-specific tasks referenced above, follow these detailed steps. For configuring with Contour using HTTPProxy, follow these instructions.

Create the secret

We first need to create a Kubernetes secret that contains the AWS credentials. ExternalDNS needs the AWS credentials to make modifications to the Route 53 DNS tables. Open a text editor and paste the content below into it:

apiVersion: v1
kind: Secret
metadata:
  name: aws-externaldns
  namespace: tanzu-system-service-discovery
type: Opaque
stringData:
  access-key-id: << ACCESS KEY ID >>
  secret-access-key: << SECRET ACCESS KEY >>

Modify the name, access-key-id, and secret-access-key to meet your requirements and save the file as “secret.yaml”. 

Open a terminal in the same directory where you saved the secret.yaml file, and execute the following to the secret to the tanzu-system-service-discovery namespace:

kubectl apply -f secret.yaml

Deploy the package

Log in to the Tanzu Mission Control console by visiting your organization’s URL:

<Org Name>.tmc.cloud.vmware.com

Click on “Catalog” on the left-side menu and click on the external-dns package.

Click “Install Package” at the top right of the view. Enter the name for the package install and click “Next”.

In step two, leave these values at the default. The namespace selected here is only used to install the package. ExternalDNS will be installed to the tanzu-system-service-discovery namespace. Click “Next”.

Here is an example of an ExternalDNS configuration for Route53. The arguments are going to be similar for any Route53 configuration, but be sure to change the domain-filter, policy, aws-zone-type, and txt-owner-id to the required values. The environment variables are utilizing the Kubernetes secret that was created in an earlier step. After modifying the below YAML config, copy and paste it into the “Your Configured Values” text box in step 3:

deployment:
  args:
    - --source=service
    - --source=ingress
    - --provider=aws
    - --domain-filter=<your domain here>
    - --events
    - --policy=sync
    - --aws-zone-type=private
    - --aws-prefer-cname
    - --registry=txt
    - --txt-owner-id=<zone ID>
    - --txt-prefix=txt

  env:
    - name: AWS_ACCESS_KEY_ID
      valueFrom:
        secretKeyRef:
          key: access-key-id
          name: aws-externaldns
    - name: AWS_SECRET_ACCESS_KEY
      valueFrom:
        secretKeyRef:
          key: secret-access-key
          name: aws-externaldns

Note: You will need to add the following to the deployment args block if you are using service accounts as a role with trust relationships:

- --aws-assume-role=<arn>

Now that the package has been deployed to the cluster, you will see a status of “Reconciling”. Once installation has completed, the status will show “Succeeded” with a green check.

Let’s deploy a sample Nginx service to verify that ExternalDNS is working. The annotation of the service will determine the DNS name that will be configured on the DNS server once the service is available. Copy and paste the below YAML into a file named “nginx-test.yaml” and replace "<your domain here>" with the desired domain:

apiVersion: v1
kind: Service
metadata:
  name: nginx
  annotations:
    external-dns.alpha.kubernetes.io/hostname: <your domain here>
spec:
  type: LoadBalancer
  ports:
  - port: 80
    name: http
    targetPort: 80
  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

Apply the YAML to your cluster with the following:

kubectl apply –f nginx-test.yaml

Check the AWS Route 53 console to ensure the DNS entries have been added automatically.

Notice the records added by ExternalDNS:

Now let’s remove the test services to make sure deletion works properly. To remove the test service and pods and to confirm the DNS entries have been removed, execute the following: 

kubectl delete –f nginx-test.yaml

This demonstration has shown how easy it is to get started using the Tanzu Mission Control Catalog. To learn more about Tanzu Mission Control Catalog, check out the recent launch announcement. You can also get free hands-on experience with Tanzu Mission Control through the Tanzu Standard Pathfinder course. Stay up to date with new features and fixes with the Tanzu Mission Control release notes.