Achraf Ben Alaya
No Result
View All Result
  • Home
  • News
  • Blog
    • blazor
    • c#
    • Cloud
      • Azure
    • docker
    • sql
    • xamarin
    • Dapr
    • Tricks, Tips and Fixes
    • General Tips & Fix
  • AI
  • Cloud
  • Motivation
  • Courses
  • About
    • Resume
    • Privacy Policy
SUBSCRIBE
  • Home
  • News
  • Blog
    • blazor
    • c#
    • Cloud
      • Azure
    • docker
    • sql
    • xamarin
    • Dapr
    • Tricks, Tips and Fixes
    • General Tips & Fix
  • AI
  • Cloud
  • Motivation
  • Courses
  • About
    • Resume
    • Privacy Policy
No Result
View All Result
Achraf Ben Alaya
No Result
View All Result
ADVERTISEMENT
Home Blog Cloud Azure

Part 5-C : Using Azure DevOps, Automate Your CI/CD Pipeline and Your Deployments

Creating our CI/CD Pipelines for Azure Kubernetes Service (AKS)

achraf by achraf
May 2, 2023
in Azure, Blog, Cloud
7 min read
0
Part 5-A : Using Azure DevOps, Automate Your CI/CD Pipeline and Your Deployments
0
SHARES
647
VIEWS
Share on FacebookShare on Twitter

As we continue writing this serie , we come to the part were we are going to deploy our apps to our Azure Kubernetes  service using Azure Devops

This article is a part of a series:

  1. Part 1 : How to setup nginx reverse proxy for aspnet core apps with and without Docker compose
  2. Part 2 :How to setup nginx reverse proxy && load balancer for aspnet core apps with Docker and azure kubernetes service
  3. Part 3 : How to configure an ingress controller using TLS/SSL for the Azure Kubernetes Service (AKS)
  4. Part 4 : switch to Azure Container Registry from Docker Hub
  5. Part 5-A: Using Azure DevOps, Automate Your CI/CD Pipeline and Your Deployments (setup)
  6. Part 5-B : Using Azure DevOps, Automate Your CI/CD Pipeline and Your Deployments (terraform)
  7. Part 5-C : Using Azure DevOps, Automate Your CI/CD Pipeline and Your Deployments (deployments)
  8. Part 6 : Using Github, Automate Your CI/CD Pipeline and Your Deployments
  9. Possible methods to reduce your costs .

    Introduction :

    Auto deploying deployment using Azure DevOps and AKS (Azure Kubernetes Service) is a powerful way to streamline the deployment process for containerized applications. With Azure DevOps, you can create automated deployment pipelines that trigger a release whenever new code is pushed to a repository. AKS provides a fully managed Kubernetes service that simplifies the deployment and operation of containerized applications, ensuring high availability, scalability, and security for production deployments. By integrating Azure DevOps with AKS, you can deploy applications to the cluster with a single click, and easily roll back deployments to a previous version if needed. This approach enables teams to deliver updates and new features to production more quickly and reliably, while minimizing the risk of errors or downtime.

    In different blog post we have seen how to deploy our infrastructure , right now , one more step , is auto deploying to aks .

    Prerequisites

    – Created service connection for azure container registry .
    – Create a service connection for azure Kubernetes service .

1-Creating our Pipeline

Our pipeline will have different steps and we will explain each part in this part:

Full pipline

name: $(BuildDefinitionName)_$(date:yyyyMMdd)$(rev:.r)

trigger:
  branches:
    include:
    - dev
    - master
   
#our agent
pool:
    name: demo-privateAgentDevOps
    demands: 
    - Agent.Name -equals DevopsAg01

variables:
    imageRepository: 'mydotnetappdemo'
    containerRegistry: 'crdvsaksdevfc01.azurecr.io'
    containerRegistryspn: 'acr-aks-001'
    dockerfilePath: '$(Build.SourcesDirectory)/Dockerfile'
    hostnamesManifest: '$(Pipeline.Workspace)/manifests/01-backend-acr-deployment.yml'
    frontendManifest: '$(Pipeline.Workspace)/manifests/01-nginx-frontend.yml'
    ingressManifest: '$(Pipeline.Workspace)/manifests/ingress.yml'
    imagePullSecret: 'context-auth'
    kubernetesServiceConnection: 'aksspn'
    hostnameImageRepo: 'mydotnetappdemo'
    tag: '$(Build.BuildId)'
