Skip to main content

Install ExternalDNS

This topic describes installing ExternalDNS on a supported Kubernetes cluster. This topic assumes you have already retrieved or know how to retrieve the API keys for your DNS provider. If you have yet to retrieve these keys, follow the provider-specific instructions in DNS Providers.

Create a Namespace

Create the external-dns namespace in which our ExternalDNS instance(s) will live using the following command:

kubectl create ns external-dns

Switch the context to the newly created external-dns namespace using the following command:

kubens external-dns

ExternalDNS Configuration Parameters

The following parameters are used to configure ExternalDNS as described in the ExternalDNS YAML file.

Parameters with the ServiceAccount Object Schema

ParameterParameter TypeDescriptionRequired
apiVersionStringThe RBAC API version. The value must be rbac.authorization.k8s.io/v1.Mandatory
kindStringThe name of a particular object schema. The value must be ServiceAccount.Mandatory
metadataObjectThe metadata describes the parameters (names and types) and attributes that have been applied.Mandatory

Metadata Parameters with the ServiceAccount Object Schema

ParameterParameter TypeDescriptionRequired
nameStringThe name of the Service Account that you define.Mandatory

Parameters with the ClusterRole Object Schema

The following parameters are used to configure ExternalDNS ClusterRole object as described in the ExternalDNS YAML file.

ParameterParameter TypeDescriptionRequired
apiVersionStringThe RBAC API version. The value must be rbac.authorization.k8s.io/v1.Mandatory
kindStringThe name of a particular object schema. The value must be ClusterRole.Mandatory
metadataObjectThe metadata describes the parameters (names and types) and attributes that have been applied.Mandatory
rulesObjectThis parameter holds information that describes a policy rule. It does not contain information about who the rule applies to or which namespace the rule applies to.Mandatory

Metadata Parameters with the ClusterRole Object Schema

ParameterParameter TypeDescriptionRequired
nameStringThe name of the role that you define.Mandatory

Rules Parameters with the ClusterRole Object Schema

ParameterParameter TypeDescriptionRequired
apiGroupsString ArrayThe name of the API group that contains the resources. If multiple API groups are specified, an action requested against one of the resources in any API group is allowed. You must not add an asterisk * to represent all API groups. An empty apiGroup represents the core API group.Mandatory
resourcesString ArrayThis contains an array of optional list of names that the rule applies to. An empty set means that all resources are allowed.Mandatory
verbsString ArrayA list of verbs that apply to all the resource types contained in this rule. * represents all verbs that apply to the resource types.Mandatory

Parameters with the ClusterRoleBinding Object Schema

The following parameters are used to configure ExternalDNS ClusterRoleBinding object as described in the ExternalDNS YAML file.

ParameterParameter TypeDescriptionRequired
apiVersionStringThe RBAC API version. The value must be rbac.authorization.k8s.io/v1.Mandatory
kindStringThe name of a particular object schema. The value must be ClusterRole.Mandatory
metadataObjectThe metadata describes the parameters (names and types) and attributes that have been applied.Mandatory
roleRefsObjectThis a reference to the role being granted.Mandatory
subjectsObjectThe name of the resource and schema to which the role is applied. For each namespace, the subjects must be added separately in an array.Mandatory

Metadata Parameters with the ClusterRoleBinding Object Schema

ParameterParameter TypeDescriptionRequired
nameStringThe name of the role that you define.Mandatory

Role Reference Parameters with the ClusterRoleBinding Object Schema

ParameterParameter TypeDescriptionRequired
apiVersionStringThe KubeSlice Controller API version. A set of resources that are exposed together, along with the version. The value must be rbac.authorization.k8s.io/v1 for Kubernetes (K8s) roles.Mandatory
kindStringThe kind of the role that is being referenced. The value must be ClusterRole for a Kubernetes (K8s) role.Mandatory
nameStringThe name of the role that you assign to the slice and namespaces onboarded onto that slice.Mandatory

Subjects Parameters with the ClusterRoleBinding Object Schema

