External DNS use cases

Prev Next

Available in VPC

You can use ExternalDNS in Ncloud Kubernetes Service (NKS) to synchronize Kubernetes resources with records in the Global DNS service.

Before use

Before proceeding with the ExternalDNS use cases, check the following supported scope and prerequisites.

Item Supported Scope
Environment VPC
Kubernetes(NKS Add-on) 1.36.2 or later
Kubernetes (manual installation using Helm) 1.33 or higher
ExternalDNS 0.21.0
Supported resources Service, Ingress, DNSEndpoint
Supported record types A, AAAA, CNAME, MX, TXT
Authentication method NKS Node IAM Role or Sub Account access key

The record types managed by ExternalDNS and their management conditions are as follows.

Record type Management condition
A, AAAA, CNAME Managed by default
MX, custom TXT Managed only when added to managedRecordTypes during manual installation using Helm (not supported by the NKS add-on)
TXT for ownership verification Automatically created according to the registry: txt setting (regardless of the managed record type)

Prepare the following in advance.

  • Ncloud Kubernetes Service cluster
  • kubeconfig that can be used with kubectl
  • Helm 3 (for manual installation)
  • Domain registered with the Global DNS service
  • Permissions to view domains, view/create/modify/delete records, and apply changes

The values used during installation are as follows.

Input value Description Example
<KUBE_CONTEXT> kubeconfig context where ExternalDNS will be installed nks_kr_cluster_example
<DNS_ZONE> Domain registered with the Global DNS service to be managed example.com
<DNS_BASE_URL> Environment-specific Global DNS OpenAPI endpoint for manual installation https://globaldns.apigw.ntruss.com/dns/v1
<WEBHOOK_IMAGE_TAG> Fixed release tag of the webhook image for manual installation v1.0.0
<TXT_OWNER_ID> Unique value used to identify a manually installed ExternalDNS instance nks-cluster-a
<INGRESS_CLASS> Ingress Class used by the cluster alb
<NODE_LABEL_KEY> Label key of the node pool associated with the Node IAM Role ncloud.com/nks-nodepool
<NODE_LABEL_VALUE> Label value of the node pool associated with the Node IAM Role pool2

If possible, use a separate Global DNS domain or delegated subdomain for each cluster. If multiple clusters must share the same domain, use a unique <TXT_OWNER_ID> for each cluster and configure them to avoid managing the same host names. The NKS add-on uses the cluster UUID as the default value for txtOwnerId.
Run the following command to check the kubeconfig context and Ingress Class.

kubectl --context "<KUBE_CONTEXT>" cluster-info
kubectl --context "<KUBE_CONTEXT>" get ingressclass

Prepare Global DNS domain

Register the domain to be managed by ExternalDNS with the Global DNS service.

For example, if example.com is specified as the managed domain, records for subhosts such as app.example.com can be created.
To resolve records through public DNS, configure the Global DNS name server information with your domain registrar.

Note

If the host name specified in a Kubernetes resource is not included in a domain registered with Global DNS, no DNS record is created and a warning is logged.

Prepare authentication credentials

The webhook provider supports NKS Node IAM Role and Sub Account access keys. If both authentication methods are configured, the Sub Account access key takes precedence.

Use NKS Node IAM Role

With NKS Node IAM Role, you do not need to store long-term access keys in a Kubernetes Secret. Prepare the role as follows.

  1. See Create role and create a Server-type Sub Account role.
  2. Add permissions to manage Global DNS domains and records to the role.
  3. When creating a node pool, select the role as the Node IAM Role.
  4. Check the node labels and taints to ensure that the ExternalDNS pod is scheduled on the node pool.
Note

For details about configuring Node IAM Role, see the Node IAM Role use cases.

To allow all Global DNS features, you can use the NCP_GLOBAL_DNS_MANAGER system-managed policies. If you use user-defined policies with minimum permissions, select the following actions.

Permission type Actions to select
Read permissions getDomainList, getRecordList
Change permissions createRecord, updateRecord, deleteRecord, applyRecordConfig

