Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Canary deployment #125

Merged
merged 60 commits into from
Dec 12, 2019
Merged
Show file tree
Hide file tree
Changes from 51 commits
Commits
Show all changes
60 commits
Select commit Hold shift + click to select a range
675eb22
build image pipeline
Nov 9, 2019
5172ab9
workspace name
Nov 9, 2019
115aade
resource group name
Nov 9, 2019
2067948
canary deployment
Nov 14, 2019
d07f786
canary deployment
Nov 14, 2019
92648cd
canary deployment
Nov 15, 2019
d586f05
Canary deployment
Nov 15, 2019
f094763
Canary deployment
Nov 15, 2019
a49a67b
Canary deployment
Nov 15, 2019
a536533
Canary deployment
Nov 15, 2019
f7ec2e0
workspace name
Dec 9, 2019
487a44d
imgname
Dec 9, 2019
e89d851
start
Dec 9, 2019
3c10b73
Score B
Dec 10, 2019
99d7f26
ScoreB
Dec 10, 2019
a4b59e8
load test script
Dec 10, 2019
0763c03
yml refactor
Dec 10, 2019
7d94315
typo
Dec 10, 2019
cdcdd87
typo
Dec 10, 2019
d2d183a
ScoreB
Dec 10, 2019
4768ed0
typo
Dec 10, 2019
8981039
wrong path
Dec 10, 2019
fcd67c2
scoreA
Dec 10, 2019
8eacbc3
docs update
Dec 10, 2019
1a91b1e
merge with master
Dec 10, 2019
7f5f7a6
merge with master
Dec 10, 2019
1d7b1a9
test
Dec 10, 2019
8c94c5d
merging with master
Dec 10, 2019
370f3eb
multistage
Dec 10, 2019
fc76269
tab
Dec 10, 2019
275d516
test
Dec 10, 2019
bf9de53
container
Dec 10, 2019
51f36b7
test
Dec 10, 2019
06caba0
test
Dec 10, 2019
5c31972
test
Dec 10, 2019
2d7d74c
test
Dec 10, 2019
4dba364
test
Dec 10, 2019
8cb94fd
test
Dec 10, 2019
c64a140
test
Dec 10, 2019
a4436ce
test
Dec 10, 2019
9244c7f
test
Dec 10, 2019
8373ebc
test
Dec 10, 2019
ee16e44
test
Dec 10, 2019
52f907f
test
Dec 10, 2019
4b50d1e
cleaning
Dec 10, 2019
650af1e
doc update
Dec 10, 2019
fd42e35
cleaning
Dec 10, 2019
b9eeb39
linting
Dec 11, 2019
04fee4c
linting
Dec 11, 2019
0733cac
Link to A/B tutorial
Dec 11, 2019
c30e3fc
helm to 3.0.1
dtzar Dec 11, 2019
2722956
Update canary_ab_deployment.md
dtzar Dec 11, 2019
7e8cfb6
Add build badge
dtzar Dec 11, 2019
8036fbf
Comments
Dec 11, 2019
0255c5f
update
Dec 11, 2019
42d3bf6
update
Dec 11, 2019
76d9a75
fix typo
dtzar Dec 12, 2019
b40bfc9
typo
Dec 12, 2019
a20affc
Link to the approvals
Dec 12, 2019
6273c40
typo
Dec 12, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
162 changes: 162 additions & 0 deletions .pipelines/azdo-abtest-pipeline.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
pr: none
trigger:
branches:
include:
- master
paths:
exclude:
- docs/
- environment_setup/
- ml_service/util/create_scoring_image.*
- ml_service/util/smoke_test_scoring_service.py

variables:
- group: 'devopsforai-aml-vg'
- name: 'helmVersion'
value: 'v3.0.1'
- name: 'helmDownloadURL'
value: 'https://get.helm.sh/helm-$HELM_VERSION-linux-amd64.tar.gz'
- name: 'blueReleaseName'
value: 'model-blue'
- name: 'greenReleaseName'
value: 'model-green'
- name: 'SCORE_SCRIPT'
value: 'scoreA.py'


stages:
- stage: 'Building'
jobs:
- job: "Build_Scoring_image"
timeoutInMinutes: 0
pool:
vmImage: 'ubuntu-latest'
container: mcr.microsoft.com/mlops/python:latest
steps:
- task: AzureCLI@1
inputs:
azureSubscription: '$(WORKSPACE_SVC_CONNECTION)'
scriptLocation: inlineScript
inlineScript: |
set -e
export SUBSCRIPTION_ID=$(az account show --query id -o tsv)
python ml_service/util/create_scoring_image.py --output_image_location_file image_location.txt
displayName: 'Create Scoring Image'
name: 'buildscoringimage'

- publish: image_location.txt
artifact: image_location

- publish: $(System.DefaultWorkingDirectory)/charts
artifact: allcharts


