Skip to main content

Managed Kubernetes Services - Azure Kubernetes Service (AKS): Deploy AKS Cluster via AZ CLI; Deploy & Configure Nginx Ingress, Cert Manager, ClusterIssuer; Example Deployment with TLS Encryption

1885 words·
Kubernetes Kubernetes Cluster Azure AKS Azure CLI Kubectl
Table of Contents
Kubernetes-Cluster - This article is part of a series.
Part 4: This Article

Azure CLI
#

Install Azure CLI (Linux)
#

Use the following script to install Azure CLI on Debian based distributions:

# Install dependencies
sudo apt update && sudo apt install apt-transport-https ca-certificates curl gnupg lsb-release -y

# Add Microsoft signing key
sudo mkdir -p /etc/apt/keyrings
curl -sLS https://packages.microsoft.com/keys/microsoft.asc |
  sudo gpg --dearmor -o /etc/apt/keyrings/microsoft.gpg
sudo chmod go+r /etc/apt/keyrings/microsoft.gpg

# Add the Azure CLI software repository
AZ_DIST=$(lsb_release -cs)
echo "Types: deb
URIs: https://packages.microsoft.com/repos/azure-cli/
Suites: ${AZ_DIST}
Components: main
Architectures: $(dpkg --print-architecture)
Signed-by: /etc/apt/keyrings/microsoft.gpg" | sudo tee /etc/apt/sources.list.d/azure-cli.sources

# Install Azure CLI
sudo apt update && sudo apt install azure-cli -y

Use the following script to install Azure CLI on any distribution:

# Install Azure CLI
curl -L https://aka.ms/InstallAzureCli | bash

Verify Installation
#

# Verify installation / check version
az --version

Login to Azure
#

# Login to Azure account: Use browser code
az login --use-device-code

Verify Login
#

# List details about current user and subscription
az account show

Install Kubectl (with Azure CLI)
#

# Install Kubectl with Azure CLI
sudo az aks install-cli

Verify Installation
#

# Verify installation / check version
kubectl version --client

Create AKS CLuster
#

List Available Regions
#

# List available regions
az account list-locations --output table