Sub Account automatically adds getDomainDetail and getRecordDetail, which are required by the actions above, as related actions. Do not deselect the automatically added related actions. getDomainMonitor, downloadRecordList, createDomain, uploadZonefile, deleteDomain, and changeDNSSECstatus are not required.

For details, see Global DNS permissions management.

Use Sub Account access key

When using a Sub Account access key, create a Secret containing the credentials in the namespace where the ExternalDNS pod runs.
The NKS add-on is installed in the kube-system namespace. When installing the add-on on an existing cluster, run the following command to create the Secret first.

kubectl --context "<KUBE_CONTEXT>" --namespace kube-system \
  create secret generic ncloud-credentials \
  --from-literal=access-key="<NCLOUD_ACCESS_KEY>" \
  --from-literal=secret-key="<NCLOUD_SECRET_KEY>"

Enter ncloud-credentials for credentials.secretName in the add-on settings.

When installing the ExternalDNS add-on during cluster creation, you can enter credentials.secretName in advance. After cluster creation is complete, create the Secret in the kube-system namespace and run the following command to restart the ExternalDNS Deployment.

kubectl --context "<KUBE_CONTEXT>" --namespace kube-system \
  rollout restart deployment/external-dns
kubectl --context "<KUBE_CONTEXT>" --namespace kube-system \
  rollout status deployment/external-dns --timeout=5m

To use a Sub Account access key, enter the Secret name in credentials.secretName in the add-on settings. To use Node IAM Role, leave the value empty. If you change the access key in a Secret with the same name, restart the ExternalDNS Deployment to apply the updated value.

For manual installation using Helm, run the following command to create the external-dns namespace and Secret.

kubectl --context "<KUBE_CONTEXT>" create namespace external-dns
kubectl --context "<KUBE_CONTEXT>" --namespace external-dns \
  create secret generic ncloud-credentials \
  --from-literal=access-key="<NCLOUD_ACCESS_KEY>" \
  --from-literal=secret-key="<NCLOUD_SECRET_KEY>"

Install ExternalDNS

ExternalDNS can be installed using the NKS add-on or Helm.

Installation method Value configuration Management method Recommended use
NKS Add-on NKS automatically injects some values, and you only need to enter the settings provided by the add-on. NKS automatically manages the configuration and version. When operating within the settings supported by NKS
Manual installation using Helm Users configure all values in the ExternalDNS Helm chart. Users manage installation, upgrades, and removal. When you need to configure values not provided by the add-on
Note

Choose only one of the two installation methods. Installing both the add-on and a Helm release in the same cluster may cause conflicts in DNS record ownership.

Install using NKS Add-on

Select and install ExternalDNS using the NKS add-on feature. The add-on installs the ExternalDNS container, the webhook provider for NAVER Cloud Platform, the DNSEndpoint CRD, and the RBAC required for the supported sources service, ingress, and crd.

The add-on automatically injects some values, such as the cluster UUID and the Global DNS OpenAPI endpoint for the environment. You only need to enter the settings provided by the add-on, while NKS automatically manages the add-on configuration and version. If you need to change values not provided by the add-on, see Manual installation using Helm.

The main add-on settings are as follows.

Setting Default Description
domainFilter Empty Global DNS domain to manage. If left empty, all domains accessible with the credentials in use are managed.
sources service, ingress, crd Kubernetes resource types for which DNS records are created.
policy upsert-only Record change policy. Select from sync, upsert-only, and create-only.
annotationFilter Empty Process only resources that match the specified annotation condition.
labelFilter Empty Process only resources that match the specified label condition.
txtPrefix _edns. Prefix for ownership TXT record names.
txtSuffix Empty Suffix for ownership TXT record names.
txtOwnerId Cluster UUID Owner identifier for the ExternalDNS instance.
logLevel info Log level
credentials.secretName Empty Name of the Sub Account access key Secret in the kube-system namespace. Leave empty when using Node IAM Role.
scheduling.nodeSelector Empty Select the node pool associated with the Node IAM Role.
scheduling.extraTolerations Empty Tolerations for the taints of the node pool.
Note

