VK Cloud logo
Updated at April 18, 2024   05:12 PM

Installing and using ExternalDNS

ExternalDNS allows you to automate DNS record management when working with the Ingress or Service resources. If these resources are configured according to ExternalDNS requirements, they will be accessible by their domain names as soon as they are created.

ExternalDNS integrates with the VK Cloud DNS service via a plugin. Below is an example of installing ExternalDNS to a cluster and using this tool with the Ingress and Service resources.

Preparatory steps

  1. Create a DNS zone for ExternalDNS to work with, if not already done.

    In the example below, the example.com zone is used.

  2. Create a Cloud Containers cluster of the latest version that has an external IP address and is accessible from the Internet.

    Select other cluster parameters at your discretion.

  3. Make sure that you can connect to the cluster using kubectl.

    To connect, use the cluster configuration file (kubeconfig) downloaded from your VK Cloud personal account.

  4. Install Helm version 3.0.0 or higher if the utility is not already installed.

    To install, select a version of Helm that is compatible with the cluster.

  5. Set an environment variable that points to kubeconfig for the cluster. This will make it easier to work with the kubectl and helm utilities when installing ExternalDNS.

    The path to your kubeconfig file may differ from the example below.

    export KUBECONFIG="/home/user/.kube/kubernetes-cluster-1234_kubeconfig.yaml"

1. Prepare a user for ExternalDNS

ExternalDNS will use this VK Cloud user's credentials to cooperate with the VK Cloud API and manage DNS resource records.

Prepare the user and get all the necessary credentials:

  1. Select an existing user or invite a new user to the project.

    User Requirements:

    • API access must be enabled.

    • One of the following roles must be assigned in order for ExternalDNS to operate resource records within the DNS zone:

      • Network Administrator (a minimum required role).
      • Project Administrator.
      • Superadministrator.
      • Project Owner.
  2. Get the credentials you need to access the VK Cloud API:

    1. Go to your VK Cloud personal account using the credentials of the user assigned to ExternalDNS.

    2. Click the username in the page header and select Project Settings.

    3. Go to the API access tab and note the values of the following parameters:

      • Project ID (Project ID for OpenStack);
      • User Domain Name;
      • Username;
      • Region Name;
      • Auth URL (Authentication URL).
  3. Write down the password for this user: it is also required to access the API.

2. Install ExternalDNS

  1. Create a namespace where ExternalDNS will be installed:

    kubectl create ns external-dns
  2. In this namespace, create a secret that contains the VK Cloud API access credentials obtained during user preparation:

    kubectl -n external-dns create secret generic vkcs-auth \  --from-literal=ProjectID="<Project ID>" \  --from-literal=UserDomainName="<User Domain Name>" \  --from-literal=Username="<Username>" \  --from-literal=RegionName="<Region Name>" \  --from-literal=AuthURL="<Auth URL>" \  --from-literal=Password="<User Password>"
  3. Add the Bitnami Helm repository:

    helm repo add bitnami https://charts.bitnami.com/bitnami
  4. Create a file that contains the values needed to install ExternalDNS with Helm:

    The behavior of the ExternalDNS Helm chart is influenced by many values. The created file contains a minimum set of values that is sufficient to start working with ExternalDNS. The most important values affecting the behavior of ExternalDNS with the VK Cloud DNS are described below. Descriptions of values that do not apply to the VK Cloud plugin (all values except sidecars[]) are given in README.md for the chart.

    The plugin for ExternalDNS, which provides its integration with the VK Cloud DNS, has many settings that affect the plugin's behavior. The settings are set using environment variables in sidecars[].env. In the created file, only the required settings are set. If necessary, you can specify additional settings for the plugin by adding the appropriate environment variables.

  5. Install ExternalDNS:

    helm -n external-dns install external-dns-vkcs bitnami/external-dns -f external-dns-vkcs-values.yaml
  6. Verify that the Helm chart has been successfully deployed:

    helm -n external-dns list && kubectl -n external-dns get all

3. Verify that External DNS is working

Next, several demo applications based on NGINX's Cafe example will be deployed. These applications will be published (made available from the Internet) using Service and Ingress configured to work with ExternalDNS.