ParameterParameter TypeDescriptionRequired
kindStringThe type of the resource for which you assign the role. For example, the kind is a User, ServiceAccount, or a Group.Mandatory
nameStringThe name of the resource to which the role is applied.Mandatory
namespaceStringThe namespace that contains the resource to which the role is appliedMandatory

Parameters with the Deployment Object Schema

The following parameters are used to configure ExternalDNS Deployment object as described in the ExternalDNS YAML file.

ParameterParameter TypeDescriptionRequired
apiVersionStringThe RBAC API version. The value must be rbac.authorization.k8s.io/v1.Mandatory
kindStringThe name of a particular object schema. The value must be ClusterRole.Mandatory
metadataObjectThe metadata describes the parameters (names and types) and attributes that have been applied.Mandatory
specObjectThe specification of the desired state of an object.Mandatory

Metadata Parameters with the Deployment Object Schema

ParameterParameter TypeDescriptionRequired
nameStringThe name of the role that you define.Mandatory

Spec Parameters with the Deployment Object Schema

ParameterParameter TypeDescriptionRequired
strategyObjectDetermine how Kubernetes should handle deployment specification changes or deployment recreation.Mandatory
selectorObjectDefine the labels to match to identify pods belonging to the deployment.Mandatory
templateObjectDefine the pod definition and spec.Mandatory

Spec Strategy Parameters

ParameterParameter TypeDescriptionRequired
typeStringWhat type of recreate strategy which should be used.Mandatory

Spec Selector Parameters

ParameterParameter TypeDescriptionRequired
matchLabelsObjectDefine the labels to match to identify pods belonging to the deployment.Mandatory

Selector Match Labels Parameters

ParameterParameter TypeDescriptionRequired
appStringThe key value selector pair for the deployment.Mandatory

Spec Template Parameters

ParameterParameter TypeDescriptionRequired
metadataObjectMandatory
specThe pod definition to use when recreating pods or identifying pods associated with the deployment.ObjectMandatory

Template Metadata Parameters

ParameterParameter TypeDescriptionRequired
labelsMetadata contains fields such as an objects name, namespace, or labels.ObjectMandatory

Template Metadata Labels Parameters

ParameterParameter TypeDescriptionRequired
appStringA key value pair denoting what the app variable should be set to. Usually will be dtc-controller.Mandatory

Template Spec Parameters

ParameterParameter TypeDescriptionRequired
serviceAccountNameStringMandatory
containersObjectMandatory

Template Spec Containers Parameters

ParameterParameter TypeDescriptionRequired
nameStringThe name of the ExternalDNS container in the pod. Can be external-dns.Mandatory
imageStringThe Avesha ExternalDNS image.Mandatory
imagePullPolicyStringImage pull policy determines when a new image should be pulled from a Docker repository.Mandatory
argsObjectExternal-DNS supports many arguments. These arguments, like txt-owner-id help us pass essential information to the service.Mandatory
[env]ObjectThese environment variables provide ExternalDNS the API Keys or Credentials to access the DNS provider's API and make changes to DNS records.Mandatory
resourcesObjectThe resources contains the limit object that sets limits for CPU, memory, and pod count.Mandatory

Container args Parameters

ParameterParameter TypeDescriptionRequired
sourceStringThe type of service which ExternalDNS will be advertising with your DNS provider.Mandatory
providerStringThe DNS provider which will be configured with ExternalDNS to advertise your records.Mandatory
txt-owner-idStringA string value which should be unique to each cluster with ExternalDNS installed on it. This is used to designate which cluster a record belongs to at your DNS provider.Mandatory

Container Resources Parameters

ParameterParameter TypeDescriptionRequired
limitsObjectThe section contains the limit object that sets limits for CPU, memory, and pod count.Mandatory
requestsObjectThe section contains the requests object that sets scheduling requirements for CPU, memory, and pod count.Mandatory

Resource Limits Parameters