When configuring the settings, note the following.

  • In production environments, we recommend specifying the domains to manage in domainFilter to prevent unintended domains from being included in the management scope.
  • When using Node IAM Role, enter the scheduling.nodeSelector of the node pool associated with the role and the required scheduling.extraTolerations.
  • To delete DNS records when Kubernetes resources are deleted, set policy to sync. The default value, upsert-only, retains DNS records even when resources are deleted.
  • If txtOwnerId is not specified, the cluster UUID is used. Specify the existing owner value only when migrating from an existing ExternalDNS instance.
  • txtPrefix and txtSuffix cannot be configured at the same time. Changing the value of during operation may leave existing ownership TXT records. Do not change it after installation.
  • NKS automatically configures the Global DNS OpenAPI endpoint for the environment, so you do not need to enter dnsBaseUrl when installing the add-on.
  • When the add-on installation status is displayed as normal, proceed to Create Service DNS records.

Manual installation using Helm

If the ExternalDNS add-on is unavailable or custom settings are required, you can manually install ExternalDNS using the official Helm chart. With manual installation, you manage installation, value changes, upgrades, and removal. The ExternalDNS container and the webhook provider for NAVER Cloud Platform are deployed in a single pod.

When using Node IAM Role, run the following command to create the namespace.

kubectl --context "<KUBE_CONTEXT>" create namespace external-dns

Run the following command to add the ExternalDNS Helm repository.

helm repo add external-dns https://kubernetes-sigs.github.io/external-dns/
helm repo update

For manual installation, you must configure the Global DNS OpenAPI endpoint for the environment.

Environment <DNS_BASE_URL>
Private https://globaldns.apigw.ntruss.com/dns/v1
Public https://globaldns.apigw.gov-ntruss.com/dns/v1
Financial https://globaldns.apigw.fin-ntruss.com/dns/v1

Copy the following content and save it as a external-dns-values.yaml file.
Replace <DNS_ZONE>, <DNS_BASE_URL>, <TXT_OWNER_ID>, and <WEBHOOK_IMAGE_TAG> and with the values you prepared.

image:
  tag: v0.21.0
sources:
  - service
  - ingress
  - crd
registry: txt
policy: sync
logLevel: info
txtPrefix: "_edns."
txtOwnerId: "<TXT_OWNER_ID>"
domainFilters:
  - "<DNS_ZONE>"
extraArgs:
  - --webhook-provider-read-timeout=90s
terminationGracePeriodSeconds: 120
provider:
  name: webhook
  webhook:
    image:
      repository: nks.kr.ncr.ntruss.com/nks/external-dns-navercloud-webhook
      tag: "<WEBHOOK_IMAGE_TAG>"
    env:
      - name: DOMAIN_FILTER
        value: "<DNS_ZONE>"
      - name: NCLOUD_DNS_BASE_URL
        value: "<DNS_BASE_URL>"
    livenessProbe:
      httpGet:
        path: /healthz
        port: 8080
      initialDelaySeconds: 5
      periodSeconds: 10
    readinessProbe:
      httpGet:
        path: /healthz
        port: 8080
      initialDelaySeconds: 3
      periodSeconds: 5
Note
  • In this example, sources is set to service, ingress, and crd. For manual installation, you can add or remove resource types as needed.
  • When using crd, do not exclude the DNSEndpoint CRD included in the ExternalDNS Helm chart from the installation.

To manage MX records and TXT records defined directly in Kubernetes resources with a manual installation, add the following values to external-dns-values.yaml.

managedRecordTypes:
  - A
  - AAAA
  - CNAME
  - MX
  - TXT

