Compare commits
2
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
96a019c088 | ||
|
|
b9eec94e60 |
No files matched your search
@@ -1,3 +0,0 @@
|
|||||||
workflows:
|
|
||||||
- name: blue-green
|
|
||||||
path: workflows/bluegreen.yaml
|
|
||||||
+3
-7
@@ -1,5 +1,5 @@
|
|||||||
local env = std.extVar("__ksonnet/environments");
|
local env = std.extVar("__ksonnet/environments");
|
||||||
local params = std.extVar("__ksonnet/params").components["bg-deploy"];
|
local params = std.extVar("__ksonnet/params").components["bg-guestbook"];
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
"apiVersion": "v1",
|
"apiVersion": "v1",
|
||||||
@@ -7,9 +7,7 @@ local params = std.extVar("__ksonnet/params").components["bg-deploy"];
|
|||||||
"metadata": {
|
"metadata": {
|
||||||
"name": params.name,
|
"name": params.name,
|
||||||
"annotations": {
|
"annotations": {
|
||||||
"argocd.argoproj.io/workflow-sync": "blue-green",
|
"argocd.argoproj.io/hook": "Skip",
|
||||||
"argocd.argoproj.io/workflow-param.blue-green.service-name": params.name,
|
|
||||||
"argocd.argoproj.io/workflow-param.blue-green.new-service-manifest": "{{manifest}}",
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"spec": {
|
"spec": {
|
||||||
@@ -31,9 +29,7 @@ local params = std.extVar("__ksonnet/params").components["bg-deploy"];
|
|||||||
"metadata": {
|
"metadata": {
|
||||||
"name": params.name,
|
"name": params.name,
|
||||||
"annotations": {
|
"annotations": {
|
||||||
"argocd.argoproj.io/workflow-sync": "blue-green",
|
"argocd.argoproj.io/hook": "Skip",
|
||||||
"argocd.argoproj.io/workflow-param.blue-green.deployment-name": params.name,
|
|
||||||
"argocd.argoproj.io/workflow-param.blue-green.new-deployment-manifest": "{{manifest}}",
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"spec": {
|
"spec": {
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
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,13 +6,14 @@
|
|||||||
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-deploy": {
|
"bg-guestbook": {
|
||||||
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-deploy",
|
name: "bg-guestbook",
|
||||||
replicas: 3,
|
replicas: 3,
|
||||||
servicePort: 80,
|
servicePort: 80,
|
||||||
type: "LoadBalancer",
|
type: "LoadBalancer",
|
||||||
},
|
},
|
||||||
|
"bg-workflow": {},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
+40
-14
@@ -1,11 +1,13 @@
|
|||||||
# 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, transfering traffic
|
# deployment. Then after upgrading the original deployment to a later version, redirects 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:
|
||||||
@@ -68,30 +70,53 @@ spec:
|
|||||||
|
|
||||||
# end of steps
|
# end of steps
|
||||||
|
|
||||||
# clone deployment creates a "blue" clone of an existing deployment.
|
# clone-deployment creates a "blue" clone of an existing deployment. The string -blue is appended to:
|
||||||
# -blue is appended to the metadata.name, as well as the values in the spec.selector.matchLabels,
|
# - metadata.name
|
||||||
# and spec.template.metadata.labels
|
# - spec.selector.matchLabels
|
||||||
|
# - 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}} > /tmp/original-deploy &&
|
- kubectl get --export -o json deployment.apps/{{workflow.parameters.deployment-name}} > /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)'
|
||||||
/tmp/original-deploy > /tmp/cloned-deploy &&
|
/original-deploy > /cloned-deploy &&
|
||||||
cat /tmp/cloned-deploy &&
|
cat /cloned-deploy &&
|
||||||
kubectl apply -o yaml -f /tmp/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
|
- name: apply-manifest
|
||||||
inputs:
|
inputs:
|
||||||
parameters:
|
parameters:
|
||||||
- name: manifest
|
- name: manifest
|
||||||
resource:
|
artifacts:
|
||||||
action: apply
|
- name: manifest-file
|
||||||
manifest: '{{inputs.parameters.manifest}}'
|
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 -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:
|
||||||
@@ -100,14 +125,15 @@ 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 > /tmp/original-svc &&
|
- kubectl get -n default service {{workflow.parameters.service-name}} --export -o json > /original-svc &&
|
||||||
jq '.spec.selector = (.spec.selector | with_entries(.value+="-blue"))' /tmp/original-svc > /tmp/blue-svc &&
|
jq '.spec.selector = (.spec.selector | with_entries(.value+="-blue"))' /original-svc > /blue-svc &&
|
||||||
kubectl apply -o yaml -f /tmp/blue-svc
|
kubectl apply -o yaml -f /blue-svc
|
||||||
|
|
||||||
- name: delete-deployment
|
- name: delete-deployment
|
||||||
resource:
|
resource:
|
||||||
Reference in new issue
Block a user