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.
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.
- See Create role and create a Server-type Sub Account role.
- Add permissions to manage Global DNS domains and records to the role.
- When creating a node pool, select the role as the Node IAM Role.
- Check the node labels and taints to ensure that the ExternalDNS pod is scheduled on the node pool.
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 |
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. |
When configuring the settings, note the following.
- In production environments, we recommend specifying the domains to manage in
domainFilterto prevent unintended domains from being included in the management scope. - When using Node IAM Role, enter the
scheduling.nodeSelectorof the node pool associated with the role and the requiredscheduling.extraTolerations. - To delete DNS records when Kubernetes resources are deleted, set
policytosync. The default value,upsert-only, retains DNS records even when resources are deleted. - If
txtOwnerIdis not specified, the cluster UUID is used. Specify the existing owner value only when migrating from an existing ExternalDNS instance. txtPrefixandtxtSuffixcannot 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
dnsBaseUrlwhen 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
- In this example,
sourcesis set toservice,ingress, andcrd. For manual installation, you can add or remove resource types as needed. - When using
crd, do not exclude theDNSEndpointCRD 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 Roleprovider=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.
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
domainFilteris configured in the add-on, ordomainFiltersandDOMAIN_FILTERare 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
SOAandNSrecords are not managed.