txtPrefix prevents naming conflicts between CNAME records and ownership TXT records. txtOwnerId distinguishes owners to prevent multiple ExternalDNS instances from modifying the same records.
When using a Sub Account access key, configure provider.webhook.env as follows.

    env:
      - name: DOMAIN_FILTER
        value: "<DNS_ZONE>"
      - name: NCLOUD_DNS_BASE_URL
        value: "<DNS_BASE_URL>"
      - name: NCLOUD_ACCESS_KEY
        valueFrom:
          secretKeyRef:
            name: ncloud-credentials
            key: access-key
      - name: NCLOUD_SECRET_KEY
        valueFrom:
          secretKeyRef:
            name: ncloud-credentials
            key: secret-key

Run the following command to install ExternalDNS.

helm upgrade --install external-dns external-dns/external-dns \
  --kube-context "<KUBE_CONTEXT>" \
  --namespace external-dns \
  --version 1.21.1 \
  --values external-dns-values.yaml

The DNSEndpoint CRD is also installed when the Helm chart is installed. Do not use the --skip-crds option.
Run the following command to check the status of ExternalDNS and the CRD.

kubectl --context "<KUBE_CONTEXT>" --namespace external-dns \
  rollout status deployment/external-dns --timeout=5m
kubectl --context "<KUBE_CONTEXT>" --namespace external-dns get pod
kubectl --context "<KUBE_CONTEXT>" get crd dnsendpoints.externaldns.k8s.io

Run the following command to check the logs of the ExternalDNS container and webhook container.

kubectl --context "<KUBE_CONTEXT>" --namespace external-dns \
  logs deployment/external-dns --all-containers=true --tail=100

You can identify the authentication method used by the webhook provider from the following values in the logs.

  • provider=ServerRoleProvider: Use NKS Node IAM Role
  • provider=EnvProvider: Use Sub Account access key

Create Service DNS records

You can create a DNS record that points to the external address of Service by adding an ExternalDNS annotation to a LoadBalancer type of Service.
The example resources are created in the external-dns namespace. If the namespace does not exist, run the following command to create it.

kubectl --context "<KUBE_CONTEXT>" create namespace external-dns

Copy the following content and save it as a external-dns-service.yaml file. Replace <SERVICE_HOSTNAME> with a host name under <DNS_ZONE>.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: external-dns-nginx
  namespace: external-dns
spec:
  replicas: 1
  selector:
    matchLabels:
      app: external-dns-nginx
  template:
    metadata:
      labels:
        app: external-dns-nginx
    spec:
      containers:
        - name: nginx
          image: nginx:1.27-alpine
          ports:
            - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: external-dns-nginx
  namespace: external-dns
  annotations:
    external-dns.alpha.kubernetes.io/hostname: "<SERVICE_HOSTNAME>"
    external-dns.alpha.kubernetes.io/ttl: "300"
spec:
  type: LoadBalancer
  selector:
    app: external-dns-nginx
  ports:
    - port: 80
      targetPort: 80

Run the following command to create the Deployment and Service and check the external address assignment status.

kubectl --context "<KUBE_CONTEXT>" apply -f external-dns-service.yaml
kubectl --context "<KUBE_CONTEXT>" --namespace external-dns \
  get service external-dns-nginx

After the next synchronization is complete, check that the <SERVICE_HOSTNAME> record for and the ownership TXT record have been created in the Global DNS menu. By default, ExternalDNS synchronizes every minute. It may take several minutes or longer to create a Load Balancer.

Create Ingress DNS records

You can create a DNS record using the external address assigned by the Ingress Controller to Ingress and the host name specified in Ingress. For instructions on installing the Ingress Controller and creating an Ingress, see ALB Ingress Controller use cases.

Copy the following content and save it as a external-dns-ingress.yaml file. Replace <INGRESS_HOSTNAME> with a host name under <DNS_ZONE>.

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: external-dns-ingress
  namespace: external-dns
  annotations:
    external-dns.alpha.kubernetes.io/ttl: "300"
spec:
  ingressClassName: "<INGRESS_CLASS>"
  rules:
    - host: "<INGRESS_HOSTNAME>"
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: external-dns-nginx
                port:
                  number: 80