ParameterParameter TypeDescriptionRequired
cpuStringThe maximum allowable memory usage by the pod.Mandatory
memoryStringThe maximum allowable memory usage by the pod.Mandatory

Resource Requests Parameters

ParameterParameter TypeDescriptionRequired
cpuStringThe minimum amount of CPU which must be available to schedule a pod on a node.Mandatory
memoryStringThe minimum amount of memory which must be available to schedule a pod on a node.Mandatory

Create an ExternalDNS YAML File

info

If you are deploying multiple instances of ExternalDNS on your cluster, you should create a unique name for this deployment rather than the default external-dns. Modify the names with comments next to them if this is your case.

Copy the following configuration into a new descriptively named YAML file, such as gcp-cluster-external-dns.yaml.

note

Take note of the commented sections, this is where we will fill in the configuration for this ExternalDNS instance.

apiVersion: v1
kind: ServiceAccount
metadata:
name: external-dns
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: external-dns
rules:
- apiGroups: [""]
resources: ["services"]
verbs: ["get","watch","list"]
- apiGroups: [""]
resources: ["pods"]
verbs: ["get","watch","list"]
- apiGroups: ["networking","networking.k8s.io"]
resources: ["ingresses"]
verbs: ["get","watch","list"]
- apiGroups: [""]
resources: ["nodes"]
verbs: ["get","watch","list"]
- apiGroups: [""]
resources: ["endpoints"]
verbs: ["get","watch","list"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: external-dns-viewer
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: external-dns
subjects:
- kind: ServiceAccount
name: external-dns
namespace: external-dns
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: external-dns # Optional: Change Deployment Name
spec:
strategy:
type: Recreate
selector:
matchLabels:
app: external-dns # Optional: Change Deployment Name
template:
metadata:
labels:
app: external-dns # Optional: Change Deployment Name
spec:
serviceAccountName: external-dns
containers:
- name: external-dns
image: aveshasystems/external-dns:0.13.1
imagePullPolicy: Always
args:
- --source= # external-dns Source
- --provider= # Required: DNS Provider
- --txt-owner-id= # Required: Unique Cluster ID
env:
- name: EXTERNAL_DNS_DOMAIN_FILTER # Optional: Domain Filter, Required if using multiple ExternalDNS instances
value: |-
allowed-domain1.com # Update or Remove
allowed-domain2.com # Update or Remove
# Required: Provider-Specific Environment Variables
resources:
requests:
cpu: 20m
memory: 32Mi
limits:
cpu: 50m
memory: 64Mi

args Section

We will now address each place where user input is required, starting with the source section. This will be one of two options, service or ingress.

Your args section should now reflect something like this (one of the two options):

args:
- --source=service|ingress

The provider is chosen, likely either stackpath or ns1, which is reflected as shown below.

args:
- --source=service
- --provider=stackpath|ns1

The txt-owner-id should be unique across all clusters to each individual instance of ExternalDNS. This would look like the properties below.

args:
- --source=service
- --provider=stackpath
- --txt-owner-id=cluster-a-1

Prepare the Environment

The EXTERNAL_DNS_DOMAIN_FILTER specifies what hostnames this external-DNS-based GLB instance should be looking for. The domain(s) listed are the domains allowed. You may add multiple domains to the ExternalDNS domain filter as shown below.

env:
- name: EXTERNAL_DNS_DOMAIN_FILTER # Optional: Domain Filter, Required if using multiple ExternalDNS instances
value: |-
allowed-domain1.com # Update or Remove
allowed-domain2.com # Update or Remove

The env section also will contain the authentication details for your chosen DNS provider, which should look like one of the below. If you have yet to retrieve your API Keys, go to the DNS Providers page.

NS1 Environment

NS1 Environment Configuration Parameters

The following parameters are used to configure the NS1 environment.

ParameterParameter TypeDescriptionRequired
envObjectThis object contains the name and value of the StackPath environment.Mandatory

NS1 Environment Object Parameters

ParameterParameter TypeDescriptionRequired
nameStringThe parameter name of the ExternalDNS domain filter called EXTERNAL_DNS_DOMAIN_FILTER.Mandatory
valueStringThe value of the ExternalDNS domain filter.Mandatory
nameStringThe unique identifier name of the NS1 provider called NS1_APIKEY.Mandatory
valueStringThe value of the NS1 provider API key.Mandatory

NS1 Environment YAML File

env:
- name: EXTERNAL_DNS_DOMAIN_FILTER
value: |-
allowed-domain1.com
- name: NS1_APIKEY
value: ns1_api_key

StackPath Environment

The following parameters are used to configure the StackPath environment.

ParameterParameter TypeDescriptionRequired
envObjectThis object contains the name and value of the StackPath environment.Mandatory

StackPath Environment Object Parameters

ParameterParameter TypeDescriptionRequired
nameStringThe parameter name of the ExternalDNS domain filter called EXTERNAL_DNS_DOMAIN_FILTER.Mandatory
valueStringThe value of the ExternalDNS domain filter.Mandatory
nameStringThe unique identifier name of the StackPath called STACKPATH_STACK_ID.Mandatory
valueStringThe unique identifier value of STACKPATH_STACK_ID.Mandatory
nameStringThe parameter name of the StackPath client ID called STACKPATH_CLIENT_ID.Mandatory
valueStringThe value of the StackPath client ID.Mandatory
nameStringThe parameter name of the StackPath client secret called STACKPATH_CLIENT_SECRET.Mandatory
valueStringThe value of the StackPath client secret.Mandatory

StackPath Environment YAML File

env:
- name: EXTERNAL_DNS_DOMAIN_FILTER
value: |-
allowed-domain1.com
- name: STACKPATH_STACK_ID
value: your_stack_id
- name: STACKPATH_CLIENT_ID
value: your_client_id
- name: STACKPATH_CLIENT_SECRET
value: your_client_secret

Install ExternalDNS

To install:

  1. Ensure that you are in your external-dns namespace using the following command:

    kubens external-dns
  2. Apply the configured YAML file for the ExternalDNS using the following command:

    kubectl apply -f <configuration>.yaml
  3. Wait for a few seconds.

  4. Verify your installation using the following command:

    kubectl get all -n external-dns

    Expected Output

    NAME                                    READY   STATUS    RESTARTS   AGE
    pod/external-dns-ns1-586b858949-8mk84 1/1 Running 0 18s

    NAME READY UP-TO-DATE AVAILABLE AGE
    deployment.apps/external-dns-ns1 1/1 1 1 18s

    NAME DESIRED CURRENT READY AGE
    replicaset.apps/external-dns-ns1-586b858949 1 1 1 18s
  5. To view the live logs for GTB, use the following command:

    kubectl logs -f <external-dns-pod-name>

    Expected Output

    time="2022-09-14T16:41:31Z" level=info msg="config: {APIServerURL: KubeConfig: RequestTimeout:30s DefaultTargets:[] ContourLoadBalancerService:heptio-contour/contour GlooNamespace:gloo-system SkipperRouteGroupVersion:zalando.org/v1 Sources:[service] Namespace: AnnotationFilter: LabelFilter: FQDNTemplate: CombineFQDNAndAnnotation:false IgnoreHostnameAnnotation:false IgnoreIngressTLSSpec:false IgnoreIngressRulesSpec:false GatewayNamespace: GatewayLabelFilter: Compatibility: PublishInternal:false PublishHostIP:false AlwaysPublishNotReadyAddresses:false ConnectorSourceServer:localhost:8080 Provider:ns1 GoogleProject: GoogleBatchChangeSize:1000 GoogleBatchChangeInterval:1s GoogleZoneVisibility: DomainFilter:[wmar.io] ExcludeDomains:[] RegexDomainFilter: RegexDomainExclusion: ZoneNameFilter:[] ZoneIDFilter:[] AlibabaCloudConfigFile:/etc/kubernetes/alibaba-cloud.json AlibabaCloudZoneType: AWSZoneType: AWSZoneTagFilter:[] AWSAssumeRole: AWSBatchChangeSize:1000 AWSBatchChangeInterval:1s AWSEvaluateTargetHealth:true AWSAPIRetries:3 AWSPreferCNAME:false AWSZoneCacheDuration:0s AWSSDServiceCleanup:false AzureConfigFile:/etc/kubernetes/azure.json AzureResourceGroup: AzureSubscriptionID: AzureUserAssignedIdentityClientID: BluecatDNSConfiguration: BluecatConfigFile:/etc/kubernetes/bluecat.json BluecatDNSView: BluecatGatewayHost: BluecatRootZone: BluecatDNSServerName: BluecatDNSDeployType:no-deploy BluecatSkipTLSVerify:false CloudflareProxied:false CloudflareZonesPerPage:50 CoreDNSPrefix:/skydns/ RcodezeroTXTEncrypt:false AkamaiServiceConsumerDomain: AkamaiClientToken: AkamaiClientSecret: AkamaiAccessToken: AkamaiEdgercPath: AkamaiEdgercSection: InfobloxGridHost: InfobloxWapiPort:443 InfobloxWapiUsername:admin InfobloxWapiPassword: InfobloxWapiVersion:2.3.1 InfobloxSSLVerify:true InfobloxView: InfobloxMaxResults:0 InfobloxFQDNRegEx: InfobloxCreatePTR:false InfobloxCacheDuration:0 DynCustomerName: DynUsername: DynPassword: DynMinTTLSeconds:0 OCIConfigFile:/etc/kubernetes/oci.yaml InMemoryZones:[] OVHEndpoint:ovh-eu OVHApiRateLimit:20 PDNSServer:http://localhost:8081 PDNSAPIKey: PDNSTLSEnabled:false TLSCA: TLSClientCert: TLSClientCertKey: Policy:sync Registry:txt TXTOwnerID:kind-ns1 TXTPrefix: TXTSuffix: Interval:1m0s MinEventSyncInterval:5s Once:false DryRun:false UpdateEvents:false LogFormat:text MetricsAddress::7979 LogLevel:info TXTCacheInterval:0s TXTWildcardReplacement: ExoscaleEndpoint:https://api.exoscale.ch/dns ExoscaleAPIKey: ExoscaleAPISecret: CRDSourceAPIVersion:externaldns.k8s.io/v1alpha1 CRDSourceKind:DNSEndpoint ServiceTypeFilter:[] CFAPIEndpoint: CFUsername: CFPassword: RFC2136Host: RFC2136Port:0 RFC2136Zone: RFC2136Insecure:false RFC2136GSSTSIG:false RFC2136KerberosRealm: RFC2136KerberosUsername: RFC2136KerberosPassword: RFC2136TSIGKeyName: RFC2136TSIGSecret: RFC2136TSIGSecretAlg: RFC2136TAXFR:false RFC2136MinTTL:0s RFC2136BatchChangeSize:50 NS1Endpoint: NS1IgnoreSSL:false NS1MinTTLSeconds:0 TransIPAccountName: TransIPPrivateKeyFile: DigitalOceanAPIPageSize:50 ManagedDNSRecordTypes:[A CNAME] GoDaddyAPIKey: GoDaddySecretKey: GoDaddyTTL:0 GoDaddyOTE:false OCPRouterName: IBMCloudProxied:false IBMCloudConfigFile:/etc/kubernetes/ibmcloud.json}"
    time="2022-09-14T16:41:31Z" level=info msg="Instantiating new Kubernetes client"
    time="2022-09-14T16:41:31Z" level=info msg="Using inCluster-config based on service account-token"
    time="2022-09-14T16:41:31Z" level=info msg="Created Kubernetes client https://10.96.0.1:443"
    time="2022-09-14T16:41:40Z" level=info msg="[]"
    time="2022-09-14T16:41:40Z" level=info msg="All records are already up to date"