This tutorial describes how to setup ExternalDNS for usage within a Kubernetes cluster using UltraDNS.
For this tutorial, please make sure that you are using a version > 0.7.2 of ExternalDNS.
If you would like to read-up on the UltraDNS service, you can find additional details here: Introduction to UltraDNS
Before proceeding, please create a new DNS Zone that you will create your records in for this tutorial process. For the examples in this tutorial, we will be using example.com
as our Zone.
The following environment variables will be needed to run ExternalDNS with UltraDNS.
ULTRADNS_USERNAME
,ULTRADNS_PASSWORD
, &ULTRADNS_BASEURL
ULTRADNS_ACCOUNTNAME
(optional variable).
Connect your kubectl
client to the cluster you want to test ExternalDNS with.
Then, apply one of the following manifests file to deploy ExternalDNS.
- Note: We are assuming the zone is already present within UltraDNS.
- Note: While creating CNAMES as target endpoints, the
--txt-prefix
option is mandatory.
apiVersion: apps/v1
kind: Deployment
metadata:
name: external-dns
spec:
strategy:
type: Recreate
selector:
matchLabels:
app: external-dns
template:
metadata:
labels:
app: external-dns
spec:
containers:
- name: external-dns
image: registry.k8s.io/external-dns/external-dns:v0.15.1
args:
- --source=service
- --source=ingress # ingress is also possible
- --domain-filter=example.com # (Recommended) We recommend to use this filter as it minimize the time to propagate changes, as there are less number of zones to look into..
- --provider=ultradns
- --txt-prefix=txt-
env:
- name: ULTRADNS_USERNAME
value: ""
- name: ULTRADNS_PASSWORD # The password is required to be BASE64 encrypted.
value: ""
- name: ULTRADNS_BASEURL
value: "https://api.ultradns.com/"
- name: ULTRADNS_ACCOUNTNAME
value: ""
apiVersion: v1
kind: ServiceAccount
metadata:
name: external-dns
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: external-dns
rules:
- apiGroups: [""]
resources: ["services","endpoints","pods"]
verbs: ["get","watch","list"]
- apiGroups: ["extensions"]
resources: ["ingresses"]
verbs: ["get","watch","list"]
- apiGroups: [""]
resources: ["nodes"]
verbs: ["list","watch"]
---
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: default
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: external-dns
spec:
strategy:
type: Recreate
selector:
matchLabels:
app: external-dns
template:
metadata:
labels:
app: external-dns
spec:
serviceAccountName: external-dns
containers:
- name: external-dns
image: registry.k8s.io/external-dns/external-dns:v0.15.1
args:
- --source=service
- --source=ingress
- --domain-filter=example.com #(Recommended) We recommend to use this filter as it minimize the time to propagate changes, as there are less number of zones to look into..
- --provider=ultradns
- --txt-prefix=txt-
env:
- name: ULTRADNS_USERNAME
value: ""
- name: ULTRADNS_PASSWORD # The password is required to be BASE64 encrypted.
value: ""
- name: ULTRADNS_BASEURL
value: "https://api.ultradns.com/"
- name: ULTRADNS_ACCOUNTNAME
value: ""
Create a service file called 'nginx.yaml' with the following contents:
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx
spec:
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- image: nginx
name: nginx
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: nginx
annotations:
external-dns.alpha.kubernetes.io/hostname: my-app.example.com.
spec:
selector:
app: nginx
type: LoadBalancer
ports:
- protocol: TCP
port: 80
targetPort: 80
Please note the annotation on the service. Use the same hostname as the UltraDNS zone created above.
ExternalDNS uses this annotation to determine what services should be registered with DNS. Removing the annotation will cause ExternalDNS to remove the corresponding DNS records.
$ kubectl create -f nginx.yaml
$ kubectl create -f external-dns.yaml
Depending on where you run your service from, it can take a few minutes for your cloud provider to create an external IP for the service.
Once the service has an external IP assigned, ExternalDNS will notice the new service IP address and will synchronize the UltraDNS records.
Please verify on the UltraDNS UI that the records are created under the zone "example.com".
For more information on UltraDNS UI, refer to (https://docs.ultradns.com/Content/MSP_User_Guide/Content/User%20Guides/MSP_User_Guide/Navigation/Moving%20Around%20the%20UI.htm#_Toc2780722).
Select the zone that was created above (or select the appropriate zone if a different zone was used.)
The external IP address will be displayed as a CNAME record for your zone.
Now that we have verified that ExternalDNS will automatically manage your UltraDNS records, you can delete example zones that you created in this tutorial:
$ kubectl delete service -f nginx.yaml
$ kubectl delete service -f externaldns.yaml
- First, you want to create a service file called 'apple-banana-echo.yaml'
---
kind: Pod
apiVersion: v1
metadata:
name: example-app
labels:
app: apple
spec:
containers:
- name: example-app
image: hashicorp/http-echo
args:
- "-text=apple"
---
kind: Service
apiVersion: v1
metadata:
name: example-service
spec:
selector:
app: apple
ports:
- port: 5678 # Default port for image
- Then, create service file called 'expose-apple-banana-app.yaml' to expose the services. For more information to deploy ingress controller, refer to (https://kubernetes.github.io/ingress-nginx/deploy/)
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: example-ingress
annotations:
ingress.kubernetes.io/rewrite-target: /
ingress.kubernetes.io/scheme: internet-facing
external-dns.alpha.kubernetes.io/hostname: apple.example.com.
external-dns.alpha.kubernetes.io/target: 10.10.10.1,10.10.10.23
spec:
rules:
- http:
paths:
- path: /apple
pathType: Prefix
backend:
service:
name: example-service
port:
number: 5678
- Then, create the deployment and service:
$ kubectl create -f apple-banana-echo.yaml
$ kubectl create -f expose-apple-banana-app.yaml
$ kubectl create -f external-dns.yaml
- Depending on where you run your service from, it can take a few minutes for your cloud provider to create an external IP for the service.
- Please verify on the UltraDNS UI that the records have been created under the zone "example.com".
- Finally, you will need to clean up the deployment and service. Please verify on the UI afterwards that the records have been deleted from the zone "example.com":
$ kubectl delete -f apple-banana-echo.yaml
$ kubectl delete -f expose-apple-banana-app.yaml
$ kubectl delete -f external-dns.yaml
- Please note, that prior to deploying the external-dns service, you will need to add the option –txt-prefix=txt- into external-dns.yaml. If this not provided, your records will not be created.
- First, create a service file called 'apple-banana-echo.yaml'
- Config File Example – kubernetes cluster is on-premise not on cloud
--- kind: Pod apiVersion: v1 metadata: name: example-app labels: app: apple spec: containers: - name: example-app image: hashicorp/http-echo args: - "-text=apple" --- kind: Service apiVersion: v1 metadata: name: example-service spec: selector: app: apple ports: - port: 5678 # Default port for image --- apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: example-ingress annotations: ingress.kubernetes.io/rewrite-target: / ingress.kubernetes.io/scheme: internet-facing external-dns.alpha.kubernetes.io/hostname: apple.example.com. external-dns.alpha.kubernetes.io/target: apple.cname.com. spec: rules: - http: paths: - path: /apple backend: service: name: example-service port: number: 5678
- Config File Example – Kubernetes cluster service from different cloud vendors
--- kind: Pod apiVersion: v1 metadata: name: example-app labels: app: apple spec: containers: - name: example-app image: hashicorp/http-echo args: - "-text=apple" --- kind: Service apiVersion: v1 metadata: name: example-service annotations: external-dns.alpha.kubernetes.io/hostname: my-app.example.com. spec: selector: app: apple type: LoadBalancer ports: - protocol: TCP port: 5678 targetPort: 5678
- Then, create the deployment and service:
$ kubectl create -f apple-banana-echo.yaml
$ kubectl create -f external-dns.yaml
- Depending on where you run your service from, it can take a few minutes for your cloud provider to create an external IP for the service.
- Please verify on the UltraDNS UI, that the records have been created under the zone "example.com".
- Finally, you will need to clean up the deployment and service. Please verify on the UI afterwards that the records have been deleted from the zone "example.com":
$ kubectl delete -f apple-banana-echo.yaml
$ kubectl delete -f external-dns.yaml
- Please note, that prior to deploying the external-dns service, you will need to add the option –txt-prefix=txt- into external-dns.yaml. Since you will also be created a CNAME record, If this not provided, your records will not be created.
- First, create a service file called 'apple-banana-echo.yaml'
- Config File Example – kubernetes cluster is on-premise not on cloud
--- kind: Pod apiVersion: v1 metadata: name: example-app labels: app: apple spec: containers: - name: example-app image: hashicorp/http-echo args: - "-text=apple" --- kind: Service apiVersion: v1 metadata: name: example-service spec: selector: app: apple ports: - port: 5678 # Default port for image --- kind: Pod apiVersion: v1 metadata: name: example-app1 labels: app: apple1 spec: containers: - name: example-app1 image: hashicorp/http-echo args: - "-text=apple" --- kind: Service apiVersion: v1 metadata: name: example-service1 spec: selector: app: apple1 ports: - port: 5679 # Default port for image --- kind: Pod apiVersion: v1 metadata: name: example-app2 labels: app: apple2 spec: containers: - name: example-app2 image: hashicorp/http-echo args: - "-text=apple" --- kind: Service apiVersion: v1 metadata: name: example-service2 spec: selector: app: apple2 ports: - port: 5680 # Default port for image --- apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: example-ingress annotations: ingress.kubernetes.io/rewrite-target: / ingress.kubernetes.io/scheme: internet-facing external-dns.alpha.kubernetes.io/hostname: apple.example.com. external-dns.alpha.kubernetes.io/target: apple.cname.com. spec: rules: - http: paths: - path: /apple backend: service: name: example-service port: number: 5678 --- apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: example-ingress1 annotations: ingress.kubernetes.io/rewrite-target: / ingress.kubernetes.io/scheme: internet-facing external-dns.alpha.kubernetes.io/hostname: apple-banana.example.com. external-dns.alpha.kubernetes.io/target: 10.10.10.3 spec: rules: - http: paths: - path: /apple backend: service: name: example-service1 port: number: 5679 --- apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: example-ingress2 annotations: ingress.kubernetes.io/rewrite-target: / ingress.kubernetes.io/scheme: internet-facing external-dns.alpha.kubernetes.io/hostname: banana.example.com. external-dns.alpha.kubernetes.io/target: 10.10.10.3,10.10.10.20 spec: rules: - http: paths: - path: /apple backend: service: name: example-service2 port: number: 5680
- Config File Example – Kubernetes cluster service from different cloud vendors
--- apiVersion: apps/v1 kind: Deployment metadata: name: nginx spec: selector: matchLabels: app: nginx template: metadata: labels: app: nginx spec: containers: - image: nginx name: nginx ports: - containerPort: 80 --- apiVersion: v1 kind: Service metadata: name: nginx annotations: external-dns.alpha.kubernetes.io/hostname: my-app.example.com. spec: selector: app: nginx type: LoadBalancer ports: - protocol: TCP port: 80 targetPort: 80 --- kind: Pod apiVersion: v1 metadata: name: example-app labels: app: apple spec: containers: - name: example-app image: hashicorp/http-echo args: - "-text=apple" --- kind: Service apiVersion: v1 metadata: name: example-service spec: selector: app: apple ports: - port: 5678 # Default port for image --- kind: Pod apiVersion: v1 metadata: name: example-app1 labels: app: apple1 spec: containers: - name: example-app1 image: hashicorp/http-echo args: - "-text=apple" --- apiVersion: extensions/v1beta1 kind: Service apiVersion: v1 metadata: name: example-service1 spec: selector: app: apple1 ports: - port: 5679 # Default port for image --- apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: example-ingress annotations: ingress.kubernetes.io/rewrite-target: / ingress.kubernetes.io/scheme: internet-facing external-dns.alpha.kubernetes.io/hostname: apple.example.com. external-dns.alpha.kubernetes.io/target: 10.10.10.3,10.10.10.25 spec: rules: - http: paths: - path: /apple backend: service: name: example-service port: number: 5678 --- apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: example-ingress1 annotations: ingress.kubernetes.io/rewrite-target: / ingress.kubernetes.io/scheme: internet-facing external-dns.alpha.kubernetes.io/hostname: apple-banana.example.com. external-dns.alpha.kubernetes.io/target: 10.10.10.3 spec: rules: - http: paths: - path: /apple backend: service: name: example-service1 port: number: 5679
- Then, create the deployment and service:
$ kubectl create -f apple-banana-echo.yaml
$ kubectl create -f external-dns.yaml
- Depending on where you run your service from, it can take a few minutes for your cloud provider to create an external IP for the service.
- Please verify on the UltraDNS UI, that the records have been created under the zone "example.com".
- Finally, you will need to clean up the deployment and service. Please verify on the UI afterwards that the records have been deleted from the zone "example.com":
$ kubectl delete -f apple-banana-echo.yaml
$ kubectl delete -f external-dns.yaml```