Set up a custom domain name and SSL certificate with the application routing add-on for Azure Kubernetes Service (AKS)

This article shows you how to configure custom domain names and SSL/TLS certificates for AKS ingress using Azure Key Vault and Azure DNS with the application routing add-on for AKS.

Prerequisites

  • An AKS cluster with the application routing add-on.

  • Azure Key Vault if you want to configure SSL termination and store certificates in the vault hosted in Azure. If you don't have one, see Create a key vault using the Azure CLI.

  • To enable support for HTTPS traffic, you need an SSL certificate. If you don't have one, see create a certificate.

  • Azure DNS if you want to configure global and private zone management and host them in Azure. If you don't have an Azure DNS zone, you can create one. To enable support for DNS zones:

    • All global Azure DNS zones need to be in the same resource group, which could be different from the cluster resource group.
    • All private Azure DNS zones need to be in the same resource group, which could be different from the cluster resource group.
    • The resource group doesn't need to be in the same subscription as the cluster.

Required Azure permissions

Your user account needs: Owner, Azure account administrator, or Azure co-administrator role on your Azure subscription.

What the commands do: When you run az aks approuting update --attach-kv or az aks approuting zone add --attach-zones, these commands use your role assignment permissions to automatically grant the application routing add-on's managed identity the following roles:

  • Key Vault Certificate User role on your Azure Key Vault (for certificate access).
  • DNS Zone Contributor role on your Azure DNS zones (for DNS record management).

For more information on AKS managed identities, see Summary of managed identities.

Connect to your AKS cluster

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 command.

  • Configure kubectl to connect to your Kubernetes cluster using the az aks get-credentials command.

    # Set environment variables for your resource group and cluster name
    export RESOURCE_GROUP=<resource-group-name>
    export CLUSTER_NAME=<cluster-name>
    
    # Get the AKS cluster credentials
    az aks get-credentials --resource-group $RESOURCE_GROUP --name $CLUSTER_NAME
    

Create and export a self-signed SSL certificate

For testing, you can use a self-signed public certificate instead of a Certificate Authority (CA)-signed certificate. If you already have a certificate, you can skip this step.

Caution

Self-signed certificates are digital certificates that aren't signed by a trusted third-party CA. The company or developer responsible for the website or software creates, issues, and signs these certificates. This is why self-signed certificates are considered unsafe for public-facing websites and applications. Azure Key Vault has a trusted partnership with the some Certificate Authorities.

  1. Create a self-signed SSL certificate to use with the ingress using the openssl req command. Make sure you replace <host-name> with the DNS name you're using.

    openssl req -new -x509 -nodes -out aks-ingress-tls.crt -keyout aks-ingress-tls.key -subj "/CN=<host-name>" -addext "subjectAltName=DNS:<host-name>"
    
  2. Export the SSL certificate and skip the password prompt using the openssl pkcs12 -export command.

    openssl pkcs12 -export -in aks-ingress-tls.crt -inkey aks-ingress-tls.key -out aks-ingress-tls.pfx
    

Import a self-signed SSL certificate into Azure Key Vault

  • Import the SSL certificate into Azure Key Vault using the az keyvault certificate import command. If your certificate is password protected, you can pass the password through the --password flag.

    # Set environment variables for your key vault name and certificate name
    export KEY_VAULT_NAME=<key-vault-name>
    export KEY_VAULT_CERT_NAME=<key-vault-certificate-name>
    
    # Import the SSL certificate into Azure Key Vault
    az keyvault certificate import --vault-name $KEY_VAULT_NAME --name $KEY_VAULT_CERT_NAME --file aks-ingress-tls.pfx [--password <certificate password if specified>]
    

Note

To enable the application routing add-on to reload certificates from Azure Key Vault when they change, you should enable the secret autorotation feature of the Secrets Store CSI driver. When autorotation is enabled, the driver updates the pod mount and the Kubernetes secret by polling for changes periodically, based on the rotation poll interval you define. The default rotation poll interval is two minutes.

Enable Azure Key Vault integration