stages:
- stage: Build
  condition: and(succeeded(), ne(variables['Build.Reason'], 'PullRequest'))
  displayName: Build and push Docker image to ACR
  
  jobs:
  - job: Build
    displayName: Restore project
    steps:  
    - task: DotNetCoreCLI@2
      displayName: 'Restore packages'
      inputs:
          command: 'restore'
          projects: '**/*.csproj'

    - task: Docker@2
      displayName: 'Build Project'
      inputs:
          containerRegistry: $(containerRegistryspn)
          repository: '$(imageRepository)'
          command: 'build'
          Dockerfile: '**/Dockerfile'
          tags: |
            $(tag)
            latest
    - task: Docker@2
      displayName: 'Push Docker image'
      inputs:
          containerRegistry: $(containerRegistryspn)
          repository: $(imageRepository)
          command: 'push'
          tags: |
            $(tag)
            latest
    - task: PublishPipelineArtifact@1
      inputs:
          targetPath: '$(Pipeline.Workspace)/s/manifests'
          artifact: 'manifests'
          publishLocation: 'pipeline'


- stage: DEV
  condition: and(succeeded(), ne(variables['Build.Reason'], 'PullRequest'))
  displayName: DEV - Deploy API to AKS 
  dependsOn: Build
  jobs:
  - deployment: Deploy
    displayName: Deploy DEV

    environment: 'development'
    strategy:
      runOnce:
        deploy:
          steps:
          
          - task: DownloadPipelineArtifact@2
            inputs:
              buildType: 'current'
              artifactName: 'manifests'
              targetPath: '$(Pipeline.Workspace)/manifests'

          - task: replacetokens@3
            displayName: Replace Build tag & environment values
            inputs:
              rootDirectory: '$(Pipeline.Workspace)/manifests/'
              targetFiles: '*.yml'
              encoding: 'utf-8'
              writeBOM: true
              actionOnMissing: 'warn'
              keepToken: false
              tokenPrefix: '#{'
              tokenSuffix: '}#'
              useLegacyPattern: false
              enableTransforms: false
              enableTelemetry: false          
          - task: KubernetesManifest@1
            inputs:
                action: 'createSecret'
                connectionType: 'azureResourceManager'
                azureSubscriptionConnection: 'terrafromspn'
                azureResourceGroup: 'azure-loves-terraform-2023'
                kubernetesCluster: 'achrafdoingaks'
                secretType: 'dockerRegistry'
                secretName: $(imagePullSecret)
                dockerRegistryEndpoint: 'acr-aks-001'
          - task: KubernetesManifest@0
            displayName: Deploy to Kubernetes cluster
            inputs:
              action: deploy
              kubernetesServiceConnection: $(kubernetesServiceConnection)
              namespace: 'ingress'
              manifests: |
                $(hostnamesManifest)
                $(ingressManifest)
              imagePullSecrets: |
                $(imagePullSecret)
              containers: |
                $(containerRegistry)/$(hostnameImageRepo):$(tag)
          - task: PublishBuildArtifacts@1
            displayName: Publish Swaggers
            inputs:
              PathtoPublish: '$(Build.ArtifactStagingDirectory)'
              ArtifactName: 'swagger-dev'
              publishLocation: 'Container'

What will the pipeline look like :

Now let’s understand this pipeline by task :

The first stage of our pipeline will consist of building our project (dotnet ) , building the docker image and pushing it to our azure container registry .

The second part , will run only if the first stage is done with success .

replacetokens@3

Replace Tokens is an extension that can be used in Azure DevOps, which provides the possibility to replace tokens in the code files with variables values (which can be configured in the Pipelines Library) during the execution of the CI/CD process.
In our case , in each time we build our solution we want to update our deployment the build tag of the new image that we have created .
You may say why not using latest ?

When deploying Docker images, it is generally recommended to avoid using the “latest” tag and instead use a specific version or build tag. The reason for this is that the “latest” tag is a floating tag that always points to the most recent build of an image. This can lead to unpredictability and make it difficult to manage and track the versions of deployed images.

By using a specific version or build tag, you can ensure that the same version of an image is deployed consistently across different environments, such as development, testing, and production. This can also make it easier to troubleshoot issues and roll back to a previous version if necessary.

When using build tags, it is common to use a versioning scheme that includes the version number and the Git commit hash or build ID. This enables you to track the version of the code that was used to build the image and ensure consistency across different environments.

In summary, it is generally better to use a specific version or build tag when deploying Docker images, rather than relying on the “latest” tag, to ensure consistency and predictability in your deployment process.

          - task: replacetokens@3
            displayName: Replace Build tag & environment values
            inputs:
              rootDirectory: '$(Pipeline.Workspace)/manifests/'
              targetFiles: '*.yml'
              encoding: 'utf-8'
              writeBOM: true
              actionOnMissing: 'warn'
              keepToken: false
              tokenPrefix: '#{'
              tokenSuffix: '}#'
              useLegacyPattern: false
              enableTransforms: false
              enableTelemetry: false   