3.1. Publish the application using a service like LoadBalancer

  1. Create a manifest for the tea application:

  2. Apply this manifest to the cluster to deploy the application:

    kubectl apply -f tea-app.yaml
  3. Verify that the application has been successfully deployed as a ReplicaSet of three replicas:

    kubectl get rs,pod -l app==tea
  4. Create a tea-service.yaml manifest for the Kubernetes service (Service).

    This service will be used to publish the deployed application. The application will be accessible by the domain name tea.example.com.

    To have ExternalDNS create resource records for the service:

    • The external-dns.alpha.kubernetes.io/hostname annotation must be set for the service.
    • The service must have the LoadBalancer type.

    Specify the external-dns.alpha.kubernetes.io/ttl annotation if you want to set a non-standard TTL for resource records (default: 86400 seconds, 24 hours).

    apiVersion: v1kind: Servicemetadata:  annotations:    external-dns.alpha.kubernetes.io/hostname: "tea.example.com"    external-dns.alpha.kubernetes.io/ttl: "3600"  name: tea-svc  labels:    app: teaspec:  type: LoadBalancer  ports:  - port: 80    targetPort: 8080    protocol: TCP    name: http  selector:    app: tea

    Here:

    • The required external-dns.alpha.kubernetes.io/hostname annotation is specified: the domain name to use for the service.

    • The optional external-dns.alpha.kubernetes.io/ttl annotation is specified: TTL in seconds for the resource record to be created by ExternalDNS.

    • The LoadBalancer service type is selected. A standard load balancer will be created for such a service. Since the load balancer is created with a public IP address, the application associated with the service will be accessible from the Internet.

  5. Apply this manifest to the cluster to create the service:

    kubectl apply -f tea-service.yaml
  6. Check the status of the service:

    kubectl get svc tea-svc

    Wait until the service is assigned the public IP address of the load balancer. Creating the load balancer can take a long time.

  7. Verify that ExternalDNS has created the necessary resource records:

    1. Get a list of resource records for the example.com zone.

    2. Find the entries created by ExternalDNS in the list:

      • One A record tea.example.com.

      • Two TXT records externaldns-tea.example.com and externaldns-a-tea.example.com.

        These TXT records are service records used by ExternalDNS to track the status of the tea-svc A record created for the tea-svc service.

      If the desired resource records are not present, wait a few more minutes. ExternalDNS will start creating resource records after the service has been assigned an IP address. This will take some time.

  8. Check that the application is accessible by domain name. To do this, go to http://tea.example.com in your browser.

    You should see a page with a response from the application like this:

    Server address: 10.100.184.219:8080Server name: tea-XXXXXXXXX-AAAAADate: 09/Feb/2024:10:09:51 +0000URI: /Request ID: <unique request identifier>

    Successful interaction with the application at this address indicates that ExternalDNS works correctly with a service like LoadBalancer.

3.2. Publish the application using Ingress

  1. Install the Ingress NGINX addon of the latest version to the cluster.

    Perform a standard installation. Do not change any parameters, only edit the addon configuration code:

    1. Make sure that the service.beta.kubernetes.io/openstack-internal-load-balancer annotation is set to false:

      controller:  ...  service:    annotations: {"loadbalancer.openstack.org/proxy-protocol": "true", "service.beta.kubernetes.io/openstack-internal-load-balancer": "false"}    ...

      This is necessary to create a load balancer with a public IP address for the Ingress controller. Then the application using Ingress will be accessible from the Internet.

    2. Set the controller.publishService.enabled field to true:

      controller:  ...  publishService:    enabled: true    pathOverride: ""    ...

      This is necessary to assign a public IP address of the Ingress controller to the Ingress resource. This will allow ExternalDNS to create the correct resource records for Ingress.

    Wait for the addon installation to complete. This process may take a long time.

  2. Create a manifest for the coffee application:

  3. Create a manifest for the Kubernetes service that the application will use.

    Here, the service type is set to ClusterIP, which is sufficient since the application will be published using Ingress. Such a service is accessible only from within the cluster and does not have a dedicated load balancer, unlike the service created earlier.

  4. Apply these manifests to the cluster to create all necessary resources:

    kubectl apply -f coffee-app.yaml -f coffee-service.yaml
  5. Check that the application has been successfully deployed as a ReplicaSet of two replicas along with the corresponding service:

    kubectl get rs,pod,svc -l app==coffee
  6. Create the cafe-ingress.yaml manifest for the Ingress resource.

    This Ingress resource will be used to publish the deployed application. The application will be available on the cafe.example.com domain at the http://cafe.example.com/coffee URL.

    For ExternalDNS to create resource records for the service, no additional values need to be specified in the manifest: having an Ingress controller configured in the right way is sufficient. The domain name values will be taken from the host fields for the Ingress spec.rules[] rules.

    Specify the external-dns.alpha.kubernetes.io/ttl annotation if you want to set a non-standard TTL for resource records (default: 86400 seconds, 24 hours).

    apiVersion: networking.k8s.io/v1kind: Ingressmetadata:  name: cafe-ingress  annotations:    external-dns.alpha.kubernetes.io/ttl: "3600"spec:  ingressClassName: nginx  rules:  - host: cafe.example.com    http:      paths:      - path: /coffee        pathType: Prefix        backend:          service:            name: coffee-svc            port:              number: 80

    Here:

    • The optional external-dns.alpha.kubernetes.io/ttl annotation is specified: TTL in seconds for the resource records to be created by ExternalDNS.
    • The cafe.example.com host for the Ingress rule is specified. Since only one host is specified, one resource record will be created for this domain name.
    • According to the Ingress rule, the coffee application that is behind the coffee-svc service will be accessible at the URL http://cafe.example.com/coffee.
  7. Apply this manifest to the cluster to create the resource:

    kubectl apply -f cafe-ingress.yaml
  8. Check the status of Ingress:

    kubectl get ingress cafe-ingress

    Wait for the Ingress resource to be assigned a public IP address. This address will be the same as the address of the Ingress controller.

  9. Verify that ExternalDNS has created the necessary resource records:

    1. Get a list of resource records for the example.com zone.

    2. Find the entries created by ExternalDNS in the list:

      • One CNAME record cafe.example.com.

      • Two TXT records externaldns-cafe.example.com and externaldns-cname-cafe.example.com.

        These TXT records are service records used by ExternalDNS to track the status of the cafe-ingress CNAME record created for Ingress.

      If the desired resource records are not present, wait a few more minutes. ExternalDNS will begin creating resource records after the Ingress resource has been assigned an IP address. This will take some time.

  10. Verify that the application is accessible by domain name. To do this, go to http://cafe.example.com/coffee in your browser.

A page should open with a response from the application like:

Server address: 10.100.184.220:8080Server name: coffee-YYYYYYYYY-DDDDDDate: 09/Feb/2024:13:07:11 +0000URI: /coffeeRequest ID: <unique request identifier>

Successful interaction with the application at this address indicates that ExternalDNS works correctly with the Ingress resource.

Remove unused resources

  1. If you no longer need the Kubernetes resources created for ExternalDNS validation, delete them:

    1. Delete all resources associated with the tea application:

      kubectl delete -f cafe-ingress.yaml -f coffee-service.yaml -f coffee-app.yaml

      It can take a long time to remove the load balancer associated with the service.

    2. Remove all resources associated with the coffee application:

      kubectl delete -f tea-service.yaml -f tea-app.yaml
    3. Delete the Ingress NGINX addon.

      It may take a long time to remove the addon and its associated resources.

    4. Delete the resource records created by ExternalDNS.

      This must be done if you did not modify the external-dns-vkcs-values.yaml file when installing ExternalDNS: in this case ExternalDNS uses the upsert-only policy and does not remove resource records from the DNS zone when removing Kubernetes resources. If you modified this file and selected the sync policy, then these records will be deleted automatically.

      List of resource records:

      • A record tea.example.com.
      • TXT records externaldns-tea.example.com and externaldns-a-tea.example.com.
      • CNAME record cafe.example.com.
      • TXT records externaldns-cafe.example.com and externaldns-cname-cafe.example.com.
  2. If you no longer need ExternalDNS, delete it:

    1. Remove the Helm chart from ExternalDNS:

      helm -n external-dns uninstall external-dns-vkcs
    2. Remove the external-dns namespace.

      kubectl delete ns external-dns
  3. A running Cloud Containers cluster consumes compute resources and is charged. If you no longer need it:

  4. Delete the example.com DNS zone if you no longer need it.