# Shell output:
DisplayName               Name                 RegionalDisplayName
------------------------  -------------------  -------------------------------------
East US                   eastus               (US) East US
South Central US          southcentralus       (US) South Central US
West US 2                 westus2              (US) West US 2
West US 3                 westus3              (US) West US 3
Australia East            australiaeast        (Asia Pacific) Australia East
Southeast Asia            southeastasia        (Asia Pacific) Southeast Asia
North Europe              northeurope          (Europe) North Europe
Sweden Central            swedencentral        (Europe) Sweden Central
UK South                  uksouth              (Europe) UK South
West Europe               westeurope           (Europe) West Europe
Central US                centralus            (US) Central US
South Africa North        southafricanorth     (Africa) South Africa North
Central India             centralindia         (Asia Pacific) Central India
East Asia                 eastasia             (Asia Pacific) East Asia
Japan East                japaneast            (Asia Pacific) Japan East
Korea Central             koreacentral         (Asia Pacific) Korea Central
Canada Central            canadacentral        (Canada) Canada Central
France Central            francecentral        (Europe) France Central
Germany West Central      germanywestcentral   (Europe) Germany West Central
Italy North               italynorth           (Europe) Italy North
Norway East               norwayeast           (Europe) Norway East
Poland Central            polandcentral        (Europe) Poland Central
Spain Central             spaincentral         (Europe) Spain Central
Switzerland North         switzerlandnorth     (Europe) Switzerland North
Mexico Central            mexicocentral        (Mexico) Mexico Central
UAE North                 uaenorth             (Middle East) UAE North
Brazil South              brazilsouth          (South America) Brazil South
Israel Central            israelcentral        (Middle East) Israel Central
Qatar Central             qatarcentral         (Middle East) Qatar Central
Central US (Stage)        centralusstage       (US) Central US (Stage)
East US (Stage)           eastusstage          (US) East US (Stage)
East US 2 (Stage)         eastus2stage         (US) East US 2 (Stage)
North Central US (Stage)  northcentralusstage  (US) North Central US (Stage)
South Central US (Stage)  southcentralusstage  (US) South Central US (Stage)
West US (Stage)           westusstage          (US) West US (Stage)
West US 2 (Stage)         westus2stage         (US) West US 2 (Stage)
Asia                      asia                 Asia
Asia Pacific              asiapacific          Asia Pacific
Australia                 australia            Australia
Brazil                    brazil               Brazil
Canada                    canada               Canada
Europe                    europe               Europe
France                    france               France
Germany                   germany              Germany
Global                    global               Global
India                     india                India
Israel                    israel               Israel
Italy                     italy                Italy
Japan                     japan                Japan
Korea                     korea                Korea
New Zealand               newzealand           New Zealand
Norway                    norway               Norway
Poland                    poland               Poland
Qatar                     qatar                Qatar
Singapore                 singapore            Singapore
South Africa              southafrica          South Africa
Sweden                    sweden               Sweden
Switzerland               switzerland          Switzerland
United Arab Emirates      uae                  United Arab Emirates
United Kingdom            uk                   United Kingdom
United States             unitedstates         United States
United States EUAP        unitedstateseuap     United States EUAP
East Asia (Stage)         eastasiastage        (Asia Pacific) East Asia (Stage)
Southeast Asia (Stage)    southeastasiastage   (Asia Pacific) Southeast Asia (Stage)
Brazil US                 brazilus             (South America) Brazil US
East US 2                 eastus2              (US) East US 2
East US STG               eastusstg            (US) East US STG
North Central US          northcentralus       (US) North Central US
West US                   westus               (US) West US
Japan West                japanwest            (Asia Pacific) Japan West
Jio India West            jioindiawest         (Asia Pacific) Jio India West
Central US EUAP           centraluseuap        (US) Central US EUAP
East US 2 EUAP            eastus2euap          (US) East US 2 EUAP
West Central US           westcentralus        (US) West Central US
South Africa West         southafricawest      (Africa) South Africa West
Australia Central         australiacentral     (Asia Pacific) Australia Central
Australia Central 2       australiacentral2    (Asia Pacific) Australia Central 2
Australia Southeast       australiasoutheast   (Asia Pacific) Australia Southeast
Jio India Central         jioindiacentral      (Asia Pacific) Jio India Central
Korea South               koreasouth           (Asia Pacific) Korea South
South India               southindia           (Asia Pacific) South India
West India                westindia            (Asia Pacific) West India
Canada East               canadaeast           (Canada) Canada East
France South              francesouth          (Europe) France South
Germany North             germanynorth         (Europe) Germany North
Norway West               norwaywest           (Europe) Norway West
Switzerland West          switzerlandwest      (Europe) Switzerland West
UK West                   ukwest               (Europe) UK West
UAE Central               uaecentral           (Middle East) UAE Central
Brazil Southeast          brazilsoutheast      (South America) Brazil Southeast

Create Resource Group
#

# Create resouce group
az group create --name aks-playground --location westeurope

List Available Kubernetes Version
#

# List available Kubernetes versions
az aks get-versions --location westeurope -o table

# Shell output
KubernetesVersion    IsPreview    Upgrades                 SupportPlan
-------------------  -----------  -----------------------  --------------------------------------
1.30.0               True         None available           KubernetesOfficial
1.29.4                            1.30.0                   KubernetesOfficial
1.29.2                            1.29.4, 1.30.0           KubernetesOfficial
1.28.9                            1.29.2, 1.29.4           KubernetesOfficial
1.28.5                            1.28.9, 1.29.2, 1.29.4   KubernetesOfficial
1.27.13                           1.28.5, 1.28.9           KubernetesOfficial, AKSLongTermSupport
1.27.9                            1.27.13, 1.28.5, 1.28.9  KubernetesOfficial, AKSLongTermSupport

Create Kubernetes Cluster
#

Default region

If no region is specified, Azure defaults to using the region of the resource group.

# Create Kubernetes cluster
az aks create \
    --resource-group aks-playground \
    --name aks-cluster-1 \
    --kubernetes-version 1.30.0 \
    --node-count 1 \
    --node-vm-size Standard_DS2_v2 \
    --node-osdisk-size 30 \
    --generate-ssh-keys

# Shell output:
SSH key files '/home/ubuntu/.ssh/id_rsa' and '/home/ubuntu/.ssh/id_rsa.pub' have been generated under ~/.ssh to allow SSH access to the VM. If using machines without permanent storage like Azure Cloud Shell without an attached file share, back up your keys to a safe location
Specific region

If necessary, define the region wherethe cluster is deployed:

az aks create \
    --resource-group aks-playground \
    --name aks-cluster-1 \
    --location northeurope \
    --kubernetes-version 1.30.0 \
    --node-count 1 \
    --node-vm-size Standard_DS2_v2 \
    --node-osdisk-size 30 \
    --generate-ssh-keys
  • --node-count Number of worker nodes. AKS manages the controller nodes, they do not count toward the node count.

  • --generate-ssh-keys Used to access the AKS nodes. Azure CLI checks for the presence of SSH keys in the default location ~/.ssh and generates a new SSH key pair if no keys exist.


Configure Kubectl
#

# Configure Kubectl to use the AKS cluster
az aks get-credentials \
    --resource-group aks-playground \
    --name aks-cluster-1

# Shell output:
Merged "aks-cluster-1" as current context in /home/ubuntu/.kube/config

Verify Cluster Nodes
#

# List nodes
kubectl get nodes

# Shell output:
NAME                                STATUS   ROLES    AGE    VERSION
aks-nodepool1-23540999-vmss000000   Ready    <none>   4m7s   v1.30.0
# List nodes: More details
kubectl get nodes -o wide

# Shell output:
NAME                                STATUS   ROLES    AGE     VERSION   INTERNAL-IP   EXTERNAL-IP   OS-IMAGE             KERNEL-VERSION      CONTAINER-RUNTIME
aks-nodepool1-23540999-vmss000000   Ready    <none>   4m18s   v1.30.0   10.224.0.4    <none>        Ubuntu 22.04.4 LTS   5.15.0-1066-azure   containerd://1.7.15-1



Helm
#

Install Helm
#

# Install Helm with script
curl -fsSL -o get_helm.sh https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 &&
chmod +x get_helm.sh &&
./get_helm.sh
# Verify the installation / check version
helm version

Nginx Ingress
#

Add Helm Chart
#

# Add Helm chart
helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx

# Update package index
helm repo update

Install Nginx Ingress
#

# Install the Nginx ingress controller 
helm install ingress-nginx ingress-nginx/ingress-nginx \
    --namespace ingress-nginx \
    --create-namespace \
    --set controller.service.externalTrafficPolicy=Local

Verify Ingress Resources
#

# List Ingress resources
kubectl get all -n ingress-nginx

# Shell output:
NAME                                            READY   STATUS    RESTARTS   AGE
pod/ingress-nginx-controller-5bfc858768-thxqj   1/1     Running   0          67s

NAME                                         TYPE           CLUSTER-IP     EXTERNAL-IP      PORT(S)                      AGE
service/ingress-nginx-controller             LoadBalancer   10.0.7.167     57.153.157.142   80:31149/TCP,443:30480/TCP   67s
service/ingress-nginx-controller-admission   ClusterIP      10.0.195.163   <none>           443/TCP                      67s

NAME                                       READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/ingress-nginx-controller   1/1     1            1           67s

NAME                                                  DESIRED   CURRENT   READY   AGE
replicaset.apps/ingress-nginx-controller-5bfc858768   1         1         1       67s

Cert Manager
#

Install Cert Manager
#

Find latest release: https://github.com/cert-manager/cert-manager/tags

# Add the Jetstack Helm repository
helm repo add jetstack https://charts.jetstack.io
# Update your local Helm chart repository cache
helm repo update
# Install Cert Manager Custom Resource Definitions (CRDs) 
kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.15.1/cert-manager.crds.yaml
# Install the cert-manager Helm chart: In "ingress-nginx" namespace
helm install cert-manager jetstack/cert-manager \
  --namespace ingress-nginx \
  --version v1.15.1

# Shell output:
NAME: cert-manager
LAST DEPLOYED: Sun Jul 14 16:07:15 2024
NAMESPACE: ingress-nginx
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
cert-manager v1.15.1 has been deployed successfully!

In order to begin issuing certificates, you will need to set up a ClusterIssuer
or Issuer resource (for example, by creating a 'letsencrypt-staging' issuer).

More information on the different types of issuers and how to configure them
can be found in our documentation:

https://cert-manager.io/docs/configuration/

For information on how to configure cert-manager to automatically provision
Certificates for Ingress resources, take a look at the `ingress-shim`
documentation:

https://cert-manager.io/docs/usage/ingress/

Configure Let’s Encrypt ClusterIssuer
#

# Create manifest file
vi cert-manager.yml
# Cluster Issuer
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
  name: letsencrypt-production
spec:
  acme:
    server: https://acme-v02.api.letsencrypt.org/directory
    email: juergen@jklug.work
    privateKeySecretRef:
      name: letsencrypt-production-private-key
    solvers:
    - http01:
        ingress:
          class: nginx