this task will replace the code inside the #{Build.BuildId}# below inside our deployement file with the build id of our pipline

      containers:
        - name: backend-restapp
          image: crdvsaksdevfc01.azurecr.io/mydotnetappdemo:#{Build.BuildId}#

KubernetesManifest@1

The Create imagePullSecret parameter in the KubernetesManifest@1 task in Azure DevOps is used to create a Docker registry credential secret in the target Kubernetes cluster.

When you deploy a container to a Kubernetes cluster, the container image is typically stored in a Docker registry, such as Docker Hub or Azure Container Registry. In order to pull the image from the registry, the Kubernetes cluster needs to be authenticated with the registry using credentials, such as a username and password or a token.

To avoid storing these credentials in plaintext in the Kubernetes manifest, you can create an image pull secret that contains the credentials and reference it in the manifest file. The KubernetesManifest@1 task in Azure DevOps can create this image pull secret for you by specifying the Docker registry server, username, and password as task inputs.

When you enable the Create imagePullSecret parameter in the KubernetesManifest@1 task, Azure DevOps creates a secret in the target Kubernetes cluster that contains the Docker registry credentials. The secret is named “acr-credentials” and can be referenced in the manifest file using the “imagePullSecrets” field.

By creating the image pull secret with Azure DevOps, you can securely authenticate your Kubernetes cluster with your Docker registry and ensure that your container images can be pulled successfully during deployment.

- task: KubernetesManifest@1
  inputs:
      action: 'createSecret'
      connectionType: 'azureResourceManager'
      azureSubscriptionConnection: 'terrafromspn'
      azureResourceGroup: 'azure-loves-terraform-2023'
      kubernetesCluster: 'achrafdoingaks'
      secretType: 'dockerRegistry'
      secretName: $(imagePullSecret)
      dockerRegistryEndpoint: 'acr-aks-001'

Now time to deploy :

- task: KubernetesManifest@0
  displayName: Deploy to Kubernetes cluster
  inputs:
    action: deploy
    kubernetesServiceConnection: $(kubernetesServiceConnection)
    namespace: 'ingress'
    manifests: |
      $(hostnamesManifest)
      $(ingressManifest)
    imagePullSecrets: |
      $(imagePullSecret)
    containers: |
      $(containerRegistry)/$(hostnameImageRepo):$(tag)

The “action: deploy” in the “KubernetesManifest@0” task in Azure DevOps specifies that the task should deploy the Kubernetes manifests to the target cluster.

The “KubernetesManifest@0” task is used to deploy Kubernetes manifests, which are YAML or JSON files that define Kubernetes resources, such as pods, services, and deployments. The task allows you to specify the manifest files, the Kubernetes cluster to deploy to, and various other parameters that control the deployment process.

When the “action” parameter is set to “deploy”, the task will create or update the resources in the target Kubernetes cluster based on the manifest files provided. If a resource does not exist, it will be created. If a resource already exists, it will be updated to match the configuration in the manifest file.

The “KubernetesManifest@0” task can also be configured to perform other actions, such as deleting resources or running custom kubectl commands. However, when the “action” parameter is set to “deploy”, the task will only deploy the manifests to the target cluster.

Overall, the “KubernetesManifest@0” task with “action: deploy” is a powerful tool for automating the deployment of Kubernetes resources in Azure DevOps, allowing you to quickly and easily deploy your applications and services to a Kubernetes cluster.

2-Creating Our Manifest Files

In our pipeline we are deploying an Ingress and a deployment.

Deployment file :

apiVersion: apps/v1
kind: Deployment
metadata:
  name: backend-restapp
  namespace: ingress 
  labels:
    app: backend-restapp
    tier: backend 
spec:
  replicas: 2
  selector:
    matchLabels:
      app: backend-restapp
  template:
    metadata:
      labels:
        app: backend-restapp
        tier: backend 
    spec: 
      containers:
        - name: backend-restapp
          image: crdvsaksdevfc01.azurecr.io/mydotnetappdemo:#{Build.BuildId}#
          ports:
            - containerPort: 5000        
---
apiVersion: v1
kind: Service
metadata:
  name: my-backend-service ## VERY VERY IMPORTANT - NGINX PROXYPASS needs this name
  labels:
    app: backend-restapp
    tier: backend   
spec:
  selector:
    app: backend-restapp
  ports:
    - name: http
      port: 5000 # ClusterIP Service Port
      targetPort: 5000 # Container Port
  type: ClusterIP    