- stage: 'Blue_Staging'
jobs:
- deployment: "Deploy_to_Staging"
timeoutInMinutes: 0
environment: abtestenv
strategy:
runOnce:
deploy:
steps:
- script: |
IMAGE_LOCATION="$(cat $(Pipeline.Workspace)/image_location/image_location.txt)"
echo "##vso[task.setvariable variable=IMAGE_LOCATION]$IMAGE_LOCATION"
displayName: 'Get Image Location'
- template: azdo-helm-upgrade.yml
parameters:
chartPath: '$(Pipeline.Workspace)/allcharts/abtest-model'
releaseName: $(blueReleaseName)
overrideValues: 'deployment.name=$(blueReleaseName),deployment.bluegreen=blue,deployment.image.name=$(IMAGE_LOCATION)'

- stage: 'Blue_50'
jobs:
- job: 'Blue_Rollout_50'
displayName: 50 50 rollout to blue environment
timeoutInMinutes: 0
steps:
- template: azdo-helm-upgrade.yml
parameters:
chartPath: '$(System.DefaultWorkingDirectory)/charts/abtest-istio'
releaseName: 'abtest-istio'
overrideValues: 'weight.blue=50,weight.green=50'

- stage: 'Blue_100'
jobs:
- deployment: 'blue_Rollout_100'
timeoutInMinutes: 0
environment: abtestenv
strategy:
runOnce:
deploy:
steps:
- template: azdo-helm-upgrade.yml
parameters:
chartPath: '$(Pipeline.Workspace)/allcharts/abtest-istio'
releaseName: 'abtest-istio'
overrideValues: 'weight.blue=100,weight.green=0'

- stage: 'Rollback'
dependsOn: 'Blue_100'
condition: failed()
jobs:
- deployment: 'Roll_Back'
displayName: 'Roll Back after failure'
environment: abtestenv
strategy:
runOnce:
deploy:
steps:
- template: azdo-helm-upgrade.yml
parameters:
chartPath: '$(Pipeline.Workspace)/allcharts/abtest-istio'
releaseName: 'abtest-istio'
overrideValues: 'weight.blue=0,weight.green=100'

- stage: 'Set_Production_Tag'
dependsOn: 'Blue_100'
condition: succeeded()
jobs:
- deployment: 'green_blue_tagging'
timeoutInMinutes: 0
environment: abtestenv
strategy:
runOnce:
deploy:
steps:
- script: |
IMAGE_LOCATION="$(cat $(Pipeline.Workspace)/image_location/image_location.txt)"
echo "##vso[task.setvariable variable=IMAGE_LOCATION]$IMAGE_LOCATION"
displayName: 'Get Image Location'
- template: azdo-helm-upgrade.yml
parameters:
chartPath: '$(Pipeline.Workspace)/allcharts/abtest-model'
releaseName: $(greenReleaseName)
overrideValues: 'deployment.name=$(greenReleaseName),deployment.bluegreen=green,initialDeployment=true,deployment.image.name=$(IMAGE_LOCATION)'
dtzar marked this conversation as resolved.
Show resolved Hide resolved

- stage: 'Green_100'
jobs:
- job: 'Prod_Rollout_100'
timeoutInMinutes: 0
steps:
- template: azdo-helm-upgrade.yml
parameters:
chartPath: '$(System.DefaultWorkingDirectory)/charts/abtest-istio'
releaseName: 'abtest-istio'
overrideValues: 'weight.blue=0,weight.green=100'

- stage: 'Disable_blue'
condition: always()
jobs:
- job: 'blue_disable'
timeoutInMinutes: 0
steps:
- template: azdo-helm-install.yml
- task: HelmDeploy@0
displayName: 'helm uninstall blue'
inputs:
connectionType: 'Kubernetes Service Connection'
kubernetesServiceConnection: $(K8S_AB_SERVICE_CONNECTION)
command: delete
arguments: $(blueReleaseName) --namespace $(K8S_AB_NAMESPACE)
36 changes: 36 additions & 0 deletions .pipelines/azdo-ci-image.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
pr: none
trigger:
branches:
include:
- master
paths:
include:
- ml_service/util/create_scoring_image.py
- ml_service/util/Dockerfile
- code/scoring/
exclude:
- code/scoring/deployment_config_aci.yml
- code/scoring/deployment_config_aks.yml

pool:
vmImage: 'ubuntu-latest'

container: mcr.microsoft.com/mlops/python:latest

variables:
- group: devopsforai-aml-vg
- name: 'SCORE_SCRIPT'
value: 'scoreB.py'

steps:

- task: AzureCLI@1
inputs:
azureSubscription: '$(WORKSPACE_SVC_CONNECTION)'
scriptLocation: inlineScript
inlineScript: |
set -e
export SUBSCRIPTION_ID=$(az account show --query id -o tsv)
python3 $(Build.SourcesDirectory)/ml_service/util/create_scoring_image.py
displayName: 'Create Scoring Image'