# Apply configuration
kubectl apply -f cert-manager.yml

Find Ingress Public IP
#

# List services
kubectl get svc -n ingress-nginx

# Shell output:
NAME                                 TYPE           CLUSTER-IP     EXTERNAL-IP      PORT(S)                      AGE
cert-manager                         ClusterIP      10.0.26.0      <none>           9402/TCP                     57s
cert-manager-webhook                 ClusterIP      10.0.29.94     <none>           443/TCP                      57s
ingress-nginx-controller             LoadBalancer   10.0.7.167     57.153.157.142   80:31149/TCP,443:30480/TCP   4m1s
ingress-nginx-controller-admission   ClusterIP      10.0.195.163   <none>           443/TCP                      4m1s

Create DNS Entry
#

Create an A record the points to the public IP of the Nginx Ingress LoadBalancer:

# Create DNS entry
57.153.157.142 aks-cluster.jklug.work
# Verify the DNS entry
ping aks-cluster.jklug.work



Example Deployment with TLS Encryption
#

Example Pod & Service
#

# Create deployment
kubectl create deployment my-container --image=jueklu/container-1

# Expose deployment with ClusterIP: So that the container port can be accessed
kubectl expose deployment my-container --port=8888 --target-port=8080 --type=ClusterIP --name=my-container-deployment

Create a Certificate
#

# Create YML file
vi cert-manager-certificate.yml
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
  name: my-certificate
spec:
  secretName: my-certificate-secret
  dnsNames:
    - "aks-cluster.jklug.work"
  issuerRef:
    name: letsencrypt-production
    kind: ClusterIssuer
# Apply configuration
kubectl apply -f cert-manager-certificate.yml 

Verify TLS Certificate
#

# List certificates
kubectl get certificate

# Shell output: Wait till the READY status is "TRUE"
NAME             READY   SECRET                  AGE
my-certificate   False   my-certificate-secret   14s

# Shell output:
NAME             READY   SECRET                  AGE
my-certificate   True    my-certificate-secret   4s
# List certificate details
kubectl describe certificate my-certificate

# List the certificate secret (contains the actual TLS certificate) details
kubectl describe secret my-certificate-secret

Create Ingress for Deployment Service
#

Create an Ingress resources for the service that points to the deployment:

# Create YML file
vi ingress.yml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: my-container-ingress
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
    cert-manager.io/cluster-issuer: letsencrypt-production
spec:
  ingressClassName: nginx
  tls:
  - hosts:
    - "aks-cluster.jklug.work"
    secretName: my-certificate-secret
  rules:
  - host: "aks-cluster.jklug.work"
    http:
      paths:
      - path: /mypath
        pathType: Prefix
        backend:
          service:
            name: my-container-deployment
            port:
              number: 8888
# Apply configuration
kubectl apply -f ingress.yml

Verify Ingress
#

# Verify Ingress
kubectl get ing --namespace ingress-nginx

# Shell output:
NAME                   CLASS   HOSTS                    ADDRESS   PORTS     AGE
my-container-ingress   nginx   aks-cluster.jklug.work             80, 443   37s

Test the Deployment
#

# Curl the DNS name
curl https://aks-cluster.jklug.work/mypath

# Shell output:
jklug.work container :)

Delete Example Deployment Resources
#

# Delete the deployment ingress resource
kubectl delete -f ingress.yml

# Delete the certificate
kubectl delete certificate my-certificate
# Delete the example deployment
kubectl delete deployment my-container

# Delete the service for the deployment
kubectl delete svc my-container-deployment

Delete Azure Resources
#

Delete Kubernetes Cluster
#

# Delete Kubernetes cluster
az aks delete --resource-group aks-playground --name aks-cluster-1 --yes --no-wait

Delete Resource Group
#

# Delete resource group
az group delete --name aks-playground --yes --no-wait

Links #

# Azure Portal
https://portal.azure.com/
# Install Azure CLI
https://learn.microsoft.com/en-us/cli/azure/install-azure-cli

# Azure CLI Commands
https://learn.microsoft.com/en-us/cli/azure/aks?view=azure-cli-latest#az-aks-install-cli

# Deploy AKS Cluster
https://learn.microsoft.com/en-us/azure/aks/learn/quick-kubernetes-deploy-cli
Kubernetes-Cluster - This article is part of a series.
Part 4: This Article