Introduction
Deploying applications in a private AKS cluster presents unique challenges, especially when the cluster lacks direct internet access. In such environments, the cluster cannot pull container images from public registries like Docker Hub or Quay.io. Instead, all container images must be sourced from a private ACR accessible within the cluster’s network.
To address this, we need a robust solution that not only synchronizes required images into the ACR but also integrates with Continuous Integration/Continuous Deployment (CI/CD) pipelines and adheres to Software Development Life Cycle (SDLC) best practices. This ensures that all images are reviewed and approved before being imported, enhancing security and compliance.
Table of Contents
Open Table of Contents
Implementation
By leveraging Azure DevOps CI/CD pipelines, we can automate the public image importing process as below.
1. Image Configuration File
The images.txt
file lists all the container images that need to be imported into the private ACR.
Each line specifies the source image and the destination repository within the ACR, separated by =>
. This format allows for easy maintenance and review of the images being imported.
Example images.txt
#registry.k8s.io/ingress-nginx/controller:v1.11.1 => ingress-nginx/controller
#registry.k8s.io/ingress-nginx/kube-webhook-certgen:v1.4.1 => ingress-nginx/kube-webhook-certgen
#quay.io/jetstack/cert-manager-controller:v1.15.2 => jetstack/cert-manager-controller
#quay.io/jetstack/cert-manager-webhook:v1.15.2 => jetstack/cert-manager-webhook
#quay.io/jetstack/cert-manager-cainjector:v1.15.2 => jetstack/cert-manager-cainjector
#docker.io/cloudflare/cloudflared:latest => cloudflare/cloudflared
#mcr.microsoft.com/azuredocs/aks-helloworld:v1 => azuredocs/aks-helloworld
- Source Image: The full path to the image in the public registry, including the tag.
- Destination Repository: The repository path within the ACR where the image will be imported.
- Comments: Lines starting with
#
are treated as comments and ignored by the script.
2. Synchronization Script
The sync-script.sh
script automates the process of importing images listed in images.txt
into the ACR. It reads each line of the configuration file, processes the source and destination information, and uses the Azure CLI to import the images.
View code
#!/bin/bash
# Define the name of your Azure Container Registry
ACR_NAME="$1"
IMAGE_LIST_PATH="$2"
DOCKER_USERNAME="$3"
DOCKER_PASSWORD="$4"
# Read the image list from the specified file
while IFS= read -r IMAGE; do
# Ignore comment lines and empty lines
if [[ $IMAGE == \#* ]] || [[ -z $IMAGE ]]; then
continue
fi
# Split the source and destination using '=>' as the delimiter
# Use parameter expansion to split
SOURCE="${IMAGE%%=>*}"
DESTINATION="${IMAGE##*=>}"
# Trim whitespace from both source and destination
SOURCE=$(echo "$SOURCE" | xargs)
DESTINATION=$(echo "$DESTINATION" | xargs)
# Extract the tag from the source image
if [[ "$SOURCE" == *:* ]]; then
TAG="${SOURCE##*:}"
else
TAG="latest"
fi
# Append the tag to the destination image
DESTINATION_WITH_TAG="$DESTINATION:$TAG"
# Extract the image name from the destination path
IMAGE_NAME=$(basename "$DESTINATION")
# Print a message indicating the import process
echo "Importing $IMAGE_NAME:$TAG from $SOURCE to $DESTINATION_WITH_TAG..."
# Build and execute the az acr import command
# If the source is from docker.io, include username and password
if [[ $SOURCE == docker.io* ]]; then
az acr import --name "$ACR_NAME" --source "$SOURCE" --image "$DESTINATION_WITH_TAG" --username "$DOCKER_USERNAME" --password "$DOCKER_PASSWORD" --force
else
# Otherwise, import without authentication
az acr import --name "$ACR_NAME" --source "$SOURCE" --image "$DESTINATION_WITH_TAG" --force
fi
# Confirm the import completion
echo -e "The $IMAGE_NAME:$TAG has been imported.\n\n"
# Pause for 15 seconds before processing the next image
sleep 15
done < "$IMAGE_LIST_PATH"
3. Azure Pipeline
To streamline the synchronization process, we utilize a CI/CD pipeline. This pipeline is designed to automatically execute the synchronization script whenever there are updates to the images.txt
file, ensuring that all container images in the ACR remain current.
View code
Important Variables:
- The
image-sync
variable group contains theDOCKER_NAME
andDOCKER_TOKEN
, which are essential for accessing Docker Hub and avoiding rate limits. - The
azureSubscription
with a specific Azure service connection name in Azure DevOps. - Replace
acrName
with the actual name of the Azure Container Registry.
Once the pipeline completes successfully, you can verify that all images have been correctly imported into the ACR.
The imported images on ACR repositories
Conclusion
Synchronizing container images for a private AKS cluster without direct internet access requires careful planning and automation. By leveraging a combination of an image configuration file, a synchronization script, and an Azure DevOps CI/CD pipeline, we can:
- Automate the import of necessary images into a private ACR.
- Ensure that all images are reviewed and approved according to SDLC practices.
- Maintain a secure and compliant deployment environment within the private AKS cluster.
This approach not only streamlines the deployment process but also integrates seamlessly with existing development workflows, promoting efficiency and reliability in managing containerized applications.
References
Next
Day 10: Implementing a Helm Deployment CI/CD AzureDevOps Pipeline for a Private AKS Cluster.
In the next article, We will create Helm charts for nginx-ingress and cert-manager, and set up a robust CI/CD pipeline using Azure DevOps for Helm deployments to a private AKS cluster.
Thank You
Thank you for taking the time to read this guide! We hope it has been helpful. Feel free to explore further and happy coding! 🌟✨
Steven | GitHub