Ingress

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: webapp
  namespace: ingress
  annotations:
    nginx.ingress.kubernetes.io/ssl-redirect: "false"
    nginx.ingress.kubernetes.io/use-regex: "true"
    nginx.ingress.kubernetes.io/rewrite-target: /\
spec:
  ingressClassName: nginx
  rules:
  - http:
      paths:
      - backend:
          service:
            name: my-backend-service
            port:
              number: 5000
        path: /
        pathType: Prefix
      - backend:
          service:
            name: my-backend-service
            port:
              number: 5000
        path: /acr(/|$)(.*)
        pathType: Prefix                           
  - host: himhelloworld.com
    http:
      paths:
      - backend:
          service:
            name: my-backend-service
            port: 
              number: 5000
        path: /
        pathType: Prefix
      - backend:
          service:
            name: my-backend-service
            port: 
              number: 5000
        path: /acr
        pathType: Prefix    

Results :

ShareTweet
Previous Post

15 E-books that focus on learning Microsoft Azure Cloud

Next Post

What if we can check the cost of Azure resources in a juts few seconds

Related Posts

AI

Model Context Protocol (MCP): The Future of AI Integration

April 21, 2025
110
Azure

Step-by-Step Guide: Azure Front Door + Storage Account Static Website + Custom Domain with Terraform

March 11, 2025
231
Network Security & Route Tables – Checking NSGs, route tables, and service endpoints for a targeted VNET or Subnet
Azure

Network Security & Route Tables – Checking NSGs, route tables, and service endpoints for a targeted VNET or Subnet

February 3, 2025
137
Understanding Generative AI and RAG Benefits
AI

Understanding Generative AI and RAG Benefits

January 12, 2025
96
Azure Communication Services Email Sending Simplified: From Setup to Execution and Monitoring
Azure

Azure Communication Services Email Sending Simplified: From Setup to Execution and Monitoring

December 8, 2024
1.6k
PowerShell Automation for Azure Networks: Detailed VNET and Subnet Analysis
Azure

PowerShell Automation for Azure Networks: Detailed VNET and Subnet Analysis

November 2, 2024
502
Next Post
What if we can check the cost of Azure resources in a juts few seconds

What if we can check the cost of Azure resources in a juts few seconds

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

Terraform

Certifications

Microsoft certified trainer (MCT)

Recommended

PowerShell Automation for Azure Networks: Detailed VNET and Subnet Analysis

PowerShell Automation for Azure Networks: Detailed VNET and Subnet Analysis

November 2, 2024
502
Reading Excel file in Azure Web Apps

Reading Excel file in Azure Web Apps

December 1, 2020
1.8k
Migrate and modernize your applications on Azure

Migrate and modernize your applications on Azure – Part 2.0 (Proxy Function)

April 3, 2021
1.2k
Elevate Your API Reliability: Deep Dive into Load Balancing and Failover Strategies in Azure API Management

Elevate Your API Reliability: Deep Dive into Load Balancing and Failover Strategies in Azure API Management

December 29, 2023
353
Deploy azure function from Docker Hub CI/CD

Deploy azure function from Docker Hub CI/CD

April 27, 2020
320
Run background tasks with WebJobs in Azure App Service

Run background tasks with WebJobs in Azure App Service

August 21, 2021
2k
Facebook Twitter LinkedIn Youtube

Model Context Protocol (MCP): The Future of AI Integration

April 21, 2025

Step-by-Step Guide: Azure Front Door + Storage Account Static Website + Custom Domain with Terraform

March 11, 2025
Network Security & Route Tables – Checking NSGs, route tables, and service endpoints for a targeted VNET or Subnet

Network Security & Route Tables – Checking NSGs, route tables, and service endpoints for a targeted VNET or Subnet

February 3, 2025

Categories

  • AI (2)
  • Apps (1)
  • Azure (63)
  • blazor (2)
  • Blog (91)
  • c# (7)
  • Cloud (65)
  • Courses (3)
  • Dapr (4)
  • docker (4)
  • Games (1)
  • General Tips & Fix (1)
  • Home (1)
  • Kubernetes Service (AKS) (1)
  • motivation (2)
  • Motivation (3)
  • News (9)
  • Resume (1)
  • sql (4)
  • Terrafrom (1)
  • Tricks, Tips and Fixes (4)
  • xamarin (5)
No Result
View All Result
  • Home
  • News
  • Blog
    • blazor
    • c#
    • Cloud
      • Azure
    • docker
    • sql
    • xamarin
    • Dapr
    • Tricks, Tips and Fixes
    • General Tips & Fix
  • AI
  • Cloud
  • Motivation
  • Courses
  • About
    • Resume
    • Privacy Policy