Run the following command to create Ingress and check the external address assignment status.

kubectl --context "<KUBE_CONTEXT>" apply -f external-dns-ingress.yaml
kubectl --context "<KUBE_CONTEXT>" --namespace external-dns \
  get ingress external-dns-ingress

After the next synchronization is complete, check that the <INGRESS_HOSTNAME> record for and the ownership TXT record have been created in the Global DNS menu.
If the Ingress Controller provides an IP address, an A or AAAA record is created. If it provides a host name, a CNAME record is created.

Create DNS records using DNSEndpoint

With DNSEndpoint, you can define DNS records directly, independently of Service or Ingress.
Copy the following content and save it as a external-dns-crd.yaml file.

Replace <CRD_HOSTNAME> and <IP_ADDRESS> with the host name and IP address to use.

apiVersion: externaldns.k8s.io/v1alpha1
kind: DNSEndpoint
metadata:
  name: external-dns-crd
  namespace: external-dns
spec:
  endpoints:
    - dnsName: "<CRD_HOSTNAME>"
      recordTTL: 300
      recordType: A
      targets:
        - "<IP_ADDRESS>"

Run the following command to create DNSEndpoint and verify that it has been created.

kubectl --context "<KUBE_CONTEXT>" apply -f external-dns-crd.yaml
kubectl --context "<KUBE_CONTEXT>" --namespace external-dns \
  get dnsendpoint external-dns-crd

After the next synchronization is complete, check that the A record for <CRD_HOSTNAME> and the ownership TXT record have been created in the Global DNS menu.

Delete DNS records

This example uses policy: sync, so when Kubernetes resources are deleted, ExternalDNS deletes the managed DNS records and ownership TXT records.
Run the following command to delete the example resources.

kubectl --context "<KUBE_CONTEXT>" delete -f external-dns-crd.yaml
kubectl --context "<KUBE_CONTEXT>" delete -f external-dns-ingress.yaml
kubectl --context "<KUBE_CONTEXT>" delete -f external-dns-service.yaml

After the next synchronization is complete, check that the DNS record for and the ownership TXT record have been deleted in the Global DNS menu.
If you no longer use ExternalDNS, remove it according to the installation method.

  • NKS Add-on: Remove the ExternalDNS add-on from the NKS add-on management interface.
  • Manual installation using Helm: Run the following command to remove the Helm release.
helm uninstall external-dns \
  --kube-context "<KUBE_CONTEXT>" \
  --namespace external-dns

Removing the Helm release does not delete the DNSEndpoint CRD. If the CRD is no longer required, make sure that no DNSEndpoint is in use, and then delete it separately.
If you used a Sub Account access key for manual installation using Helm, make sure that the Secret is not used by other workloads, and then run the following command to delete it.

kubectl --context "<KUBE_CONTEXT>" --namespace external-dns \
  delete secret ncloud-credentials

If you used a Sub Account access key with the add-on, make sure that the Secret is not used by other workloads, and then delete it.

Caution

If you delete ExternalDNS before deleting the Kubernetes resources, the DNS records cannot be cleaned up automatically. Even if policy is set to upsert-only, DNS records are retained and must be deleted manually from the Global DNS service.

Service limits

Note the following restrictions when using ExternalDNS and the webhook provider for NAVER Cloud Platform.

  • Host names for domains that are not registered with the Global DNS service are skipped.
  • If domainFilter is configured in the add-on, or domainFilters and DOMAIN_FILTER are configured for manual installation using Helm, only the specified domains are managed.
  • If Global DNS has pending changes that have not been applied to the name servers, ExternalDNS does not modify records for the domain. Click [Apply settings] > [Deploy] to apply the changes, or click [Cancel changes] to revert them. ExternalDNS resumes processing from the next synchronization.
  • Do not directly modify records for the same domain in the Global DNS console while the webhook provider is running.
  • The default SOA and NS records are not managed.