Jesse Suen
6 years ago
18 changed files with 5 additions and 311 deletions
@ -1,4 +0,0 @@ |
|||
/lib |
|||
/.ksonnet/registries |
|||
/app.override.yaml |
|||
/.ks_environment |
@ -1,11 +0,0 @@ |
|||
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-workflow |
|||
version: 0.0.1 |
@ -1,64 +0,0 @@ |
|||
local env = std.extVar("__ksonnet/environments"); |
|||
local params = std.extVar("__ksonnet/params").components["bg-guestbook"]; |
|||
[ |
|||
{ |
|||
"apiVersion": "v1", |
|||
"kind": "Service", |
|||
"metadata": { |
|||
"name": params.name, |
|||
"annotations": { |
|||
"argocd.argoproj.io/hook": "Skip", |
|||
}, |
|||
}, |
|||
"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/hook": "Skip", |
|||
}, |
|||
}, |
|||
"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 |
|||
} |
|||
] |
|||
} |
|||
] |
|||
} |
|||
} |
|||
} |
|||
} |
|||
] |
@ -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)}, |
|||
], |
|||
}, |
|||
}, |
|||
} |
|||
] |
@ -1,19 +0,0 @@ |
|||
{ |
|||
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-guestbook": { |
|||
containerPort: 80, |
|||
image: "gcr.io/heptio-images/ks-guestbook-demo:0.2", |
|||
name: "bg-guestbook", |
|||
replicas: 3, |
|||
servicePort: 80, |
|||
type: "LoadBalancer", |
|||
}, |
|||
"bg-workflow": {}, |
|||
}, |
|||
} |
@ -1,150 +0,0 @@ |
|||
# 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, redirects traffic |
|||
# back to the original (now upgraded) deployment. |
|||
apiVersion: argoproj.io/v1alpha1 |
|||
kind: Workflow |
|||
metadata: |
|||
generateName: k8s-bluegreen- |
|||
annotations: |
|||
argocd.argoproj.io/hook: Sync |
|||
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. The string -blue is appended to: |
|||
# - metadata.name |
|||
# - spec.selector.matchLabels |
|||
# - 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}} > /original-deploy && |
|||
jq -r '.metadata.name+="-blue" | |
|||
.spec.template.metadata.labels += (.spec.template.metadata.labels | to_entries | map(select(.key != "app.kubernetes.io/instance")) | map(.value+="-blue") | from_entries) | |
|||
.spec.selector.matchLabels += (.spec.selector.matchLabels | to_entries | map(select(.key != "app.kubernetes.io/instance")) | map(.value+="-blue") | from_entries)' |
|||
/original-deploy > /cloned-deploy && |
|||
cat /cloned-deploy && |
|||
kubectl apply -o yaml -f /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 |
|||
inputs: |
|||
parameters: |
|||
- name: manifest |
|||
artifacts: |
|||
- name: manifest-file |
|||
path: /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 -f /manifest-new -o json | jq -r '.metadata.labels."app.kubernetes.io/instance"') && |
|||
if [ "$APP_NAME" != "null" ]; then |
|||
jq -r --arg APP_NAME "$APP_NAME" '.metadata.labels."app.kubernetes.io/instance" = $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."app.kubernetes.io/instance" = $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 |
|||
inputs: |
|||
parameters: |
|||
- name: deployment-name |
|||
container: |
|||
image: argoproj/argoexec:v2.1.1 |
|||
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 |
|||
container: |
|||
image: argoproj/argoexec:v2.1.1 |
|||
command: [sh, -c, -x] |
|||
args: |
|||
- kubectl get service {{workflow.parameters.service-name}} --export -o json > /original-svc && |
|||
jq '.spec.selector = (.spec.selector | with_entries(.value+="-blue"))' /original-svc > /blue-svc && |
|||
kubectl apply -o yaml -f /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"] |
@ -1,4 +0,0 @@ |
|||
local components = std.extVar("__ksonnet/components"); |
|||
components + { |
|||
// Insert user-specified overrides here. |
|||
} |
@ -1,2 +0,0 @@ |
|||
{ |
|||
} |
@ -1,8 +0,0 @@ |
|||
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"}) |
|||
} |
@ -1,17 +0,0 @@ |
|||
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) |
|||
}, |
|||
} |
@ -1,11 +0,0 @@ |
|||
apiVersion: v1 |
|||
kind: Service |
|||
metadata: |
|||
name: guestbook-ui |
|||
spec: |
|||
ports: |
|||
- port: 80 |
|||
targetPort: 80 |
|||
selector: |
|||
app: guestbook-ui |
|||
type: LoadBalancer |
Loading…
Reference in new issue