Reading Time: 4 mins
Overview
ExternalDNS service publishes DNS records for applications to DNS servers. This post explains how to deploy ExternalDNS into a Tanzu Kubernetes (workload) and dns zone deployed on Azure.
Pre reqs
- Bootstrap machine with the following installed: Tanzu CLI, kubectl installed as mentioned here
- Tanzu Kubernetes Grid management cluster and workload cluster running on vSphere, Amazon EC2, or Azure, with the package repository installed. For this demo, I have deployed TKG on Azure.
- Registered Domain Name
Note: For this demo, I have used a domain (captainvirtualization.in) registered with Godaddy and created dns zone in Azure as shown below:
Install AZ CLI
- Follow the steps given here to install AZ CLI on your bootstrap machine.
Prepare setup in Azure
az login
az account set -s SUBSCRIPTION-ID-GUID
- In Azure portal: Navigate to Home > Services > Azure Active Directory > App registrations > + New Registration
- Provide a name and click Register
Note the Application ID, Tenant ID from the registered service principal
# Retrieve the ID of the resource group
#Syntax: az group show --name RESOURCE-GROUP --query id
#Example: az group show --name images-rg --query id
"/subscriptions/827ba436b-aa9b-45d645395244/resourceGroups/images-rg"
# Assign the reader role to the service principal for the resource group scope
# Syntax: az role assignment create --role "Reader" --assignee APP-ID-GUID --scope RESOURCE-GROUP-RESOURCE-ID
# Example: az role assignment create --role "Reader" --assignee 8d65aec8-96f7-45a3-a349-eac3d722de0c --scope /subscriptions/-f0b2-4e6b-aa9b-45d645395244/resourceGroups/images-rg
{
"canDelegate": null,
"id": "/subscriptions/-f0b2-4e6b-aa9b-45d645395244/resourceGroups/images-rg/providers/Microsoft.Authorization/roleAssignments/a435e88c-e1cb-4bc8-8810-03dfb37a3e88",
"name": "a435e88c-e1cb-4bc8-8810-03dfb37a3e88",
"principalId": "-c1fa-4a91-a58f-2641136f108d",
"principalType": "ServicePrincipal",
"resourceGroup": "images-rg",
"roleDefinitionId": "/subscriptions/-f0b2-4e6b-aa9b-45d645395244/providers/Microsoft.Authorization/roleDefinitions/acdd72a7-3385-48ef-bd42-f606fba81ae7",
"scope": "/subscriptions/-f0b2-4e6b-aa9b-444/resourceGroups/images-rg",
"type": "Microsoft.Authorization/roleAssignments"
}
# Syntax: az network dns zone show --name DNS-ZONE-NAME -g RESOURCE-GROUP-NAME --query id
# Syntax: az role assignment create --role "Contributor" --assignee APP-ID-GUID --scope DNS-ZONE-RESOURCE-ID
# Example: az network dns zone show --name captainvirtualization.in -g images-rg --query id
"/subscriptions/0b2-4e6b-aa9b-45244/resourceGroups/images-rg/providers/Microsoft.Network/dnszones/captainvirtualization.in"
- To connect the ExternalDNS service to the Azure DNS service, you create a configuration file named azure.json with content like shown below:
{
"tenantId": "01234abc-de56-ff78-abc1-234567890def",
"subscriptionId": "01234abc-de56-ff78-abc1-234567890def",
"resourceGroup": "MyDnsResourceGroup",
"aadClientId": "01234abc-de56-ff78-abc1-234567890def",
"aadClientSecret": "uKiuXeiwui4jo9quae9o"
}
#### Don't include this #######
# To retrieve tenantId, you can run the az account show --query "tenantId" command.
# To retrieve subscriptionId, you can run the az account show --query "id" command.
# ResourceGroup is the name of the resource group that your DNS zone is within.
# aadClientId is the appId collected after creating the service principal.
#aadClientSecret can created by navigating to Azure portal > Azure Active Directory > App registrations > Click on newly created service principal (capv-demo in this case) > certificated & Secrets > + New client secret
# Get the admin credentials of the workload cluster into which you want to deploy External-DNS. In this case, capv-workload is workload cluster:
$ tanzu cluster kubeconfig get capv-workload --admin
# Set the context of kubectl to the cluster
$ kubectl config use-context capv-workload-admin@capv-workload
# Create Namespace
$ kubectl create ns tanzu-system-service-discovery
namespace/tanzu-system-service-discovery created
# Create secret
$ kubectl -n tanzu-system-service-discovery create secret generic azure-config-file --from-file=azure.json
secret/azure-config-file created
Install the package
In TMC Console: Catalog > select the workload cluster (capv-workload in my case) from drop down and click on external-dns
- Click on Install Package which can be found on top right side of the page
- Name the Installed package as : capv-workload-extdns and click NEXT
- Package install resources: Leave to Default and click NEXT
- Configure values: Provide below values after changing domain-filter and resource-group
# Deployment-related configuration.
namespace: tanzu-system-service-discovery
deployment:
args:
- --source=service
- --source=ingress
- --source=contour-httpproxy
- --domain-filter=captainvirtualization.in ## To be Changed
- --policy=upsert-only
- --registry=txt
- --txt-prefix=externaldns-
- --provider=azure
- --azure-resource-group=images-rg ## To be Changed
env: []
securityContext: {}
volumeMounts:
- name: azure-config-file
mountPath: /etc/kubernetes
readOnly: true
volumes:
- name: azure-config-file
secret:
secretName: azure-config-file
Validate
In TMC Console: Clusters > capv-workload > Add-ons > Installed > check if the package ( external-dns.tanzu.vmware.com ) is succeeded and healthy
Verify the pod status
# Validate the pods
kubectl get pods -n tanzu-system-service-discovery
NAME READY STATUS RESTARTS AGE
external-dns-646dbd7c96-kfvhb 1/1 Running 0 4m14s
- Now, lets test the external-dns:
- Create a yaml with below config to create a Service and Deployment
apiVersion: v1
kind: Service
metadata:
name: nginx
annotations:
external-dns.alpha.kubernetes.io/hostname: nginx.captainvirtualization.in ## Change me
spec:
ports:
- port: 80
targetPort: 80
protocol: TCP
type: LoadBalancer
selector:
app: nginx
---
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
name: http
Service
# Get the external IP of service
kubectl get svc --kubeconfig ~/.kube/config-tkg
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 100.64.0.1 <none> 443/TCP 2d1h
nginx LoadBalancer 100.69.57.234 20.207.97.64 80:31455/TCP 3m33s
logs
## Validate the logs and it should show a message "updating a record"
$ kubectl logs external-dns-646dbd7c96-kfvhb -n tanzu-system-service-discovery
time="2022-03-17T13:38:12Z" level=info msg="Updating A record named 'nginx' to '20.207.97.64' for Azure DNS zone 'captainvirtualization.in'."
time="2022-03-17T13:38:13Z" level=info msg="Updating TXT record named 'externaldns-nginx' to '\"heritage=external-dns,external-dns/owner=default,external-dns/resource=service/default/nginx\"' for Azure DNS zone 'captainvirtualization.in'."
- DNS record should be automatically created as shown below:
- Access the hostname in browser and it should load nginx page as shown below:
This confirms that external-dns is working as expected as the DNS records are created automatically in DNS.