9 changes: 9 additions & 0 deletions .pipelines/azdo-helm-install.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
steps:
- task: Bash@3
displayName: 'Install Helm $(helmVersion)'
inputs:
targetType: inline
script: wget -q $(helmDownloadURL) -O /tmp/$FILENAME && tar -zxvf /tmp/$FILENAME -C /tmp && sudo mv /tmp/linux-amd64/helm /usr/local/bin/helm
env:
HELM_VERSION: $(helmVersion)
FILENAME: helm-$(helmVersion)-linux-amd64.tar.gz
19 changes: 19 additions & 0 deletions .pipelines/azdo-helm-upgrade.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
parameters:
chartPath: ''
releaseName: ''
overrideValues: ''

steps:
- template: azdo-helm-install.yml
- task: HelmDeploy@0
displayName: 'helm upgrade'
inputs:
connectionType: 'Kubernetes Service Connection'
kubernetesServiceConnection: $(K8S_AB_SERVICE_CONNECTION)
command: upgrade
chartType: FilePath
chartPath: ${{ parameters.chartPath }}
releaseName: ${{ parameters.releaseName }}
overrideValues: ${{ parameters.overrideValues }}
install: true
arguments: --namespace $(K8S_AB_NAMESPACE)
4 changes: 3 additions & 1 deletion .pipelines/azdo-variables.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,4 +37,6 @@ variables:
value: 'mltrained'
# Optional. Used by a training pipeline with R on Databricks
- name: DB_CLUSTER_ID
value: ''
value: ''
- name: SCORE_SCRIPT
value: score.py
5 changes: 5 additions & 0 deletions charts/abtest-istio/Chart.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
apiVersion: v1
appVersion: "1.0"
description: A Helm chart for Kubernetes
name: abtest-istio
version: 0.1.0
60 changes: 60 additions & 0 deletions charts/abtest-istio/templates/istio-canary.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
name: mlmodel-gateway
namespace: abtesting
spec:
selector:
istio: ingressgateway
servers:
- port:
number: {{ .Values.ingress.port }}
name: http
protocol: HTTP
hosts:
- "*"
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: mlmodel-virtualservice
namespace: abtesting
spec:
gateways:
- mlmodel-gateway
hosts:
- '*'
http:
- match:
- uri:
prefix: /score
headers:
x-api-version:
exact: 'blue'
route:
- destination:
host: {{ .Values.svc.name }}-blue.abtesting.svc.cluster.local
port:
number: {{ .Values.svc.port }}
- match:
- uri:
prefix: /score
headers:
x-api-version:
exact: 'green'
route:
- destination:
host: {{ .Values.svc.name }}-green.abtesting.svc.cluster.local
port:
number: {{ .Values.svc.port }}
- route:
- destination:
host: {{ .Values.svc.name }}-green.abtesting.svc.cluster.local
port:
number: {{ .Values.svc.port }}
weight: {{ .Values.weight.green }}
- destination:
host: {{ .Values.svc.name }}-blue.abtesting.svc.cluster.local
port:
number: {{ .Values.svc.port }}
weight: {{ .Values.weight.blue }}
15 changes: 15 additions & 0 deletions charts/abtest-istio/values.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
ingress:
port: 80

svc:
port: 5001
name: model-svc


weight:
green: 50
blue: 50

uri:
prefix: /score

5 changes: 5 additions & 0 deletions charts/abtest-model/Chart.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
apiVersion: v1
appVersion: "1.0"
description: A Helm chart for Kubernetes
name: abtest-model
version: 0.1.0
31 changes: 31 additions & 0 deletions charts/abtest-model/templates/deployment.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ .Values.deployment.name }}
namespace: {{ .Values.namespace }}
labels:
app: {{ .Values.appname }}
model_version: {{ .Values.deployment.bluegreen }}
spec:
replicas: 1
selector:
matchLabels:
app: {{ .Values.appname }}
model_version: {{ .Values.deployment.bluegreen }}
template:
metadata:
labels:
app: {{ .Values.appname }}
model_version: {{ .Values.deployment.bluegreen }}
spec:
containers:
- name: {{ .Values.deployment.container.name }}
image: "{{ .Values.deployment.image.name }}"
imagePullPolicy: Always
ports:
- name: http
containerPort: 5001
- name: probe
containerPort: 8086
imagePullSecrets:
- name: aks-secret
13 changes: 13 additions & 0 deletions charts/abtest-model/templates/service.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
apiVersion: v1
kind: Service
metadata:
name: "{{ .Values.svc.name }}-{{ .Values.deployment.bluegreen }}"
namespace: {{ .Values.namespace }}
spec:
selector:
app: {{ .Values.appname }}
model_version: {{ .Values.deployment.bluegreen }}
ports:
- port: {{ .Values.svc.port }}
targetPort: {{ .Values.deployment.container.port }}

18 changes: 18 additions & 0 deletions charts/abtest-model/values.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
namespace: abtesting
appname: model

deployment:
name: model-green
bluegreen: green
container:
name: model
port: 5001
image:
name: amlabtest74c95585.azurecr.io/abtestimg
eedorenko marked this conversation as resolved.
Show resolved Hide resolved
tag: 2
eedorenko marked this conversation as resolved.
Show resolved Hide resolved

svc:
name: model-svc
port: 5001

initialDeployment: false
Loading