From 9c7c339de766f4254382c205f9e2e566e3a97ef3 Mon Sep 17 00:00:00 2001 From: AADITYA201 <115879999+AADITYA201@users.noreply.github.com> Date: Wed, 4 Feb 2026 13:30:42 +0530 Subject: [PATCH] Add AKS CI/CD pipeline and deployment manifests --- azure-pipelines.yml | 114 ++++++++++++++++++++++++++++++++------------ docs/aks-cicd.md | 106 ++++++++++++++++++++++++++++++++++++++++ k8s/deployment.yaml | 47 ++++++++++++++++++ k8s/ingress.yaml | 19 ++++++++ k8s/namespace.yaml | 6 +++ k8s/service.yaml | 15 ++++++ 6 files changed, 276 insertions(+), 31 deletions(-) create mode 100644 docs/aks-cicd.md create mode 100644 k8s/deployment.yaml create mode 100644 k8s/ingress.yaml create mode 100644 k8s/namespace.yaml create mode 100644 k8s/service.yaml diff --git a/azure-pipelines.yml b/azure-pipelines.yml index eab58bd9..824f27c0 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -1,36 +1,88 @@ trigger: -- main + - main pool: - vmImage: 'ubuntu-latest' + vmImage: "ubuntu-latest" variables: - nodeVersion: '18.x' - -steps: -# Install Node -- task: NodeTool@0 - inputs: - versionSpec: '$(nodeVersion)' - displayName: 'Install Node.js' - -# Build Backend -- script: | - cd backend - npm install - npm test || echo "No tests" - displayName: 'Backend Build & Test' - -# Build Frontend -- script: | - cd frontend - npm install - npm install -g @angular/cli - ng build --configuration=production - displayName: 'Angular Build' - -# Publish Artifact -- task: PublishBuildArtifacts@1 - inputs: - PathtoPublish: 'frontend/dist' - ArtifactName: 'angular-build' + dockerRegistryServiceConnection: "ACR-SERVICE-CONNECTION" + kubernetesServiceConnection: "AKS-SERVICE-CONNECTION" + imageRepository: "angular-nodejs-example" + containerRegistry: "myacr.azurecr.io" + dockerfilePath: "$(Build.SourcesDirectory)/Dockerfile" + tag: "$(Build.BuildId)" + namespace: "dev" + +stages: + - stage: Build + displayName: Build and Push + jobs: + - job: Build + displayName: Build and Push Image + steps: + - task: Docker@2 + displayName: Build and push image + inputs: + containerRegistry: "$(dockerRegistryServiceConnection)" + repository: "$(imageRepository)" + command: "buildAndPush" + Dockerfile: "$(dockerfilePath)" + tags: | + $(tag) + + - stage: Deploy + displayName: Deploy to AKS + dependsOn: Build + jobs: + - job: Deploy + displayName: Deploy manifests + steps: + - task: Kubernetes@1 + displayName: Ensure namespace + inputs: + connectionType: "Kubernetes Service Connection" + kubernetesServiceEndpoint: "$(kubernetesServiceConnection)" + command: "apply" + useConfigurationFile: true + configuration: "k8s/namespace.yaml" + + - task: Kubernetes@1 + displayName: Apply deployment + inputs: + connectionType: "Kubernetes Service Connection" + kubernetesServiceEndpoint: "$(kubernetesServiceConnection)" + namespace: "$(namespace)" + command: "apply" + useConfigurationFile: true + configuration: "k8s/deployment.yaml" + + - task: Kubernetes@1 + displayName: Apply service + inputs: + connectionType: "Kubernetes Service Connection" + kubernetesServiceEndpoint: "$(kubernetesServiceConnection)" + namespace: "$(namespace)" + command: "apply" + useConfigurationFile: true + configuration: "k8s/service.yaml" + + - task: Kubernetes@1 + displayName: Apply ingress + inputs: + connectionType: "Kubernetes Service Connection" + kubernetesServiceEndpoint: "$(kubernetesServiceConnection)" + namespace: "$(namespace)" + command: "apply" + useConfigurationFile: true + configuration: "k8s/ingress.yaml" + + - task: Kubernetes@1 + displayName: Update image + inputs: + connectionType: "Kubernetes Service Connection" + kubernetesServiceEndpoint: "$(kubernetesServiceConnection)" + namespace: "$(namespace)" + command: "set" + arguments: >- + image deployment/angular-nodejs-example + angular-nodejs-example=$(containerRegistry)/$(imageRepository):$(tag) diff --git a/docs/aks-cicd.md b/docs/aks-cicd.md new file mode 100644 index 00000000..d55f637c --- /dev/null +++ b/docs/aks-cicd.md @@ -0,0 +1,106 @@ +# AKS CI/CD + Managed Prometheus/Grafana (Dev) + +This guide sets up Azure DevOps CI/CD, Azure Container Registry (ACR), Azure Kubernetes Service (AKS), and Azure Managed Prometheus/Grafana for a dev environment sized for ~10 users. + +## Architecture + +- Azure DevOps Pipeline builds and pushes the Docker image to ACR. +- AKS pulls the image and runs the deployment in the `dev` namespace. +- Azure Managed Prometheus/Grafana monitors AKS and the workload. + +## Prerequisites + +- Azure subscription with **Owner** or **Contributor** access. +- Azure DevOps project with permissions to create service connections. +- Azure CLI, kubectl, and Helm installed locally (for provisioning). + +## Suggested Sizing (Dev / ~10 Users) + +- AKS node pool: **2x Standard_B2s** (2 vCPU, 4 GB RAM each) +- Kubernetes deployment replicas: **2** (defined in `k8s/deployment.yaml`) + +## Provisioning (Example) + +> Replace names and regions as needed. + +```bash +# Resource group +az group create --name rg-angular-nodejs-dev --location eastus + +# Container registry +az acr create --resource-group rg-angular-nodejs-dev --name myacr --sku Basic + +# AKS cluster +az aks create \ + --resource-group rg-angular-nodejs-dev \ + --name aks-angular-nodejs-dev \ + --node-count 2 \ + --node-vm-size Standard_B2s \ + --enable-managed-identity \ + --attach-acr myacr + +# Fetch kubeconfig +az aks get-credentials --resource-group rg-angular-nodejs-dev --name aks-angular-nodejs-dev +``` + +## Enable Azure Managed Prometheus/Grafana + +```bash +# Enable Azure Monitor for containers (includes managed Prometheus) +az aks enable-addons \ + --resource-group rg-angular-nodejs-dev \ + --name aks-angular-nodejs-dev \ + --addons monitoring + +# Create a Managed Grafana instance +az grafana create \ + --name grafana-angular-nodejs-dev \ + --resource-group rg-angular-nodejs-dev +``` + +> In Grafana, connect to the managed Prometheus workspace created by the AKS monitoring addon. + +## Azure DevOps Service Connections + +Create the following service connections: + +1. **ACR Service Connection** + - Type: Docker Registry + - Registry: `myacr.azurecr.io` + - Name used in pipeline: `ACR-SERVICE-CONNECTION` + +2. **AKS Service Connection** + - Type: Kubernetes + - Cluster: `aks-angular-nodejs-dev` + - Namespace: `dev` + - Name used in pipeline: `AKS-SERVICE-CONNECTION` + +Update the values in `azure-pipelines.yml` if you choose different names. + +## Pipeline Overview + +- **Build stage**: Docker build and push to ACR. +- **Deploy stage**: Apply namespace, deployment, service, ingress, and set image tag. + +## Kubernetes Manifests + +- `k8s/namespace.yaml` +- `k8s/deployment.yaml` +- `k8s/service.yaml` +- `k8s/ingress.yaml` + +### Update the ingress host + +Set your DNS host in `k8s/ingress.yaml`: + +```yaml +host: angular-nodejs-example.dev.example.com +``` + +If you are using a public domain, create a DNS A record pointing to the AKS ingress public IP. + +## Optional Enhancements + +- Add an HPA for CPU-based autoscaling. +- Add TLS with cert-manager for HTTPS. +- Add Azure Monitor alerts for latency and error rate. diff --git a/k8s/deployment.yaml b/k8s/deployment.yaml new file mode 100644 index 00000000..58611843 --- /dev/null +++ b/k8s/deployment.yaml @@ -0,0 +1,47 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: angular-nodejs-example + namespace: dev + labels: + app: angular-nodejs-example +spec: + replicas: 2 + selector: + matchLabels: + app: angular-nodejs-example + template: + metadata: + labels: + app: angular-nodejs-example + annotations: + prometheus.io/scrape: "true" + prometheus.io/port: "3080" + spec: + containers: + - name: angular-nodejs-example + image: myacr.azurecr.io/angular-nodejs-example:latest + ports: + - containerPort: 3080 + env: + - name: NODE_ENV + value: "production" + resources: + requests: + cpu: "100m" + memory: "128Mi" + limits: + cpu: "500m" + memory: "256Mi" + readinessProbe: + httpGet: + path: / + port: 3080 + initialDelaySeconds: 5 + periodSeconds: 10 + livenessProbe: + httpGet: + path: / + port: 3080 + initialDelaySeconds: 15 + periodSeconds: 20 diff --git a/k8s/ingress.yaml b/k8s/ingress.yaml new file mode 100644 index 00000000..8b733bf9 --- /dev/null +++ b/k8s/ingress.yaml @@ -0,0 +1,19 @@ +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: angular-nodejs-example + namespace: dev + annotations: + kubernetes.io/ingress.class: nginx +spec: + rules: + - host: angular-nodejs-example.dev.example.com + http: + paths: + - path: / + pathType: Prefix + backend: + service: + name: angular-nodejs-example + port: + number: 80 diff --git a/k8s/namespace.yaml b/k8s/namespace.yaml new file mode 100644 index 00000000..fc37c439 --- /dev/null +++ b/k8s/namespace.yaml @@ -0,0 +1,6 @@ +apiVersion: v1 +kind: Namespace +metadata: + name: dev + labels: + environment: dev diff --git a/k8s/service.yaml b/k8s/service.yaml new file mode 100644 index 00000000..0a019dd6 --- /dev/null +++ b/k8s/service.yaml @@ -0,0 +1,15 @@ +apiVersion: v1 +kind: Service +metadata: + name: angular-nodejs-example + namespace: dev + labels: + app: angular-nodejs-example +spec: + type: ClusterIP + selector: + app: angular-nodejs-example + ports: + - name: http + port: 80 + targetPort: 3080