|
| 1 | +--- |
| 2 | +title: Configure internal NGIX ingress controller for Azure private DNS zone |
| 3 | +description: Understand how to configure an ingress controller with a private IP address and an Azure private DNS zone using the application routing add-on for Azure Kubernetes Service. |
| 4 | +ms.subservice: aks-networking |
| 5 | +ms.custom: devx-track-azurecli |
| 6 | +ms.topic: how-to |
| 7 | +ms.date: 02/27/2024 |
| 8 | +author: sabbour |
| 9 | +ms.author: asabbour |
| 10 | +--- |
| 11 | + |
| 12 | +# Configure NGINX ingress controller to support Azure private DNS zone with application routing add-on |
| 13 | + |
| 14 | +This article demonstrates how to configure an NGINX ingress controller to work with Azure internal load balancer and configure a private Azure DNS zone to enable DNS resolution for the private endpoints to resolve specific domains. |
| 15 | + |
| 16 | +## Before you begin |
| 17 | + |
| 18 | +- An AKS cluster with the [application routing add-on][app-routing-add-on-basic-configuration]. |
| 19 | +- To attach an Azure private DNS Zone, you need the [Owner][rbac-owner], [Azure account administrator][rbac-classic], or [Azure co-administrator][rbac-classic] role on your Azure subscription. |
| 20 | + |
| 21 | +## Connect to your AKS cluster |
| 22 | + |
| 23 | +To connect to the Kubernetes cluster from your local computer, you use `kubectl`, the Kubernetes command-line client. You can install it locally using the [az aks install-cli][az-aks-install-cli] command. If you use the Azure Cloud Shell, `kubectl` is already installed. |
| 24 | + |
| 25 | +The following example configures connecting to your cluster named *myAKSCluster* in the *myResourceGroup* using the [`az aks get-credentials`][az-aks-get-credentials] command. |
| 26 | + |
| 27 | +```azurecli-interactive |
| 28 | +az aks get-credentials --resource-group myResourceGroup --name myAKSCluster |
| 29 | +``` |
| 30 | + |
| 31 | +## Create a virtual network |
| 32 | + |
| 33 | +To publish a private DNS zone to your virtual network, you need to specify a list of virtual networks that are allowed to resolve records within the zone. These are called [virtual network links][virtual-network-links]. |
| 34 | + |
| 35 | +The following example creates a virtual network named *myAzureVNet* in the *myResourceGroup* resource group, and one subnet named *mySubnet* to create within the VNet with a specific address prefix. |
| 36 | + |
| 37 | +```azurecli-interactive |
| 38 | +az network vnet create \ |
| 39 | + --name myAzureVNet \ |
| 40 | + --resource-group myResourceGroup \ |
| 41 | + --location eastus \ |
| 42 | + --address-prefix 10.2.0.0/16 \ |
| 43 | + --subnet-name mysubnet \ |
| 44 | + --subnet-prefixes 10.2.0.0/24 |
| 45 | +``` |
| 46 | + |
| 47 | +## Create an Azure private DNS zone |
| 48 | + |
| 49 | +> [!NOTE] |
| 50 | +> You can configure the application routing add-on to automatically create records on one or more Azure global and private DNS zones for hosts defined on Ingress resources. All global Azure DNS zones and all private Azure DNS zones need to be in the same resource group. |
| 51 | +
|
| 52 | +You create a DNS zone using the [az network private-dns zone create][az-network-private-dns-zone-create] command, specifying the name of the zone and the resource group to create it in. The following example creates a DNS zone named *private.contoso.com* in the *myResourceGroup* resource group. |
| 53 | + |
| 54 | +```azurecli-interactive |
| 55 | +az network private-dns zone create --resource-group myResourceGoup -n private.contoso.com |
| 56 | +``` |
| 57 | + |
| 58 | +You create a virtual network link to the DNS zone created earlier using the [az network private-dns link vnet create][az-network-private-dns-link-vnet-create] command. The following example creates a link named *myDNSLink* to the zone *private.contoso.com* for the virtual network *myAzureVNet*. Include the `--registration-enabled` parameter to specify the link is not registration enabled. |
| 59 | + |
| 60 | +```azurecli-interactive |
| 61 | +az network private-dns link vnet create --resource-group myResourceGroup \ |
| 62 | + --name myDNSLink \ |
| 63 | + --zone-name private.contoso.com \ |
| 64 | + --virtual-network myAzureVNet \ |
| 65 | + --registration-enabled false |
| 66 | +``` |
| 67 | + |
| 68 | +The Azure DNS private zone auto registration feature manages DNS records for virtual machines deployed in a virtual network. When you link a virtual network with a private DNS zone with this setting enabled, a DNS record gets created for each Azure virtual machine for your AKS node deployed in the virtual network. |
| 69 | + |
| 70 | +## Attach an Azure private DNS zone to the application routing add-on |
| 71 | + |
| 72 | +> [!NOTE] |
| 73 | +> The `az aks approuting zone add` command uses the permissions of the user running the command to create the [Azure DNS Zone][azure-dns-zone-role] role assignment. The **Private DNS Zone Contributor** role is a built-in role for managing private DNS resources and is assigned to the add-on's managed identity. For more information on AKS managed identities, see [Summary of managed identities][summary-msi]. |
| 74 | +
|
| 75 | +1. Retrieve the resource ID for the DNS zone using the [`az network dns zone show`][az-network-dns-zone-show] command and set the output to a variable named `ZONEID`. The following example queries the zone *private.contoso.com* in the resource group *myResourceGroup*. |
| 76 | + |
| 77 | + ```azurecli-interactive |
| 78 | + ZONEID=$(az network private-dns zone show --resource-group myResourceGroup --name private.contoso.com --query "id" --output tsv) |
| 79 | + ``` |
| 80 | +
|
| 81 | +1. Update the add-on to enable integration with Azure DNS using the [`az aks approuting zone`][az-aks-approuting-zone] command. You can pass a comma-separated list of DNS zone resource IDs. The following example updates the AKS cluster *myAKSCluster* in the resource group *myResourceGroup*. |
| 82 | +
|
| 83 | + ```azurecli-interactive |
| 84 | + az aks approuting zone add --resource-group myResourceGroup --name myAKSCluster --ids=${ZONEID} --attach-zones |
| 85 | + ``` |
| 86 | +
|
| 87 | +## Create an NGINX ingress controller with a private IP address and an internal load balancer |
| 88 | +
|
| 89 | +The application routing add-on uses a Kubernetes [custom resource definition (CRD)][k8s-crds] called [`NginxIngressController`][app-routing-crds] to configure NGINX ingress controllers. You can create more ingress controllers or modify an existing configuration. |
| 90 | +
|
| 91 | +`NginxIngressController` CRD has a `loadBalancerAnnotations` field to control the behavior of the NGINX ingress controller's service by setting [load balancer annotations](load-balancer-standard.md#customizations-via-kubernetes-annotations). |
| 92 | +
|
| 93 | +Perform the following steps to create an NGINX ingress controller with an internal facing Azure Load Balancer with a private IP address. |
| 94 | +
|
| 95 | +1. Copy the following YAML manifest into a new file named **nginx-internal-controller.yaml** and save the file to your local computer. |
| 96 | +
|
| 97 | + ```yml |
| 98 | + apiVersion: approuting.kubernetes.azure.com/v1alpha1 |
| 99 | + kind: NginxIngressController |
| 100 | + metadata: |
| 101 | + name: nginx-internal |
| 102 | + spec: |
| 103 | + ingressClassName: nginx-internal |
| 104 | + controllerNamePrefix: nginx-internal |
| 105 | + loadBalancerAnnotations: |
| 106 | + service.beta.kubernetes.io/azure-load-balancer-internal: "true" |
| 107 | + ``` |
| 108 | +
|
| 109 | +1. Create the NGINX ingress controller resources using the [`kubectl apply`][kubectl-apply] command. |
| 110 | +
|
| 111 | + ```bash |
| 112 | + kubectl apply -f nginx-internal-controller.yaml |
| 113 | + ``` |
| 114 | +
|
| 115 | + The following example output shows the created resource: |
| 116 | +
|
| 117 | + ```output |
| 118 | + nginxingresscontroller.approuting.kubernetes.azure.com/nginx-internal created |
| 119 | + ``` |
| 120 | +
|
| 121 | +1. Verify the ingress controller was created |
| 122 | +
|
| 123 | + You can verify the status of the NGINX ingress controller using the [`kubectl get nginxingresscontroller`][kubectl-get] command. |
| 124 | +
|
| 125 | + ```bash |
| 126 | + kubectl get nginxingresscontroller |
| 127 | + ``` |
| 128 | +
|
| 129 | + The following example output shows the created resource. It may take a few minutes for the controller to be available: |
| 130 | +
|
| 131 | + ```output |
| 132 | + NAME INGRESSCLASS CONTROLLERNAMEPREFIX AVAILABLE |
| 133 | + default webapprouting.kubernetes.azure.com nginx True |
| 134 | + nginx-internal nginx-internal nginx-internal True |
| 135 | + ``` |
| 136 | +
|
| 137 | +## Deploy an application |
| 138 | +
|
| 139 | +The application routing add-on uses annotations on Kubernetes Ingress objects to create the appropriate resources. |
| 140 | +
|
| 141 | +1. Create an application namespace called `hello-web-app-routing` to run the example pods using the [`kubectl create namespace`][kubectl-create-namespace] command. |
| 142 | +
|
| 143 | + ```bash |
| 144 | + kubectl create namespace hello-web-app-routing |
| 145 | + ``` |
| 146 | +
|
| 147 | +1. Create the deployment by copying the following YAML manifest into a new file named **deployment.yaml** and save the file to your local computer. |
| 148 | +
|
| 149 | + ```yaml |
| 150 | + apiVersion: apps/v1 |
| 151 | + kind: Deployment |
| 152 | + metadata: |
| 153 | + name: aks-helloworld |
| 154 | + namespace: hello-web-app-routing |
| 155 | + spec: |
| 156 | + replicas: 1 |
| 157 | + selector: |
| 158 | + matchLabels: |
| 159 | + app: aks-helloworld |
| 160 | + template: |
| 161 | + metadata: |
| 162 | + labels: |
| 163 | + app: aks-helloworld |
| 164 | + spec: |
| 165 | + containers: |
| 166 | + - name: aks-helloworld |
| 167 | + image: mcr.microsoft.com/azuredocs/aks-helloworld:v1 |
| 168 | + ports: |
| 169 | + - containerPort: 80 |
| 170 | + env: |
| 171 | + - name: TITLE |
| 172 | + value: "Welcome to Azure Kubernetes Service (AKS)" |
| 173 | + ``` |
| 174 | +
|
| 175 | +1. Create the service by copying the following YAML manifest into a new file named **service.yaml** and save the file to your local computer. |
| 176 | +
|
| 177 | + ```yaml |
| 178 | + apiVersion: v1 |
| 179 | + kind: Service |
| 180 | + metadata: |
| 181 | + name: aks-helloworld |
| 182 | + namespace: hello-web-app-routing |
| 183 | + spec: |
| 184 | + type: ClusterIP |
| 185 | + ports: |
| 186 | + - port: 80 |
| 187 | + selector: |
| 188 | + app: aks-helloworld |
| 189 | + ``` |
| 190 | +
|
| 191 | +1. Create the cluster resources using the [`kubectl apply`][kubectl-apply] command. |
| 192 | +
|
| 193 | + ```bash |
| 194 | + kubectl apply -f deployment.yaml -n hello-web-app-routing |
| 195 | + ``` |
| 196 | +
|
| 197 | + The following example output shows the created resource: |
| 198 | +
|
| 199 | + ```output |
| 200 | + deployment.apps/aks-helloworld created created |
| 201 | + ``` |
| 202 | +
|
| 203 | + ```bash |
| 204 | + kubectl apply -f service.yaml -n hello-web-app-routing |
| 205 | + ``` |
| 206 | +
|
| 207 | + The following example output shows the created resource: |
| 208 | +
|
| 209 | + ```output |
| 210 | + service/aks-helloworld created created |
| 211 | + ``` |
| 212 | +
|
| 213 | +## Create the Ingress resource that uses a host name on the Azure private DNS zone and a private IP address |
| 214 | +
|
| 215 | +1. Copy the following YAML manifest into a new file named **ingress.yaml** and save the file to your local computer. |
| 216 | +
|
| 217 | + Update *`<Hostname>`* with the name of your DNS host, for example, `helloworld.private.contoso.com`. Verify you're specifying `nginx-internal` for the `ingressClassName`. |
| 218 | +
|
| 219 | + ```yml |
| 220 | + apiVersion: networking.k8s.io/v1 |
| 221 | + kind: Ingress |
| 222 | + metadata: |
| 223 | + name: aks-helloworld |
| 224 | + namespace: hello-web-app-routing |
| 225 | + spec: |
| 226 | + ingressClassName: nginx-internal |
| 227 | + rules: |
| 228 | + - host: <Hostname> |
| 229 | + http: |
| 230 | + paths: |
| 231 | + - backend: |
| 232 | + service: |
| 233 | + name: aks-helloworld |
| 234 | + port: |
| 235 | + number: 80 |
| 236 | + path: / |
| 237 | + pathType: Prefix |
| 238 | + ``` |
| 239 | +
|
| 240 | +1. Create the cluster resources using the [`kubectl apply`][kubectl-apply] command. |
| 241 | +
|
| 242 | + ```bash |
| 243 | + kubectl apply -f ingress.yaml -n hello-web-app-routing |
| 244 | + ``` |
| 245 | +
|
| 246 | + The following example output shows the created resource: |
| 247 | +
|
| 248 | + ```output |
| 249 | + ingress.networking.k8s.io/aks-helloworld created |
| 250 | + ``` |
| 251 | +
|
| 252 | +## Verify the managed Ingress was created |
| 253 | +
|
| 254 | +You can verify the managed Ingress was created using the [`kubectl get ingress`][kubectl-get] command. |
| 255 | +
|
| 256 | +```bash |
| 257 | +kubectl get ingress -n hello-web-app-routing |
| 258 | +``` |
| 259 | + |
| 260 | +The following example output shows the created managed Ingress: |
| 261 | + |
| 262 | +```output |
| 263 | +NAME CLASS HOSTS ADDRESS PORTS AGE |
| 264 | +aks-helloworld nginx-internal helloworld.private.contoso.com 10.224.0.7 80 98s |
| 265 | +``` |
| 266 | + |
| 267 | +## Verify the Azure private DNS zone was updated |
| 268 | + |
| 269 | +In a few minutes, run the [az network private-dns record-set a list][az-network-private-dns-record-set-a-list] command to view the A records for your Azure private DNS zone. Specify the name of the resource group and the name of the DNS zone. In this example, the resource group is *myResourceGroup* and DNS zone is *private.contoso.com*. |
| 270 | + |
| 271 | +```azurecli-interactive |
| 272 | +az network private-dns record-set a list --resource-group myResourceGroup --zone-name private.contoso.com |
| 273 | +``` |
| 274 | + |
| 275 | +The following example output shows the created record: |
| 276 | + |
| 277 | +```output |
| 278 | +[ |
| 279 | + { |
| 280 | + "aRecords": [ |
| 281 | + { |
| 282 | + "ipv4Address": "10.224.0.7" |
| 283 | + } |
| 284 | + ], |
| 285 | + "etag": "188f0ce5-90e3-49e6-a479-9e4053f21965", |
| 286 | + "fqdn": "helloworld.private.contoso.com.", |
| 287 | + "id": "/subscriptions/xxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxx/resourceGroups/foo/providers/Microsoft.Network/privateDnsZones/private.contoso.com/A/helloworld", |
| 288 | + "isAutoRegistered": false, |
| 289 | + "name": "helloworld", |
| 290 | + "resourceGroup": "foo", |
| 291 | + "ttl": 300, |
| 292 | + "type": "Microsoft.Network/privateDnsZones/A" |
| 293 | + } |
| 294 | +] |
| 295 | +``` |
| 296 | + |
| 297 | +## Next steps |
| 298 | + |
| 299 | +For other configuration information related to SSL encryption other advanced NGINX ingress controller and ingress resource configuration, review [DNS and SSL configuration][dns-ssl-configuration] and [application routing add-on configuration][custom-ingress-configurations]. |
| 300 | + |
| 301 | +<!-- LINKS - external --> |
| 302 | +[kubectl-apply]: https://kubernetes.io/docs/reference/generated/kubectl/kubectl-commands#apply |
| 303 | +[kubectl-get]: https://kubernetes.io/docs/reference/generated/kubectl/kubectl-commands#get |
| 304 | +[kubectl-create-namespace]: https://kubernetes.io/docs/reference/kubectl/generated/kubectl_create/kubectl_create_namespace/ |
| 305 | +[k8s-crds]: https://kubernetes.io/docs/concepts/extend-kubernetes/api-extension/custom-resources/ |
| 306 | +[app-routing-crds]: https://aka.ms/aks/approuting/nginxingresscontrollercrd |
| 307 | + |
| 308 | +<!-- LINKS - internal --> |
| 309 | +[summary-msi]: use-managed-identity.md#summary-of-managed-identities |
| 310 | +[rbac-owner]: ../role-based-access-control/built-in-roles.md#owner |
| 311 | +[rbac-classic]: ../role-based-access-control/rbac-and-directory-admin-roles.md#classic-subscription-administrator-roles |
| 312 | +[app-routing-add-on-basic-configuration]: app-routing.md |
| 313 | +[dns-ssl-configuration]: app-routing-dns-ssl.md |
| 314 | +[custom-ingress-configurations]: app-routing-nginx-configuration.md |
| 315 | +[az-aks-approuting-zone]: /cli/azure/aks/approuting/zone |
| 316 | +[az-network-dns-zone-show]: /cli/azure/network/dns/zone#az-network-dns-zone-show |
| 317 | +[az-aks-install-cli]: /cli/azure/aks#az-aks-install-cli |
| 318 | +[az-aks-get-credentials]: /cli/azure/aks#az-aks-get-credentials |
| 319 | +[virtual-network-links]: ../dns/private-dns-virtual-network-links.md |
| 320 | +[azure-dns-zone-role]: ../dns/dns-protect-private-zones-recordsets.md |
| 321 | +[az-network-private-dns-zone-create]: /cli/azure/network/private-dns/zone?#az-network-private-dns-zone-create |
| 322 | +[az-network-private-dns-link-vnet-create]: /cli/azure/network/private-dns/link/vnet#az-network-private-dns-link-vnet-create |
| 323 | +[az-network-private-dns-record-set-a-list]: /cli/azure/network/private-dns/record-set/a#az-network-private-dns-record-set-a-list |
0 commit comments