Author SHA1 Message Date
Jesse Suen f43209e902 Update blue-green-deploy app version to v0.2 2018-07-03 21:56:25 -07:00
Jesse Suen bdc5d18f9f Add blue green deployment example app 2018-07-03 21:46:43 -07:00
5 changed files with 26 additions and 66 deletions

No files matched your search

+3
View File
@@ -0,0 +1,3 @@
workflows:
- name: blue-green
path: workflows/bluegreen.yaml
@@ -1,5 +1,5 @@
local env = std.extVar("__ksonnet/environments"); local env = std.extVar("__ksonnet/environments");
local params = std.extVar("__ksonnet/params").components["bg-guestbook"]; local params = std.extVar("__ksonnet/params").components["bg-deploy"];
[ [
{ {
"apiVersion": "v1", "apiVersion": "v1",
@@ -7,7 +7,9 @@ local params = std.extVar("__ksonnet/params").components["bg-guestbook"];
"metadata": { "metadata": {
"name": params.name, "name": params.name,
"annotations": { "annotations": {
"argocd.argoproj.io/hook": "Skip", "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": { "spec": {
@@ -29,7 +31,9 @@ local params = std.extVar("__ksonnet/params").components["bg-guestbook"];
"metadata": { "metadata": {
"name": params.name, "name": params.name,
"annotations": { "annotations": {
"argocd.argoproj.io/hook": "Skip", "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": { "spec": {
@@ -1,20 +0,0 @@
local bgGuestbook = std.extVar("__ksonnet/components")["bg-guestbook"];
local bgGuestbookSvc = bgGuestbook[0];
local bgGuestbookDeploy = bgGuestbook[1];
local parseYaml = std.native("parseYaml");
local bgWorkflow = parseYaml(importstr 'wf/bluegreen.yaml')[0];
[
bgWorkflow + {
spec +: {
arguments +: {
parameters : [
{name: "deployment-name", value: bgGuestbookDeploy.metadata.name},
{name: "service-name", value: bgGuestbookSvc.metadata.name},
{name: "new-deployment-manifest", value: std.manifestJson(bgGuestbookDeploy)},
{name: "new-service-manifest", value: std.manifestJson(bgGuestbookSvc)},
],
},
},
}
]
@@ -6,14 +6,13 @@
components: { components: {
// Component-level parameters, defined initially from 'ks prototype use ...' // Component-level parameters, defined initially from 'ks prototype use ...'
// Each object below should correspond to a component in the components/ directory // Each object below should correspond to a component in the components/ directory
"bg-guestbook": { "bg-deploy": {
containerPort: 80, containerPort: 80,
image: "gcr.io/heptio-images/ks-guestbook-demo:0.2", image: "gcr.io/heptio-images/ks-guestbook-demo:0.2",
name: "bg-guestbook", name: "bg-deploy",
replicas: 3, replicas: 3,
servicePort: 80, servicePort: 80,
type: "LoadBalancer", type: "LoadBalancer",
}, },
"bg-workflow": {},
}, },
} }
@@ -1,13 +1,11 @@
# This workflow performs a "blue-green" deployment, while preserving the original deployment object # 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 # 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, redirects traffic # deployment, then after upgrading the original deployment to a later version, transfering traffic
# back to the original (now upgraded) deployment. # back to the original (now upgraded) deployment.
apiVersion: argoproj.io/v1alpha1 apiVersion: argoproj.io/v1alpha1
kind: Workflow kind: Workflow
metadata: metadata:
generateName: k8s-bluegreen- generateName: k8s-bluegreen-
annotations:
argocd.argoproj.io/hook: Sync
spec: spec:
entrypoint: k8s-bluegreen entrypoint: k8s-bluegreen
arguments: arguments:
@@ -70,53 +68,30 @@ spec:
# end of steps # end of steps
# clone-deployment creates a "blue" clone of an existing deployment. The string -blue is appended to: # clone deployment creates a "blue" clone of an existing deployment.
# - metadata.name # -blue is appended to the metadata.name, as well as the values in the spec.selector.matchLabels,
# - spec.selector.matchLabels # and spec.template.metadata.labels
# - spec.template.metadata.labels
- name: clone-deployment - name: clone-deployment
container: container:
image: argoproj/argoexec:v2.1.1 image: argoproj/argoexec:v2.1.1
command: [sh, -c, -x] command: [sh, -c, -x]
args: args:
- kubectl get --export -o json deployment.apps/{{workflow.parameters.deployment-name}} > /original-deploy && - kubectl get --export -o json deployment.apps/{{workflow.parameters.deployment-name}} > /tmp/original-deploy &&
jq -r '.metadata.name+="-blue" | 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.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)' .spec.selector.matchLabels += (.spec.selector.matchLabels | to_entries | map(select(.key != "applications.argoproj.io/app-name")) | map(.value+="-blue") | from_entries)'
/original-deploy > /cloned-deploy && /tmp/original-deploy > /tmp/cloned-deploy &&
cat /cloned-deploy && cat /tmp/cloned-deploy &&
kubectl apply -o yaml -f /cloned-deploy kubectl apply -o yaml -f /tmp/cloned-deploy
# apply-manifest takes a kubernetes manifest and carrys over the app-name label (if present)
# before running `kubectl apply`. The label is used by ArgoCD for monitoring.
- name: apply-manifest - name: apply-manifest
inputs: inputs:
parameters: parameters:
- name: manifest - name: manifest
artifacts: resource:
- name: manifest-file action: apply
path: /manifest manifest: '{{inputs.parameters.manifest}}'
raw:
data: '{{inputs.parameters.manifest}}'
container:
image: argoproj/argoexec:v2.1.1
command: [sh, -c, -x]
args:
- cp /manifest /manifest-new &&
APP_NAME=$(kubectl get -n default -f /manifest-new -o json | jq -r '.metadata.labels."applications.argoproj.io/app-name"') &&
if [ "$APP_NAME" != "null" ]; then
jq -r --arg APP_NAME "$APP_NAME" '.metadata.labels."applications.argoproj.io/app-name" = $APP_NAME' /manifest-new > /manifest-new.tmp &&
mv /manifest-new.tmp /manifest-new &&
if [ "$(jq -r .spec.template.metadata.labels /manifest-new)" != "null" ]; then
jq -r --arg APP_NAME "$APP_NAME" '.spec.template.metadata.labels."applications.argoproj.io/app-name" = $APP_NAME' /manifest-new > /manifest-new.tmp &&
mv /manifest-new.tmp /manifest-new ;
fi ;
fi &&
cat /manifest-new &&
kubectl apply -f /manifest-new
# wait-deployment-ready waits for a deployment to become fully deployed and ready, using the
# `kubectl rollout` command
- name: wait-deployment-ready - name: wait-deployment-ready
inputs: inputs:
parameters: parameters:
@@ -125,15 +100,14 @@ spec:
image: argoproj/argoexec:v2.1.1 image: argoproj/argoexec:v2.1.1
command: [kubectl, rollout, status, --watch=true, 'deployments/{{inputs.parameters.deployment-name}}'] command: [kubectl, rollout, status, --watch=true, 'deployments/{{inputs.parameters.deployment-name}}']
# patch-service updates the service selector labels to point to the "blue" deployment
- name: patch-service - name: patch-service
container: container:
image: argoproj/argoexec:v2.1.1 image: argoproj/argoexec:v2.1.1
command: [sh, -c, -x] command: [sh, -c, -x]
args: args:
- kubectl get -n default service {{workflow.parameters.service-name}} --export -o json > /original-svc && - kubectl get -n default service {{workflow.parameters.service-name}} --export -o json > /tmp/original-svc &&
jq '.spec.selector = (.spec.selector | with_entries(.value+="-blue"))' /original-svc > /blue-svc && jq '.spec.selector = (.spec.selector | with_entries(.value+="-blue"))' /tmp/original-svc > /tmp/blue-svc &&
kubectl apply -o yaml -f /blue-svc kubectl apply -o yaml -f /tmp/blue-svc
- name: delete-deployment - name: delete-deployment
resource: resource: