11 changed files with 0 additions and 338 deletions
			
			
		| @ -1,4 +0,0 @@ | |||
| /lib | |||
| /.ksonnet/registries | |||
| /app.override.yaml | |||
| /.ks_environment | |||
| @ -1,15 +0,0 @@ | |||
| apiVersion: 0.3.0 | |||
| environments: | |||
|   default: | |||
|     destination: | |||
|       namespace: blue-green-deploy | |||
|       server: https://kubernetes.default.svc | |||
|     k8sVersion: v1.10.0 | |||
|     path: default | |||
| kind: ksonnet.io/app | |||
| name: blue-green-deploy | |||
| registries: | |||
|   incubator: | |||
|     protocol: github | |||
|     uri: github.com/ksonnet/parts/tree/master/incubator | |||
| version: 0.0.1 | |||
| @ -1,71 +0,0 @@ | |||
| #!bin/bash | |||
| 
 | |||
| DEPLOYMENT_NAME=$(echo "${DEPLOY_MANIFEST}" | jq -r '.metadata.name') | |||
| SERVICE_NAME=$(echo "${SERVICE_MANIFEST}" | jq -r '.metadata.name') | |||
| 
 | |||
| # 1. Check if the deployment exists. If it doesn't exist, this is the initial deployment and we | |||
| # can simply deploy without blue-green. Add the app label using jq | |||
| out=$(kubectl get --export -o json deployment.apps/${DEPLOYMENT_NAME} 2>&1) | |||
| if [ $? -ne 0 ]; then | |||
|   if [[ "${out}" =~ "NotFound" ]] ; then | |||
|     echo "Initial deployment" | |||
|     echo ${DEPLOY_MANIFEST} | \ | |||
|       jq ".metadata.labels += {\"app.kubernetes.io/instance\": \"${APPNAME}\"}" | \ | |||
|       kubectl apply -o yaml -f - || exit 1 | |||
|     echo ${SERVICE_MANIFEST} | \ | |||
|       jq ".metadata.labels += {\"app.kubernetes.io/instance\": \"${APPNAME}\"}" | \ | |||
|       kubectl apply -o yaml -f - || exit 1 | |||
|     exit 0 | |||
|   fi | |||
|   echo "Failed to get deployment: ${out}" | |||
|   exit 1 | |||
| fi | |||
| ORIGINAL_DEPLOY_MANIFEST=$out | |||
| 
 | |||
| # 2. Clone the original, running deployment to a temporary deployment, with tweaks to its name and | |||
| # selectors. The jq command carries over all labels and selectors and appends the `-temp` suffix. | |||
| TMP_DEPLOYMENT_NAME="${DEPLOYMENT_NAME}-temp" | |||
| echo ${ORIGINAL_DEPLOY_MANIFEST} | jq -r '.metadata.name+="-temp" | | |||
|   .spec.template.metadata.labels += (.spec.template.metadata.labels | to_entries | map(.value+="-temp") | from_entries) | | |||
|   .spec.selector.matchLabels += (.spec.selector.matchLabels | to_entries | map(.value+="-temp") | from_entries)' | | |||
|   kubectl apply -f - | |||
| 
 | |||
| # 3. Wait for cloned deployment to become ready. | |||
| sleep 2 | |||
| echo "Waiting for successful rollout of new (temporary) deployment" | |||
| kubectl rollout status --watch=true deployments.apps/${TMP_DEPLOYMENT_NAME} || exit 1 | |||
| echo "Rollout of temporary deployment successful" | |||
| 
 | |||
| # 4. Patch the service object such that all traffic is redirected to the cloned, temporary | |||
| # deployment. After this step, the original deployment will no longer be receiving traffic. | |||
| kubectl get service ${SERVICE_NAME} --export -o json | \ | |||
|   jq '.spec.selector = (.spec.selector | with_entries(.value+="-temp"))' | | |||
|   kubectl apply -f - || exit 1 | |||
| sleep 5 # Sleep slightly to allow iptables to get propagated to all nodes in the cluster | |||
| 
 | |||
| # 5. Update the original deployment (now receiving no traffic) with the new manifest | |||
| echo "Updating original deployment" | |||
| echo ${DEPLOY_MANIFEST} | \ | |||
|   jq ".metadata.labels += {\"app.kubernetes.io/instance\": \"${APPNAME}\"}" | \ | |||
|   kubectl apply -f - || exit 1 | |||
| 
 | |||
| # 6. Wait for the new deployment to become complete | |||
| sleep 2 | |||
| echo "Waiting for successful rollout of new deployment" | |||
| kubectl rollout status --watch=true deployments.apps/${DEPLOYMENT_NAME} || exit 1 | |||
| echo "Rollout of new deployment successful" | |||
| 
 | |||
| # dummy wait step for demo purposes | |||
| echo "sleeping for 30 seconds" | |||
| sleep 30 | |||
| 
 | |||
| # 7. Apply the new service object. Traffic will be redirected to the new version of the deployment | |||
| echo "Updating original service object" | |||
| echo ${SERVICE_MANIFEST} | \ | |||
|   jq ".metadata.labels += {\"app.kubernetes.io/instance\": \"${APPNAME}\"}" | \ | |||
|   kubectl apply -f - || exit 1 | |||
| 
 | |||
| sleep 10 | |||
| # 8. Remove the cloned deployment, which is no longer receiving any traffic | |||
| echo "Deleting ephemeral deployment" | |||
| kubectl delete deployments/${TMP_DEPLOYMENT_NAME} --ignore-not-found=true || exit 1 | |||
| @ -1,65 +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, | |||
|          "revisionHistoryLimit": 3, | |||
|          "selector": { | |||
|             "matchLabels": { | |||
|                "app": params.name | |||
|             }, | |||
|          }, | |||
|          "template": { | |||
|             "metadata": { | |||
|                "labels": { | |||
|                   "app": params.name | |||
|                } | |||
|             }, | |||
|             "spec": { | |||
|                "containers": [ | |||
|                   { | |||
|                      "image": params.image, | |||
|                      "name": params.name, | |||
|                      "ports": [ | |||
|                         { | |||
|                             "containerPort": params.containerPort | |||
|                         } | |||
|                      ] | |||
|                   } | |||
|                ] | |||
|             } | |||
|          } | |||
|       } | |||
|    } | |||
| ] | |||
| @ -1,131 +0,0 @@ | |||
| local bgGuestbook = std.extVar("__ksonnet/components")["bg-guestbook"]; | |||
| local bgGuestbookSvc = bgGuestbook[0]; | |||
| local bgGuestbookDeploy = bgGuestbook[1]; | |||
| 
 | |||
