Add blue green deployment example app
This commit is contained in:
parent
852d97d96e
commit
bdc5d18f9f
|
@ -0,0 +1,4 @@
|
|||
/lib
|
||||
/.ksonnet/registries
|
||||
/app.override.yaml
|
||||
/.ks_environment
|
|
@ -0,0 +1,11 @@
|
|||
apiVersion: 0.1.0
|
||||
environments:
|
||||
default:
|
||||
destination:
|
||||
namespace: default
|
||||
server: https://kubernetes.default.svc
|
||||
k8sVersion: v1.10.0
|
||||
path: default
|
||||
kind: ksonnet.io/app
|
||||
name: blue-green-deploy
|
||||
version: 0.0.1
|
|
@ -0,0 +1,3 @@
|
|||
workflows:
|
||||
- name: blue-green
|
||||
path: workflows/bluegreen.yaml
|
|
@ -0,0 +1,68 @@
|
|||
local env = std.extVar("__ksonnet/environments");
|
||||
local params = std.extVar("__ksonnet/params").components["bg-deploy"];
|
||||
[
|
||||
{
|
||||
"apiVersion": "v1",
|
||||
"kind": "Service",
|
||||
"metadata": {
|
||||
"name": params.name,
|
||||
"annotations": {
|
||||
"argocd.argoproj.io/workflow-sync": "blue-green",
|
||||
"argocd.argoproj.io/workflow-param.blue-green.service-name": params.name,
|
||||
"argocd.argoproj.io/workflow-param.blue-green.new-service-manifest": "{{manifest}}",
|
||||
},
|
||||
},
|
||||
"spec": {
|
||||
"ports": [
|
||||
{
|
||||
"port": params.servicePort,
|
||||
"targetPort": params.containerPort
|
||||
}
|
||||
],
|
||||
"selector": {
|
||||
"app": params.name
|
||||
},
|
||||
"type": params.type
|
||||
}
|
||||
},
|
||||
{
|
||||
"apiVersion": "apps/v1beta2",
|
||||
"kind": "Deployment",
|
||||
"metadata": {
|
||||
"name": params.name,
|
||||
"annotations": {
|
||||
"argocd.argoproj.io/workflow-sync": "blue-green",
|
||||
"argocd.argoproj.io/workflow-param.blue-green.deployment-name": params.name,
|
||||
"argocd.argoproj.io/workflow-param.blue-green.new-deployment-manifest": "{{manifest}}",
|
||||
},
|
||||
},
|
||||
"spec": {
|
||||
"replicas": params.replicas,
|
||||
"selector": {
|
||||
"matchLabels": {
|
||||
"app": params.name
|
||||
},
|
||||
},
|
||||
"template": {
|
||||
"metadata": {
|
||||
"labels": {
|
||||
"app": params.name
|
||||
}
|
||||
},
|
||||
"spec": {
|
||||
"containers": [
|
||||
{
|
||||
"image": params.image,
|
||||
"name": params.name,
|
||||
"ports": [
|
||||
{
|
||||
"containerPort": params.containerPort
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
|
@ -0,0 +1,18 @@
|
|||
{
|
||||
global: {
|
||||
// User-defined global parameters; accessible to all component and environments, Ex:
|
||||
// replicas: 4,
|
||||
},
|
||||
components: {
|
||||
// Component-level parameters, defined initially from 'ks prototype use ...'
|
||||
// Each object below should correspond to a component in the components/ directory
|
||||
"bg-deploy": {
|
||||
containerPort: 80,
|
||||
image: "gcr.io/heptio-images/ks-guestbook-demo:0.1",
|
||||
name: "bg-deploy",
|
||||
replicas: 3,
|
||||
servicePort: 80,
|
||||
type: "LoadBalancer",
|
||||
},
|
||||
},
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
local components = std.extVar("__ksonnet/components");
|
||||
components + {
|
||||
// Insert user-specified overrides here.
|
||||
}
|
|
@ -0,0 +1,2 @@
|
|||
{
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
local base = import "base.libsonnet";
|
||||
// uncomment if you reference ksonnet-lib
|
||||
// local k = import "k.libsonnet";
|
||||
|
||||
base + {
|
||||
// Insert user-specified overrides here. For example if a component is named \"nginx-deployment\", you might have something like:\n")
|
||||
// "nginx-deployment"+: k.deployment.mixin.metadata.labels({foo: "bar"})
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
local params = std.extVar("__ksonnet/params");
|
||||
local globals = import "globals.libsonnet";
|
||||
local envParams = params + {
|
||||
components +: {
|
||||
// Insert component parameter overrides here. Ex:
|
||||
// guestbook +: {
|
||||
// name: "guestbook-dev",
|
||||
// replicas: params.global.replicas,
|
||||
// },
|
||||
},
|
||||
};
|
||||
|
||||
{
|
||||
components: {
|
||||
[x]: envParams.components[x] + globals, for x in std.objectFields(envParams.components)
|
||||
},
|
||||
}
|
|
@ -0,0 +1,124 @@
|
|||
# This workflow performs a "blue-green" deployment, while preserving the original deployment object
|
||||
# and name. It accomplishes this by temporarily redirecting traffic to a *clone* of the original
|
||||
# deployment, then after upgrading the original deployment to a later version, transfering traffic
|
||||
# back to the original (now upgraded) deployment.
|
||||
apiVersion: argoproj.io/v1alpha1
|
||||
kind: Workflow
|
||||
metadata:
|
||||
generateName: k8s-bluegreen-
|
||||
spec:
|
||||
entrypoint: k8s-bluegreen
|
||||
arguments:
|
||||
parameters:
|
||||
- name: deployment-name
|
||||
- name: service-name
|
||||
- name: new-deployment-manifest
|
||||
- name: new-service-manifest
|
||||
|
||||
templates:
|
||||
- name: k8s-bluegreen
|
||||
steps:
|
||||
# 1. Create a parallel Kubernetes deployment with tweaks to name and selectors
|
||||
- - name: create-blue-deployment
|
||||
template: clone-deployment
|
||||
|
||||
# 2. Wait for parallel deployment to become ready
|
||||
- - name: wait-for-blue-deployment
|
||||
template: wait-deployment-ready
|
||||
arguments:
|
||||
parameters:
|
||||
- name: deployment-name
|
||||
value: '{{workflow.parameters.deployment-name}}-blue'
|
||||
|
||||
# 3. Patch the named service to point to the parallel deployment app
|
||||
- - name: switch-service-to-blue-deployment
|
||||
template: patch-service
|
||||
|
||||
# 4. Update the original deployment (receiving no traffic) with a new version
|
||||
- - name: apply-green-deployment
|
||||
template: apply-manifest
|
||||
arguments:
|
||||
parameters:
|
||||
- name: manifest
|
||||
value: '{{workflow.parameters.new-deployment-manifest}}'
|
||||
|
||||
# 5. Wait for the original deployment, now updated, to become ready
|
||||
- - name: wait-for-green-deployment
|
||||
template: wait-deployment-ready
|
||||
arguments:
|
||||
parameters:
|
||||
- name: deployment-name
|
||||
value: '{{workflow.parameters.deployment-name}}'
|
||||
|
||||
# dummy approval step for demo purposes. Sleeps for 30 seconds
|
||||
- - name: approve
|
||||
template: approve
|
||||
|
||||
# 6. Patch the named service to point to the original, now updated app
|
||||
- - name: switch-service-to-green-deployment
|
||||
template: apply-manifest
|
||||
arguments:
|
||||
parameters:
|
||||
- name: manifest
|
||||
value: '{{workflow.parameters.new-service-manifest}}'
|
||||
|
||||
# 7. Remove the cloned deployment (no longer receiving traffic)
|
||||
- - name: delete-cloned-deployment
|
||||
template: delete-deployment
|
||||
|
||||
# end of steps
|
||||
|
||||
# clone deployment creates a "blue" clone of an existing deployment.
|
||||
# -blue is appended to the metadata.name, as well as the values in the spec.selector.matchLabels,
|
||||
# and spec.template.metadata.labels
|
||||
- name: clone-deployment
|
||||
container:
|
||||
image: argoproj/argoexec:v2.1.1
|
||||
command: [sh, -c, -x]
|
||||
args:
|
||||
- kubectl get --export -o json deployment.apps/{{workflow.parameters.deployment-name}} > /tmp/original-deploy &&
|
||||
jq -r '.metadata.name+="-blue" |
|
||||
.spec.template.metadata.labels += (.spec.template.metadata.labels | to_entries | map(select(.key != "applications.argoproj.io/app-name")) | map(.value+="-blue") | from_entries) |
|
||||
.spec.selector.matchLabels += (.spec.selector.matchLabels | to_entries | map(select(.key != "applications.argoproj.io/app-name")) | map(.value+="-blue") | from_entries)'
|
||||
/tmp/original-deploy > /tmp/cloned-deploy &&
|
||||
cat /tmp/cloned-deploy &&
|
||||
kubectl apply -o yaml -f /tmp/cloned-deploy
|
||||
|
||||
- name: apply-manifest
|
||||
inputs:
|
||||
parameters:
|
||||
- name: manifest
|
||||
resource:
|
||||
action: apply
|
||||
manifest: '{{inputs.parameters.manifest}}'
|
||||
|
||||
- name: wait-deployment-ready
|
||||
inputs:
|
||||
parameters:
|
||||
- name: deployment-name
|
||||
container:
|
||||
image: argoproj/argoexec:v2.1.1
|
||||
command: [kubectl, rollout, status, --watch=true, 'deployments/{{inputs.parameters.deployment-name}}']
|
||||
|
||||
- name: patch-service
|
||||
container:
|
||||
image: argoproj/argoexec:v2.1.1
|
||||
command: [sh, -c, -x]
|
||||
args:
|
||||
- kubectl get -n default service {{workflow.parameters.service-name}} --export -o json > /tmp/original-svc &&
|
||||
jq '.spec.selector = (.spec.selector | with_entries(.value+="-blue"))' /tmp/original-svc > /tmp/blue-svc &&
|
||||
kubectl apply -o yaml -f /tmp/blue-svc
|
||||
|
||||
- name: delete-deployment
|
||||
resource:
|
||||
action: delete
|
||||
manifest: |
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: {{workflow.parameters.deployment-name}}-blue
|
||||
|
||||
- name: approve
|
||||
container:
|
||||
image: argoproj/argoexec:v2.1.1
|
||||
command: [sleep, "30"]
|
Loading…
Reference in New Issue