|
@@ -0,0 +1,71 @@
|
|
|
|
+#!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
|