Azure Key Vault offers two authorization systems: Azure role-based access control (Azure RBAC), which operates on the management plane, and the access policy model, which operates on both the management plane and the data plane. The --attach-kv operation selects the appropriate access model to use.

  1. Get the resource ID for the key vault using the az keyvault show command and set the output to an environment variable.

    KEY_VAULT_ID=$(az keyvault show --name <KeyVaultName> --query "id" --output tsv)
    
  2. Update the application routing add-on to enable the Azure Key Vault provider for Secrets Store CSI Driver and apply the required role assignments using the az aks approuting update command with the --enable-kv and --attach-kv arguments.

    az aks approuting update --resource-group $RESOURCE_GROUP --name $CLUSTER_NAME --enable-kv --attach-kv ${KEY_VAULT_ID}
    

Create a global Azure DNS zone

If you already have an Azure DNS zone, you can skip this step.

  • Create an Azure DNS zone using the az network dns zone create command.

    # Set environment variables for your resource group and DNS zone name
    export RESOURCE_GROUP=<resource-group-name>
    export ZONE_NAME=<zone-name>
    
    # Create the Azure DNS zone
    az network dns zone create --resource-group $RESOURCE_GROUP --name $ZONE_NAME
    

Enable Azure DNS integration

  1. Get the resource ID for the DNS zone using the az network dns zone show command and set the output to an environment variable.

    ZONE_ID=$(az network dns zone show --resource-group $RESOURCE_GROUP --name $ZONE_NAME --query "id" --output tsv)
    
  2. Update the application routing add-on to enable Azure DNS integration using the az aks approuting zone command. You can pass a comma-separated list of DNS zone resource IDs.

    az aks approuting zone add --resource-group $RESOURCE_GROUP --name $CLUSTER_NAME --ids=${ZONE_ID} --attach-zones
    

Create an Ingress class that uses a host name and a certificate from Azure Key Vault

The application routing add-on creates an Ingress class on the cluster named webapprouting.kubernetes.azure.com. When you create an Ingress object with this class, it activates the add-on.

  1. Get the certificate URI to use in the ingress from Azure Key Vault using the az keyvault certificate show command.

    az keyvault certificate show --vault-name $KEY_VAULT_NAME --name $KEY_VAULT_CERT_NAME --query "id" --output tsv
    

    The following example output shows the certificate URI returned from the command:

    https://KeyVaultName.vault.azure.cn/certificates/KeyVaultCertificateName/ab12c34567d89e01f2345g6h78ijkl90
    
  2. Copy the following YAML manifest into a new file named ingress.yaml and save the file to your local computer.

    Update <host-name> with the name of your DNS host and <key-vault-certificate-uri> with the URI returned from the previous command. The string value for <key-vault-certificate-uri> should only include https://yourkeyvault.vault.azure.cn/certificates/certname. Remove the Certificate Version at the end of the URI string to get the current version.

    The secretName key in the tls section defines the name of the secret that contains the certificate for this Ingress resource. This certificate is presented in the browser when a client browses to the URL specified in the <host-name> key. Make sure that the value of secretName is equal to keyvault- followed by the value of the Ingress resource name (from metadata.name). In the example YAML, secretName needs to be equal to keyvault-<your-ingress-name>.

    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
      annotations:
        kubernetes.azure.com/tls-cert-keyvault-uri: <key-vault-certificate-uri>
      name: aks-helloworld
      namespace: hello-web-app-routing
    spec:
      ingressClassName: webapprouting.kubernetes.azure.com
      rules:
      - host: <host-name>
        http:
          paths:
          - backend:
              service:
                name: aks-helloworld
                port:
                  number: 80
            path: /
            pathType: Prefix
      tls:
      - hosts:
        - <host-name>
        secretName: keyvault-<your-ingress-name>
    
  3. Create the cluster resources using the kubectl apply command.

    kubectl apply -f ingress.yaml -n hello-web-app-routing
    

    The following example output shows the created resource:

    Ingress.networking.k8s.io/aks-helloworld created
    

Verify the managed ingress was created

  • Verify the managed ingress was created using the kubectl get ingress command.

    kubectl get ingress -n hello-web-app-routing
    

    The following example output shows the created managed ingress:

    NAME             CLASS                                HOSTS               ADDRESS       PORTS     AGE
    aks-helloworld   webapprouting.kubernetes.azure.com   myapp.contoso.com   20.51.92.19   80, 443   4m