Author : MD TAREQ HASSAN
CD YAML pipeline
Prerequisites
Prject setup
- Create
azure-pipelines-cd.yml
- Although it’s in ‘Pipelines’ folder in solution explorer, there is no physical folder (Visual Studio treats as folder for organization pusposes)
azure-pipelines-cd.yml
will be in root folder of the solution
- Commit and push
azure-pipelines-cd.yml
trigger: none # Since CI completion trigger will be used
pool:
vmImage: ubuntu-latest
resources:
pipelines:
- pipeline: XyzapiPipelineCI
source: 'XyzAPI-Pipeline-CI'
trigger:
branches:
include:
- master
jobs:
# add script job here temporarily for testing
Create pipeline from existing azure-pipelines-cd.yml
Test pipeline completion trigger
A test run of CI pipeline to see if CD pipeline gets triggered after completion of CI pipeline
To deploy to ASK environment, see next section
Deploy to AKS environment
‘AcrPull’ role to kubelet managed identity
- Assign ‘AcrPull’ role to kubelet managed identity (at scope of target ACR) so that AKS can pull images from ACR
- I prefer this approach instead of usinf imagePullSecrets
Variable group
- Create variable group ‘xyz-api-vg’
- Put common variables in the variable group
appGwDnsUrl
: DNS record for the public IP of Application Gateway (i.e. hovermind.com)acrName
: name of ACR (not full url), i.e. if ACR url is ‘myacr.azurecr.io
’, then acrName is ‘myacr’
- Common variables in varibale group can be shared by linking varibale groups to pipelines
Variable group will be linked to pipeline as following
# ... ... ...
variables:
- group: 'xyz-api-vg'
# ... ... ...
Pipeline variables
appName: xyz-api
repositoryName: xyz-api
targetNamespace: devops-demo
apiBaseUri: xyz
Deployment job to deploy K8s manifest file to AKS
- Generate K8s manifest file using powershell task and save it to ‘
$(Agent.TempDirectory)/manifest.yaml
’ - Use KubernetesManifest@0 to deploy from ‘
$(Agent.TempDirectory)/manifest.yaml
’
azure-pipelines-cd.yml
trigger: none # Since CI completion trigger will be used
pool:
vmImage: ubuntu-latest
resources:
pipelines:
- pipeline: XyzapiPipelineCI
source: 'XyzAPI-Pipeline-CI'
trigger:
branches:
include:
- master
variables:
- group: 'xyz-api-vg'
jobs:
- deployment: deployToAKS
displayName: Deploy to AKS
dependsOn: buildAndPushDockerImageJob
environment: 'AKSDemoEnvironment.devops-demo'
strategy:
runOnce:
deploy:
steps:
- powershell: |
'# service
apiVersion: v1
kind: Service
metadata:
name: $(appName)
namespace: $(targetNamespace)
labels:
app: $(appName)
spec:
type: ClusterIP
ports:
- port: 80
targetPort: http
protocol: TCP
name: http
selector:
app: $(appName)
---
# deployment
apiVersion: apps/v1
kind: Deployment
metadata:
name: $(appName)
namespace: $(targetNamespace)
labels:
app: $(appName)
spec:
replicas: 3
selector:
matchLabels:
app: $(appName)
template:
metadata:
labels:
app: $(appName)
spec:
containers:
- name: $(appName)
image: $(acrName).azurecr.io/$(repositoryName):$(Build.BuildId)
ports:
- name: http
containerPort: 80
protocol: TCP
env:
- name: API_BASE_URI
value: $(apiBaseUri)
---
# ingress
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: $(appName)
namespace: $(targetNamespace)
annotations:
kubernetes.io/ingress.class: azure/application-gateway
appgw.ingress.kubernetes.io/backend-path-prefix: "/api/$(apiBaseUri)/"
spec:
rules:
- host: $(appGwDnsUrl)
http:
paths:
- path: /api/$(apiBaseUri)/*
pathType: Prefix
backend:
service:
name: $(appName)
port:
number: 80' | Set-Content $(Agent.TempDirectory)/manifest.yaml
displayName: 'Generate K8s Manifest file'
- task: KubernetesManifest@0
displayName: 'Deploy K8s Manifest to AKS'
inputs:
action: deploy
manifests: '$(Agent.TempDirectory)/manifest.yaml'
Release pipeline using classic editor
- Select pipelines > Releases
- New pipeline > Apply “Azure App Service deployment”
- Set Stage name i.e. “Dev_Test_Release”
- Stages > Click “1 job, 1 task”
- Select “Azure subscription” > Authorize
- App type: “Web App on Windows” > Select “App service name”
- Change “New release pipeline” to desired name i.e. “Dev_Release_Pipeline_1”
- Save > Comment < Save
- Select “Releases” > you can see newly created release pipeline
Setting target artifact to Release Pipeline
- Select Release Pipeline > Edit
- Artifacts > “Add an artifact”
- Source type: “Build” > Select “Project”
- Select “Source (build pipeline)” > Keep “Default version” and “Source alias” as it is
- Save > Comment > Save
Deployment conditions in classic release pipeline
- To enfore requirements
- To set approvers (i.e. QA must approve and only then artifacts can be deployed to Prod stage)
Pre-deployment conditions
Pre-deployment approver
Post-deployment conditions
Post-deployment approver
Delete classic release pipeline
Classic release pipeline trigger
- Releases > Click target release pipeline > Edit
- Artifacts section > Click on Trigger icon (lightning bolt icon)
- Enable “Continous deployement trigger”
- Optionally you can add branch filter
- Save > comment > Save
- Now push a commit to remote > check that release is triggered > check app is depoyed to Azure App Services
Cloning stage in classic release pipeline
- Pipelines > Releases > Select target pipeline
- States > hover over the stage that you want to clone > Click “clone icon”
- Select cloned stage > set “Stage name” i.e. “QA_Stage”
- Click “1 job, 1 task” of QA_Stage
- Set Parameters i.e. using different App service name for QA_Stage (FooAppService_QA)
- Save > Comment > Save
Multiple stages in classic release pipeline
- We can set multiple stages (i.e. Dev, QA, Prod) sequentially
- when Dev stage is completed, QA stage will triggered
- when QA stage is completed, Prod stage will be triggered
- Each stage will deploy to relevant app service (i.e. FooAppService_Dev, FooAppService_QA, FooAppService_Prob)
- Each stage will have pre-deployement condition to set desired triggers, filters etc.
- Creating multiple stages
- Create a stage i.e. Dev and then clone to create other stages
- set parameters of each stage
- set pre-deployement condition of each stage
Release manually in classic release pipeline
- Pipelines > Releases > Select target release pipeline
- (top right) Create release
- Select stage > Enter “Release description”
- Create