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:
ExternalDNS Configuration Parameters
The following parameters are used to configure ExternalDNS as described in
the ExternalDNS YAML file.
Parameters with the ServiceAccount Object Schema
Parameter | Parameter Type | Description | Required |
---|
apiVersion | String | The RBAC API version. The value must be rbac.authorization.k8s.io/v1 . | Mandatory |
kind | String | The name of a particular object schema. The value must be ServiceAccount . | Mandatory |
metadata | Object | The metadata describes the parameters (names and types) and attributes that have been applied. | Mandatory |
Parameter | Parameter Type | Description | Required |
---|
name | String | The 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.
Parameter | Parameter Type | Description | Required |
---|
apiVersion | String | The RBAC API version. The value must be rbac.authorization.k8s.io/v1 . | Mandatory |
kind | String | The name of a particular object schema. The value must be ClusterRole . | Mandatory |
metadata | Object | The metadata describes the parameters (names and types) and attributes that have been applied. | Mandatory |
rules | Object | This 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 |
Parameter | Parameter Type | Description | Required |
---|
name | String | The name of the role that you define. | Mandatory |
Rules Parameters with the ClusterRole Object Schema
Parameter | Parameter Type | Description | Required |
---|
apiGroups | String Array | The 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 |
resources | String Array | This contains an array of optional list of names that the rule applies to. An empty set means that all resources are allowed. | Mandatory |
verbs | String Array | A 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.
Parameter | Parameter Type | Description | Required |
---|
apiVersion | String | The RBAC API version. The value must be rbac.authorization.k8s.io/v1 . | Mandatory |
kind | String | The name of a particular object schema. The value must be ClusterRole . | Mandatory |
metadata | Object | The metadata describes the parameters (names and types) and attributes that have been applied. | Mandatory |
roleRefs | Object | This a reference to the role being granted. | Mandatory |
subjects | Object | The 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 |
Parameter | Parameter Type | Description | Required |
---|
name | String | The name of the role that you define. | Mandatory |
Role Reference Parameters with the ClusterRoleBinding Object Schema
Parameter | Parameter Type | Description | Required |
---|
apiVersion | String | The 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 |
kind | String | The kind of the role that is being referenced. The value must be ClusterRole for a Kubernetes (K8s) role. | Mandatory |
name | String | The name of the role that you assign to the slice and namespaces onboarded onto that slice. | Mandatory |
Subjects Parameters with the ClusterRoleBinding Object Schema
Parameter | Parameter Type | Description | Required |
---|
kind | String | The type of the resource for which you assign the role. For example, the kind is a User , ServiceAccount , or a Group . | Mandatory |
name | String | The name of the resource to which the role is applied. | Mandatory |
namespace | String | The namespace that contains the resource to which the role is applied | Mandatory |
Parameters with the Deployment Object Schema
The following parameters are used to configure ExternalDNS Deployment
object as described in
the ExternalDNS YAML file.
Parameter | Parameter Type | Description | Required |
---|
apiVersion | String | The RBAC API version. The value must be rbac.authorization.k8s.io/v1 . | Mandatory |
kind | String | The name of a particular object schema. The value must be ClusterRole . | Mandatory |
metadata | Object | The metadata describes the parameters (names and types) and attributes that have been applied. | Mandatory |
spec | Object | The specification of the desired state of an object. | Mandatory |
Parameter | Parameter Type | Description | Required |
---|
name | String | The name of the role that you define. | Mandatory |
Spec Parameters with the Deployment Object Schema
Parameter | Parameter Type | Description | Required |
---|
strategy | Object | Determine how Kubernetes should handle deployment specification changes or deployment recreation. | Mandatory |
selector | Object | Define the labels to match to identify pods belonging to the deployment. | Mandatory |
template | Object | Define the pod definition and spec. | Mandatory |
Spec Strategy Parameters
Parameter | Parameter Type | Description | Required |
---|
type | String | What type of recreate strategy which should be used. | Mandatory |
Spec Selector Parameters
Parameter | Parameter Type | Description | Required |
---|
matchLabels | Object | Define the labels to match to identify pods belonging to the deployment. | Mandatory |
Selector Match Labels Parameters
Parameter | Parameter Type | Description | Required |
---|
app | String | The key value selector pair for the deployment. | Mandatory |
Spec Template Parameters
Parameter | Parameter Type | Description | Required |
---|
metadata | Object | | Mandatory |
spec | The pod definition to use when recreating pods or identifying pods associated with the deployment. | Object | Mandatory |
Parameter | Parameter Type | Description | Required |
---|
labels | Metadata contains fields such as an objects name, namespace, or labels. | Object | Mandatory |
Parameter | Parameter Type | Description | Required |
---|
app | String | A key value pair denoting what the app variable should be set to. Usually will be dtc-controller . | Mandatory |
Template Spec Parameters
Parameter | Parameter Type | Description | Required |
---|
serviceAccountName | String | | Mandatory |
containers | Object | | Mandatory |
Template Spec Containers Parameters
Parameter | Parameter Type | Description | Required |
---|
name | String | The name of the ExternalDNS container in the pod. Can be external-dns . | Mandatory |
image | String | The Avesha ExternalDNS image. | Mandatory |
imagePullPolicy | String | Image pull policy determines when a new image should be pulled from a Docker repository. | Mandatory |
args | Object | External-DNS supports many arguments. These arguments, like txt-owner-id help us pass essential information to the service. | Mandatory |
[env] | Object | These environment variables provide ExternalDNS the API Keys or Credentials to access the DNS provider's API and make changes to DNS records. | Mandatory |
resources | Object | The resources contains the limit object that sets limits for CPU, memory, and pod count. | Mandatory |
Container args Parameters
Parameter | Parameter Type | Description | Required |
---|
source | String | The type of service which ExternalDNS will be advertising with your DNS provider. | Mandatory |
provider | String | The DNS provider which will be configured with ExternalDNS to advertise your records. | Mandatory |
txt-owner-id | String | A 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
Parameter | Parameter Type | Description | Required |
---|
limits | Object | The section contains the limit object that sets limits for CPU, memory, and pod count. | Mandatory |
requests | Object | The section contains the requests object that sets scheduling requirements for CPU, memory, and pod count. | Mandatory |
Resource Limits Parameters
Parameter | Parameter Type | Description | Required |
---|
cpu | String | The maximum allowable memory usage by the pod. | Mandatory |
memory | String | The maximum allowable memory usage by the pod. | Mandatory |
Resource Requests Parameters
Parameter | Parameter Type | Description | Required |
---|
cpu | String | The minimum amount of CPU which must be available to schedule a pod on a node. | Mandatory |
memory | String | The minimum amount of memory which must be available to schedule a pod on a node. | Mandatory |
Create an ExternalDNS YAML File
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
.
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.
Parameter | Parameter Type | Description | Required |
---|
env | Object | This object contains the name and value of the StackPath environment. | Mandatory |
NS1 Environment Object Parameters
Parameter | Parameter Type | Description | Required |
---|
name | String | The parameter name of the ExternalDNS domain filter called EXTERNAL_DNS_DOMAIN_FILTER . | Mandatory |
value | String | The value of the ExternalDNS domain filter. | Mandatory |
name | String | The unique identifier name of the NS1 provider called NS1_APIKEY . | Mandatory |
value | String | The 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.
Parameter | Parameter Type | Description | Required |
---|
env | Object | This object contains the name and value of the StackPath environment. | Mandatory |
StackPath Environment Object Parameters
Parameter | Parameter Type | Description | Required |
---|
name | String | The parameter name of the ExternalDNS domain filter called EXTERNAL_DNS_DOMAIN_FILTER . | Mandatory |
value | String | The value of the ExternalDNS domain filter. | Mandatory |
name | String | The unique identifier name of the StackPath called STACKPATH_STACK_ID . | Mandatory |
value | String | The unique identifier value of STACKPATH_STACK_ID . | Mandatory |
name | String | The parameter name of the StackPath client ID called STACKPATH_CLIENT_ID . | Mandatory |
value | String | The value of the StackPath client ID. | Mandatory |
name | String | The parameter name of the StackPath client secret called STACKPATH_CLIENT_SECRET . | Mandatory |
value | String | The 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:
Ensure that you are in your external-dns
namespace using the following command:
Apply the configured YAML file for the ExternalDNS using the following command:
kubectl apply -f <configuration>.yaml
Wait for a few seconds.
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
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"