Full CI/CD with Terraform & Kubernetes on Azure


Below is a detailed, step‐by‐step guide for a "Full CI/CD with Terraform & Kubernetes on Azure" project. This project demonstrates how to provision an Azure Kubernetes Service (AKS) cluster using Terraform, deploy a containerized application onto the cluster using Kubernetes manifests, and automate the deployment process with a CI/CD pipeline using GitHub Actions.
Project Overview
Objectives:
Use Terraform to provision an AKS cluster on Azure.
Deploy a containerized application (e.g., a simple Nginx deployment) on the AKS cluster.
Set up a CI/CD pipeline using GitHub Actions to automate build and deployment.
Tools & Technologies:
Terraform (Infrastructure as Code)
Azure Kubernetes Service (AKS)
Docker & Kubernetes (Containerization & Orchestration)
GitHub Actions (CI/CD Automation)
Azure CLI
Step 1: Provision an AKS Cluster with Terraform
1.1. Create a Project Directory
Open your terminal and run:
mkdir terraform-aks-ci-cd
cd terraform-aks-ci-cd
1.2. Create Your Terraform Configuration File
Create a file named main.tf
and paste the following code. This configuration will:
Create a resource group.
Provision an AKS cluster with a default node pool.
Output the Kubernetes configuration for later use.
terraform {
required_providers {
azurerm = {
source = "hashicorp/azurerm"
version = "~> 4.23.0"
}
kubernetes = {
source = "hashicorp/kubernetes"
version = "~> 2.0"
}
}
}
provider "azurerm" {
features {}
}
# Create a Resource Group
resource "azurerm_resource_group" "aks_rg" {
name = "aks-resource-group"
location = "East US"
}
# Create an AKS Cluster
resource "azurerm_kubernetes_cluster" "aks_cluster" {
name = "myAKSCluster"
location = azurerm_resource_group.aks_rg.location
resource_group_name = azurerm_resource_group.aks_rg.name
dns_prefix = "myaks"
default_node_pool {
name = "default"
node_count = 2
vm_size = "Standard_DS2_v2"
}
identity {
type = "SystemAssigned"
}
}
# Output the Kubernetes configuration
output "kube_config" {
value = azurerm_kubernetes_cluster.aks_cluster.kube_config_raw
sensitive = true
}
1.3. Initialize and Apply Terraform
Run these commands in your terminal:
terraform init
terraform plan
terraform apply -auto-approve
Step 2: Deploy a Containerized Application on AKS
2.1. Create Kubernetes Deployment and Service Files
Create a folder called k8s
in your project directory. Inside the folder, create two files: deployment.yaml
and service.yaml
.
Deployment File: k8s/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app
labels:
app: my-app
spec:
replicas: 2
selector:
matchLabels:
app: my-app
template:
metadata:
labels:
app: my-app
spec:
containers:
- name: my-app
image: nginx:latest
ports:
- containerPort: 80
Service File: k8s/service.yaml
apiVersion: v1
kind: Service
metadata:
name: my-app-service
spec:
type: LoadBalancer
ports:
- port: 80
targetPort: 80
selector:
app: my-app
2.2. Deploy to AKS
Before deploying, ensure your local kubectl
is configured to talk to your new AKS cluster. Run:
az aks get-credentials --resource-group aks-resource-group --name myAKSCluster --overwrite-existing
Then, deploy your app:
kubectl apply -f k8s/deployment.yaml
kubectl apply -f k8s/service.yaml
Check if Pods Are Running
kubectl get pods
Check if Services Are Running
kubectl get services
Step 3: Set Up a CI/CD Pipeline with GitHub Actions
3.1. Create a GitHub Actions Workflow
In your repository, create a folder .github/workflows
and a file named ci-cd-pipeline.yml
with the following content:
name: CI/CD Pipeline
on:
push:
branches:
- main
jobs:
build-deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout Code
uses: actions/checkout@v2
- name: Login to Azure
uses: azure/login@v1
with:
creds: ${{ secrets.AZURE_CREDENTIALS }}
- name: Set up Kubectl
uses: azure/setup-kubectl@v1
with:
version: 'latest'
- name: Update kubeconfig for AKS
run: |
az aks get-credentials --resource-group aks-resource-group --name myAKSCluster --overwrite-existing
- name: Deploy to Kubernetes
run: |
kubectl apply -f k8s/deployment.yaml
kubectl apply -f k8s/service.yaml
Step 4: Verify and Monitor
Check Kubernetes Status:
Run:kubectl get pods kubectl get services
Monitor Pipeline Execution:
Check the status in GitHub Actions (or Jenkins if you use that) to ensure all steps complete successfully.
To destroy your Terraform-managed resources on Azure, follow these steps:
Open Your Terminal
Ensure you're in the directory where your Terraform files (main.tf
, variables.tf
, etc.) are located.
Run Terraform Destroy Command
Execute the following command to remove all resources:
terraform destroy
This will show a list of resources that will be deleted and ask for confirmation.
Confirm the Destruction
Type yes
when prompted:
Do you really want to destroy all resources?
Enter a value: yes
Terraform will then proceed to delete all the resources.
(Optional) Force Destroy Without Confirmation
If you want to destroy everything without being asked for confirmation, use:
terraform destroy -auto-approve
Verify Resources Are Deleted
After the process completes, confirm everything is removed by running:
az resource list --resource-group aks-resource-group --output table
If no resources are listed, the destruction was successful.
Conclusion
This project demonstrates an end-to-end CI/CD pipeline on Azure using Terraform for infrastructure provisioning and Kubernetes for container orchestration. With this project, I automated the deployment of a containerised application, integrated continuous delivery using GitHub Actions, and built a scalable, resilient cloud-native infrastructure. This hands-on experience not only reduces deployment times significantly but also optimizes resource usage and reliability.
Subscribe to my newsletter
Read articles from Chigozie Ozoemena directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by

Chigozie Ozoemena
Chigozie Ozoemena
Hi there! 👋 I'm Daniel Ozoemena, a passionate Cloud Solution Architect and DevOps Engineer dedicated to building scalable, secure, and innovative cloud solutions. With hands-on experience in Azure, AWS, and Google Cloud Platform, I specialize in deploying infrastructure as code, automating workflows, and optimizing system reliability. Driven by a love for problem-solving, I constantly explore new technologies and best practices to deliver impactful results. Beyond the cloud, I enjoy mentoring, blogging about tech insights, and contributing to open-source projects. When I'm not automating deployments or creating secure virtual networks, you can find me playing chess, learning about AI, or brainstorming solutions to real-world challenges. Let’s connect and grow together on this tech journey! 🚀