diff --git a/docs/tutorials/azure-private-dns.md b/docs/tutorials/azure-private-dns.md index 87f9ebb5b..36e38b3b1 100644 --- a/docs/tutorials/azure-private-dns.md +++ b/docs/tutorials/azure-private-dns.md @@ -3,61 +3,20 @@ This tutorial describes how to set up ExternalDNS for managing records in Azure Private DNS. It comprises of the following steps: -1) Install NGINX Ingress Controller -2) Provision Azure Private DNS -3) Configure service principal for managing the zone -4) Deploy ExternalDNS +1) Provision Azure Private DNS +2) Configure service principal for managing the zone +3) Deploy ExternalDNS +4) Expose an NGINX service with a LoadBalancer and annotate it with the desired DNS name +5) Install NGINX Ingress Controller (Optional) +6) Expose an nginx service with an ingress (Optional) +7) Verify the DNS records -Everything will be deployed on Kubernetes. +Everything will be deployed on Kubernetes. Therefore, please see the subsequent prerequisites. ## Prerequisites - Azure Kubernetes Service is deployed and ready -- [Azure CLI 2.0](https://docs.microsoft.com/en-us/cli/azure/install-azure-cli) and `kubectl` installed on the box to execute the subsequent steps - -## Install NGINX Ingress Controller - -Helm is used to deploy the ingress controller. - -We employ the popular chart [ingress-nginx](https://github.com/kubernetes/ingress-nginx/tree/main/charts/ingress-nginx). - -``` -$ helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx -$ helm repo update -$ helm install [RELEASE_NAME] ingress-nginx/ingress-nginx - --set controller.publishService.enabled=true -``` - -The parameter `controller.publishService.enabled` needs to be set to `true.` - -It will make the ingress controller update the endpoint records of ingress-resources to contain the external-ip of the loadbalancer serving the ingress-controller. -This is crucial as ExternalDNS reads those endpoints records when creating DNS-Records from ingress-resources. -In the subsequent parameter we will make use of this. If you don't want to work with ingress-resources in your later use, you can leave the parameter out. - -Verify the correct propagation of the loadbalancer's ip by listing the ingresses. - -``` -$ kubectl get ingress -``` - -The address column should contain the ip for each ingress. ExternalDNS will pick up exactly this piece of information. - -``` -NAME HOSTS ADDRESS PORTS AGE -nginx1 sample1.aks.com 52.167.195.110 80 6d22h -nginx2 sample2.aks.com 52.167.195.110 80 6d21h -``` - -If you do not want to deploy the ingress controller with Helm, ensure to pass the following cmdline-flags to it through the mechanism of your choice: - -``` -flags: ---publish-service=/ ---update-status=true (default-value) - -example: -./nginx-ingress-controller --publish-service=default/nginx-ingress-controller -``` +- [Azure CLI 2.0](https://docs.microsoft.com/en-us/cli/azure/install-azure-cli) and `kubectl` installed on the box to execute the subsequent steps ## Provision Azure Private DNS @@ -72,7 +31,7 @@ $ az group create -n externaldns -l westeurope Substitute a more suitable location for the resource group if desired. -As a prerequisite for Azure Private DNS to resolve records is to define links with VNETs. +As a prerequisite for Azure Private DNS to resolve records is to define links with VNETs. Thus, first create a VNET. ``` @@ -101,11 +60,11 @@ $ az network private-dns link vnet create -g externaldns -n mylink \ ``` ## Configure service principal for managing the zone -ExternalDNS needs permissions to make changes in Azure Private DNS. +ExternalDNS needs permissions to make changes in Azure Private DNS. These permissions are roles assigned to the service principal used by ExternalDNS. A service principal with a minimum access level of `Private DNS Zone Contributor` to the Private DNS zone(s) and `Reader` to the resource group containing the Azure Private DNS zone(s) is necessary. -More powerful role-assignments like `Owner` or assignments on subscription-level work too. +More powerful role-assignments like `Owner` or assignments on subscription-level work too. Start off by **creating the service principal** without role-assignments. ``` @@ -119,8 +78,7 @@ $ az ad sp create-for-rbac --skip-assignment -n http://externaldns-sp ``` > Note: Alternatively, you can issue `az account show --query "tenantId"` to retrieve the id of your AAD Tenant too. - -Next, assign the roles to the service principal. +Next, assign the roles to the service principal. But first **retrieve the ID's** of the objects to assign roles on. ``` @@ -134,17 +92,17 @@ $ az network private-dns zone show --name example.com -g externaldns --query id Now, **create role assignments**. ``` # 1. as a reader to the resource group -$ az role assignment create --role "Reader" --assignee --scope +$ az role assignment create --role "Reader" --assignee --scope # 2. as a contributor to DNS Zone itself -$ az role assignment create --role "Private DNS Zone Contributor" --assignee --scope +$ az role assignment create --role "Private DNS Zone Contributor" --assignee --scope ``` ## Deploy ExternalDNS -Configure `kubectl` to be able to communicate and authenticate with your cluster. +Configure `kubectl` to be able to communicate and authenticate with your cluster. This is per default done through the file `~/.kube/config`. -For general background information on this see [kubernetes-docs](https://kubernetes.io/docs/tasks/access-application-cluster/access-cluster/). +For general background information on this see [kubernetes-docs](https://kubernetes.io/docs/tasks/access-application-cluster/access-cluster/). Azure-CLI features functionality for automatically maintaining this file for AKS-Clusters. See [Azure-Docs](https://docs.microsoft.com/de-de/cli/azure/aks?view=azure-cli-latest#az-aks-get-credentials). Follow the steps for [azure-dns provider](./azure.md#creating-configuration-file) to create a configuration file. @@ -338,11 +296,12 @@ Create the deployment for ExternalDNS: $ kubectl create -f externaldns.yaml ``` -## Deploying sample service +## Create an nginx deployment -Create a service file called 'nginx.yaml' with the following contents: +This step creates a demo workload in your cluster. Apply the following manifest to create a deployment that we are going to expose later in this tutorial in multiple ways: ```yaml +--- apiVersion: apps/v1 kind: Deployment metadata: @@ -357,15 +316,92 @@ spec: app: nginx spec: containers: - - image: nginx - name: nginx - ports: - - containerPort: 80 + - image: nginx + name: nginx + ports: + - containerPort: 80 +``` + +## Expose the nginx deployment with a load balancer + +Apply the following manifest to create a service of type `LoadBalancer`. This will create a public load balancer in Azure that will forward traffic to the nginx pods. + +```yaml +--- +apiVersion: v1 +kind: Service +annotations: + service.beta.kubernetes.io/azure-load-balancer-internal: "true" + external-dns.alpha.kubernetes.io/hostname: server.example.com + external-dns.alpha.kubernetes.io/internal-hostname: server-clusterip.example.com +metadata: + name: nginx-svc +spec: + ports: + - port: 80 + protocol: TCP + targetPort: 80 + selector: + app: nginx + type: LoadBalancer +``` + +In the service we used multiple annptations. The annotation `service.beta.kubernetes.io/azure-load-balancer-internal` is used to create an internal load balancer. The annotation `external-dns.alpha.kubernetes.io/hostname` is used to create a DNS record for the load balancer that will point to the internal IP address in the VNET allocated by the internal load balancer. The annotation `external-dns.alpha.kubernetes.io/internal-hostname` is used to create a private DNS record for the load balancer that will point to the cluster IP. + +## Install NGINX Ingress Controller (Optional) + +Helm is used to deploy the ingress controller. + +We employ the popular chart [ingress-nginx](https://github.com/kubernetes/ingress-nginx/tree/main/charts/ingress-nginx). + +``` +$ helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx +$ helm repo update +$ helm install [RELEASE_NAME] ingress-nginx/ingress-nginx + --set controller.publishService.enabled=true +``` + +The parameter `controller.publishService.enabled` needs to be set to `true.` + +It will make the ingress controller update the endpoint records of ingress-resources to contain the external-ip of the loadbalancer serving the ingress-controller. +This is crucial as ExternalDNS reads those endpoints records when creating DNS-Records from ingress-resources. +In the subsequent parameter we will make use of this. If you don't want to work with ingress-resources in your later use, you can leave the parameter out. + +Verify the correct propagation of the loadbalancer's ip by listing the ingresses. + +``` +$ kubectl get ingress +``` + +The address column should contain the ip for each ingress. ExternalDNS will pick up exactly this piece of information. + +``` +NAME HOSTS ADDRESS PORTS AGE +nginx1 sample1.aks.com 52.167.195.110 80 6d22h +nginx2 sample2.aks.com 52.167.195.110 80 6d21h +``` + +If you do not want to deploy the ingress controller with Helm, ensure to pass the following cmdline-flags to it through the mechanism of your choice: + +``` +flags: +--publish-service=/ +--update-status=true (default-value) + +example: +./nginx-ingress-controller --publish-service=default/nginx-ingress-controller +``` + +## Expose the nginx deployment with the ingress (Optional) + +Apply the following manifest to create an ingress resource that will expose the nginx deployment. The ingress resource backend points to a `ClusterIP` service that is needed to select the pods that will receive the traffic. + +```yaml --- apiVersion: v1 kind: Service metadata: - name: nginx-svc + name: nginx-svc-clusterip spec: ports: - port: 80 @@ -374,7 +410,7 @@ spec: selector: app: nginx type: ClusterIP - + --- apiVersion: networking.k8s.io/v1 kind: Ingress @@ -389,7 +425,7 @@ spec: paths: - backend: service: - name: nginx-svc + name: nginx-svc-clusterip port: number: 80 pathType: Prefix @@ -403,7 +439,7 @@ Create the deployment, service and ingress object: $ kubectl create -f nginx.yaml ``` -Since your external IP would have already been assigned to the nginx-ingress service, the DNS records pointing to the IP of the nginx-ingress service should be created within a minute. +Since your external IP would have already been assigned to the nginx-ingress service, the DNS records pointing to the IP of the nginx-ingress service should be created within a minute. ## Verify created records diff --git a/docs/tutorials/azure.md b/docs/tutorials/azure.md index 96128f1ba..29cdaed60 100644 --- a/docs/tutorials/azure.md +++ b/docs/tutorials/azure.md @@ -518,7 +518,7 @@ Create the deployment for ExternalDNS: $ kubectl create --namespace "default" --filename externaldns.yaml ``` -## Deploying an Nginx Service +## Ingress Option: Expose an nginx service with an ingress Create a file called `nginx.yaml` with the following contents: @@ -586,6 +586,49 @@ $ kubectl create --namespace "default" --filename nginx.yaml Since your external IP would have already been assigned to the nginx-ingress service, the DNS records pointing to the IP of the nginx-ingress service should be created within a minute. +## Azure Load Balancer option: Expose an nginx service with a load balancer + +Create a file called `nginx.yaml` with the following contents: + +```yaml +--- +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 +annotations: + external-dns.alpha.kubernetes.io/hostname: server.example.com +metadata: + name: nginx-svc +spec: + ports: + - port: 80 + protocol: TCP + targetPort: 80 + selector: + app: nginx + type: LoadBalancer +``` + +The annotation `external-dns.alpha.kubernetes.io/hostname` is used to specify the DNS name that should be created for the service. The annotation value is a comma separated list of host names. + ## Verifying Azure DNS records Run the following command to view the A records for your Azure DNS zone: