External DNS lets you dynamically configure DNS records based on Kubernetes load balanced services. You can deploy the TKG Extension for External DNS to provide dynamic service discovery for your cluster.

Extension Prerequisites

Adhere to the following requirements before deploying the TKG Extension v1.3.1 for External DNS.

Deploy the External DNS Extension

Harbor requires a DNS Zone on either a local DNS Server, such as BIND, or on a public cloud, such as AWS Route53, Azure DNS, or Google CloudDNS. Once you have set up DNS, to automatically register the Harbor FQDNs with a DNS Server, install the External DNS extension.

  1. Verify that you have completed the extension prerequisites. See Extension Prerequisites.
  2. Change directory to where you have downloaded the External DNS extension files.
    cd /tkg-extensions-v1.3.1+vmware.1/extensions/service-discovery/external-dns
  3. Create the namespace and several role-based access control objects for use with the External DNS extension.
    kubectl apply -f namespace-role.yaml

    This command creates the namespace tanzu-system-service-discovery and associated RBAC objects. Run kubect get ns to verify.

  4. Create a data values file. The example data values file provides the minimum required configuration.

    There are example data values files for AWS, Azure, and an RFC 2136-compliant Dynamic DNS provider, each with and without Contour ingress. Choose the appropriate example file and copy it.

    For example, if you are using AWS Route 53 with Contour, run the following command.
    cp external-dns-data-values-aws-with-contour.yaml.example external-dns-data-values-aws-with-contour.yaml
    Or, if you are using Azure with Contour, run the following command.
    cp external-dns-data-values-azure-with-contour.yaml.example external-dns-data-values-azure-with-contour.yaml
  5. Configure the External DNS data values.

    For example, below is the configuration for Azure DNS. You provide the domain-filter and azure-resource-group values.

    #@data/values
    #@overlay/match-child-defaults missing_ok=True
    ---
    externalDns:
      image:
        repository: projects.registry.vmware.com/tkg
      deployment:
        #@overlay/replace
        args:
        - --provider=azure
        - --source=service
        - --source=ingress
        - --domain-filter=my-zone.example.org #! zone where services are deployed
        - --azure-resource-group=my-resource-group #! Azure resource group
        #@overlay/replace
        volumeMounts:
        - name: azure-config-file
          mountPath: /etc/kubernetes
          readOnly: true
        #@overlay/replace
        volumes:
        - name: azure-config-file
          secret:
            secretName: azure-config-file
  6. Create a generic secret with using the data values file you populated.

    For example, the following command creates the secret using the Azure DNS data values file.

    kubectl create secret generic external-dns-data-values --from-file=values.yaml=external-dns-data-values-azure-with-contour.yaml -n tanzu-system-service-discovery

    You should see secret/external-dns-data-values created is created in the tanzu-system-service-discovery namespace. You can verify this using the command kubectl get secrets -n tanzu-system-service-discovery.

  7. Deploy the External DNS extension.
    kubectl apply -f external-dns-extension.yaml

    On success you should see app.kappctrl.k14s.io/external-dns created.

  8. Check the status of the extension deployment.
    kubectl get app external-dns -n tanzu-system-service-discovery
    The app status should change from Reconciling to Reconcile succeeded once the External DNS is deployed successfully. If the status is Reconcile failed, see Troubleshoot Deployment.
  9. View detailed status.
    kubectl get app external-dns -n tanzu-system-service-discovery -o yaml

Troubleshoot Deployment

If the reconciliation fails, run the command kubectl get pods -A to view the status of the pods. Under normal conditions you should see that the external-dns-XXXXX pod is Running. If the reconciliation fails or the pod status is ImagePullBackOff or ImagecRashLoopBackOff, this means the container image could not be pulled from the repository. Check the repository URL in the data values and the extension YAML files and make sure they are accurate.

To check the container logs, run the following commands, where name-XXXX is the unique pod name that you can see when you run kubectl get pods -A:
kubectl logs pod/external-dns-XXXXX -c external-dns -n tanzu-system-service-discovery

Update the External DNS Extension

Update the External DNS extension that is deployed to a Tanzu Kubernetes cluster.

  1. Get Contour data values from the secret.
    kubectl get secret external-dns-data-values -n tanzu-system-service-discovery -o 'go-template={{ index .data "values.yaml" }}' | base64 -d > external-dns-data-values.yaml
  2. Update External DNS data values in external-dns-data-values.yaml. See Configure the External DNS Extension.
  3. Update the Contour data values secret.
    kubectl create secret generic external-dns-data-values --from-file=values.yaml=external-dns-data-values.yaml -n tanzu-system-service-discovery -o yaml --dry-run | kubectl replace -f-
    The External DNS extension will be reconciled with the new data values.
    Note: By default, kapp-controller will sync apps every 5 minutes. The update should take effect in 5 minutes or less. If you want the update to take effect immediately, change syncPeriod in external-dns-extension to a lesser value and apply the Contour extension using kubectl apply -f external-dns-extension.
  4. Check the status of the extension.
    kubectl get app external-dns -n tanzu-system-service-disovery

    The app status should change to Reconcile Succeeded once it is updated.

  5. View detailed status and troubleshoot.
    kubectl get app external-dns -n tanzu-system-service-disovery -o yaml

Delete the External DNS Extension

Delete the Contour extension from a Tanzu Kubernetes cluster.

Note: Complete the steps in order. Do not delete the target namespace and role objects before the extension and app are deleted. Deleting the namespace and role objects deletes the service account used by kapp-controller. If this service account is deleted before the app and extension are deleted, it can lead to system errors.
  1. Change directory to where you have downloaded the extension files.
    cd /tkg-extensions-v1.3.1+vmware.1/extensions/service-discovery/external-dns
  2. Delete the External DNS extension.
    kubectl delete -f external-dns-extension.yaml
  3. Verify that the extension is deleted.
    kubectl get app contour -n tanzu-system-ingress

    Expected result: The app is Not Found.

  4. Delete the namespace.
    Only after you have confirmed that the Contour extension and app are fully deleted is safe to delete the namespace and role objects.
    kubectl delete -f namespace-role.yaml
    Expected result: The namespace where the extension is deployed, and the associated role-based access control objects, are deleted.

Configure the External DNS Extension

You can configure the External DNS extension with custom settings.

Configure the deployment parameters for your External DNS provider. Refer to the Kubernetes site https://github.com/kubernetes-sigs/external-dns#running-externaldns for additional guidance.
Table 1. Harbor Extension Configuration Parameters
Parameter Description Type Default
externalDns.namespace Namespace where external-dns will be deployed string tanzu-system-service-discovery
externalDns.image.repository Repository containing external-dns image string projects.registry.vmware.com/tkg
externalDns.image.name Name of external-dns string external-dns
externalDns.image.tag ExternalDNS image tag string v0.7.4_vmware.1
externalDns.image.pullPolicy ExternalDNS image pull policy string IfNotPresent
externalDns.deployment.annotations Annotations on the external-dns deployment map<string,string> {}
externalDns.deployment.args Arguments passed via command-line to external-dns list<string> [] ( Mandatory parameter )
externalDns.deployment.env Environment variables to pass to external-dns list<string> []
externalDns.deployment.securityContext Security context of the external-dns container SecurityContext {}
externalDns.deployment.volumeMounts Volume mounts of the external-dns container list<VolumeMount> []
externalDns.deployment.volumes Volumes of the external-dns pod list<Volume> []