| [ | |||
| { | |||
|   "apiVersion": "v1", | |||
|   "kind": "Pod", | |||
|   "metadata": { | |||
|     "generateName": "blue-green-", | |||
|     "annotations": { | |||
|       "argocd.argoproj.io/hook": "Sync", | |||
|       "deploy-manifest": std.manifestJson(bgGuestbookDeploy), | |||
|       "svc-manifest": std.manifestJson(bgGuestbookSvc), | |||
|     }, | |||
|   }, | |||
|   "spec": { | |||
|     "serviceAccountName": "blue-green-sa", | |||
|     "restartPolicy": "Never", | |||
|     "containers": [ | |||
|       { | |||
|         "name": "blue-green", | |||
|         "image": "argoproj/argoexec:latest", | |||
|         "command": ["bash", "-c"], | |||
|         "args": [" | |||
|             curl -L -o /usr/local/bin/kubectl -LO https://storage.googleapis.com/kubernetes-release/release/$(curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt)/bin/linux/amd64/kubectl && | |||
|             chmod +x /usr/local/bin/kubectl && | |||
|             curl -sSL -o /usr/local/bin/blue-green.sh https://raw.githubusercontent.com/argoproj/argocd-example-apps/master/blue-green-deploy/blue-green.sh && | |||
|             chmod +x /usr/local/bin/blue-green.sh && | |||
|             blue-green.sh | |||
|         "], | |||
|         "env": [ | |||
|           { | |||
|             "name": "DEPLOY_MANIFEST", | |||
|             "valueFrom": { | |||
|               "fieldRef": { | |||
|                 "fieldPath": "metadata.annotations['deploy-manifest']" | |||
|               } | |||
|             } | |||
|           }, | |||
|           { | |||
|             "name": "SERVICE_MANIFEST", | |||
|             "valueFrom": { | |||
|               "fieldRef": { | |||
|                 "fieldPath": "metadata.annotations['svc-manifest']" | |||
|               } | |||
|             } | |||
|           }, | |||
|           // NOTE: app.kubernetes.io/instance will get injected into the hook object | |||
|           { | |||
|             "name": "APPNAME", | |||
|             "valueFrom": { | |||
|               "fieldRef": { | |||
|                 "fieldPath": "metadata.labels['app.kubernetes.io/instance']" | |||
|               } | |||
|             } | |||
|           } | |||
|         ] | |||
|       } | |||
|     ], | |||
|   } | |||
| }, | |||
| // RBAC to allow the blue-green pod privileges to manipulate deployments and services | |||
| { | |||
| 	"apiVersion": "v1", | |||
| 	"kind": "ServiceAccount", | |||
| 	"metadata": { | |||
| 		"name": "blue-green-sa" | |||
| 	} | |||
| }, | |||
| { | |||
| 	"apiVersion": "rbac.authorization.k8s.io/v1", | |||
| 	"kind": "Role", | |||
| 	"metadata": { | |||
| 		"name": "blue-green-role" | |||
| 	}, | |||
| 	"rules": [ | |||
| 		{ | |||
| 			"apiGroups": [ | |||
| 				"apps", | |||
|         "extensions" | |||
| 			], | |||
| 			"resources": [ | |||
| 				"deployments", | |||
| 			], | |||
| 			"verbs": [ | |||
|         "list", | |||
|         "get", | |||
| 				"create", | |||
| 				"update", | |||
| 				"patch", | |||
| 				"delete", | |||
| 			] | |||
| 		}, | |||
| 		{ | |||
| 			"apiGroups": [ | |||
| 				"" | |||
| 			], | |||
| 			"resources": [ | |||
| 				"services" | |||
| 			], | |||
| 			"verbs": [ | |||
|         "list", | |||
|         "get", | |||
| 				"create", | |||
| 				"update", | |||
| 				"patch", | |||
| 				"delete", | |||
| 			] | |||
| 		} | |||
| 	] | |||
| }, | |||
| { | |||
|   "apiVersion": "rbac.authorization.k8s.io/v1", | |||
|   "kind": "RoleBinding", | |||
|   "metadata": { | |||
|     "name": "blue-green-rolebinding" | |||
|   }, | |||
|   "roleRef": { | |||
|     "apiGroup": "rbac.authorization.k8s.io", | |||
|     "kind": "Role", | |||
|     "name": "blue-green-role" | |||
|   }, | |||
|   "subjects": [ | |||
|     { | |||
|       "kind": "ServiceAccount", | |||
|       "name": "blue-green-sa" | |||
|     } | |||
|   ] | |||
| } | |||
| ] | |||
| @ -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: "blue-green-guestbook", | |||
|       replicas: 3, | |||
|       servicePort: 80, | |||
|       type: "LoadBalancer", | |||
|     }, | |||
|     "bg-pod": {}, | |||
|   }, | |||
| } | |||
| @ -1,4 +0,0 @@ | |||
| local components = std.extVar("__ksonnet/components"); | |||
| components + { | |||
|   // Insert user-specified overrides here. | |||
| } | |||
| @ -1,2 +0,0 @@ | |||
| { | |||
| } | |||
| @ -1,9 +0,0 @@ | |||
| local base = import "base.libsonnet"; | |||
| // uncomment if you reference ksonnet-lib | |||
| // local k = import "k.libsonnet"; | |||
| // local deployment = k.apps.v1beta2.deployment; | |||
| 
 | |||
| base + { | |||
|   // Insert user-specified overrides here. For example if a component is named \"nginx-deployment\", you might have something like:\n") | |||
|   // "nginx-deployment"+: deployment.mixin.metadata.withLabels({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) | |||
|   }, | |||
| } | |||
					Loading…
					
					
				
		Reference in new issue