Modern cloud-native applications rely heavily on automated Continuous Integration and Continuous Deployment (CI/CD) pipelines. When deploying containerized workloads to Azure Kubernetes Service (AKS), a robust pipeline requires a secure, frictionless bridge between your source control, your container registry, and your orchestration cluster.
This end-to-end guide walks through provisioning an Azure Container Registry (ACR), linking it to an existing AKS cluster, generating Service Principal credentials securely, and automating the entire build-to-deploy lifecycle using GitHub Actions.
Prerequisites
Before diving into the configuration, ensure you have the following in place:
An active Azure Subscription.
Azure CLI installed and authenticated (az login).
An existing Azure resource group (e.g., linux-admin-course).
An existing Azure Kubernetes Service cluster (e.g., mudassar-kubi-course).
Phase 1: Provisioning the Azure Container Registry (ACR)
The Azure Container Registry is a managed, private Docker registry used to securely store and manage your container images.
1.1 Overcoming the Registration Error
A common pitfall when creating an ACR for the first time in a new subscription is encountering a MissingSubscriptionRegistration error. Azure requires explicit registration of the Microsoft.ContainerRegistry namespace before provisioning.
Register the provider using the Azure CLI:
Bash
az provider register --namespace Microsoft.ContainerRegistry
Verify the registration status. Wait until the output returns "Registered" before proceeding:
Bash
az provider show -n Microsoft.ContainerRegistry --query "registrationState"
1.2 Creating the Registry
Once registered, you can provision the registry. Note that ACR names must be globally unique across all of Azure and consist solely of lowercase alphanumeric characters.
Bash
az acr create --resource-group linux-admin-course --name mudassaracr99 --sku Basic
The Basic SKU is highly cost-effective and provides the necessary throughput and storage for development and standard CI/CD workflows.
Phase 2: Integrating ACR with AKS
Kubernetes needs permission to pull private images from your registry. Instead of manually creating and managing Kubernetes Image Pull Secrets, Azure provides a streamlined command to establish a secure, role-based assignment (acrpull) between the AKS cluster's managed identity and the ACR.
Execute the following command to attach the registry to your cluster:
Bash
az aks update -n mudassar-kubi-course -g linux-admin-course --attach-acr mudassaracr99
Once this process completes, any Pod deployed to your AKS cluster can seamlessly authenticate and pull images from mudassaracr99.azurecr.io.
Phase 3: Provisioning an Identity for GitHub Actions
To allow GitHub Actions to build Docker images, push them to your ACR, and apply manifests to your AKS cluster, it requires an Azure identity. We achieve this by creating an Azure Active Directory Service Principal assigned the Contributor role, tightly scoped to your specific resource group.
The Shell Syntax Trap
When referencing documentation, subscription IDs are often wrapped in angle brackets (e.g., <your-subscription-id>). If executed verbatim in Bash, the < and > symbols are interpreted as file redirection operators, leading to frustrating "No such file or directory" errors.
First, retrieve your exact Azure Subscription ID:
Bash
az account show --query id --output tsv
Next, construct the Service Principal command by injecting the ID directly, stripping away any brackets:
Bash
az ad sp create-for-rbac --name "GitHub-Actions-AKS" --role contributor --scopes /subscriptions/YOUR_SUBSCRIPTION_ID_HERE/resourceGroups/linux-admin-course --json-auth
Securing the Credentials
The output of this command is a JSON object containing sensitive keys (clientId, clientSecret, subscriptionId, and tenantId).
Immediately copy this JSON payload. Navigate to your GitHub repository, go to Settings > Secrets and variables > Actions, and create a new repository secret named AZURE_CREDENTIALS. Paste the entire JSON block as the value.
Phase 4: Automating with GitHub Actions
With the infrastructure provisioned and authorized, the final step is defining the CI/CD pipeline. This workflow will trigger on code pushes, build a new container image, push it to ACR, and update the AKS cluster.
Create a file in your repository at .github/workflows/deploy.yml with the following configuration:
YAML
name: Build and Deploy to AKS
on:
push:
branches:
- main
env:
ACR_NAME: mudassaracr99
CLUSTER_NAME: mudassar-kubi-course
RESOURCE_GROUP: linux-admin-course
IMAGE_NAME: my-aks-app
jobs:
build-and-deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout Code
uses: actions/checkout@v4
- name: Azure Login
uses: azure/login@v2
with:
creds: ${{ secrets.AZURE_CREDENTIALS }}
- name: Login to ACR
run: az acr login --name ${{ env.ACR_NAME }}
- name: Build and Push Docker Image
run: |
docker build -t ${{ env.ACR_NAME }}.azurecr.io/${{ env.IMAGE_NAME }}:${{ github.sha }} .
docker push ${{ env.ACR_NAME }}.azurecr.io/${{ env.IMAGE_NAME }}:${{ github.sha }}
- name: Set AKS Context
uses: azure/aks-set-context@v3
with:
resource-group: ${{ env.RESOURCE_GROUP }}
cluster-name: ${{ env.CLUSTER_NAME }}
- name: Deploy to AKS
uses: Azure/k8s-deploy@v5
with:
manifests: |
manifests/deployment.yaml
manifests/service.yaml
images: |
${{ env.ACR_NAME }}.azurecr.io/${{ env.IMAGE_NAME }}:${{ github.sha }}
Architecture of the Pipeline
This pipeline relies on Git commit hashes (${{ github.sha }}) to tag Docker images. This practice guarantees immutability and traceability. During the final deployment step, the Azure/k8s-deploy action intelligently parses your deployment.yaml manifest, finds the base image reference, and injects the specific commit hash tag. This ensures Kubernetes recognizes a change in the manifest and gracefully rolls out the new pods with zero downtime.
Join the conversation! Your thoughts help the community grow.