Skip to content

Instantly share code, notes, and snippets.

@arash16
Last active February 25, 2023 17:46
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save arash16/4f1a9b904e6c8684b0cfb75f8a02f3d6 to your computer and use it in GitHub Desktop.
Save arash16/4f1a9b904e6c8684b0cfb75f8a02f3d6 to your computer and use it in GitHub Desktop.
Sample minimal blue/green deployment strategy codes used on cafebazaar.ir
# this is a minimal sample code used for ci pipelines to implement blue/green deployment
#!/usr/bin/env bash
SERVICE=barista
set -e
CURRENT_PRODUCTION_VERSION=$(kubectl get service ${SERVICE}-production -o jsonpath='{.spec.selector.version}')
[[ ${CURRENT_PRODUCTION_VERSION} = green ]] && NEXT_VERSION="blue" || NEXT_VERSION="green"
echo "Current production version is ${CURRENT_PRODUCTION_VERSION}"
echo "Current staging version is $(kubectl get service ${SERVICE}-staging -o jsonpath='{.spec.selector.version}'
echo "Staging will become ${NEXT_VERSION}"
IMAGE_PATH=${CI_REGISTRY}/${GIT_GROUP}/${SERVICE}:${CI_COMMIT_SHA}
echo "Image Path is: ${IMAGE_PATH}"
# set docker image of staging deployment
DEPLOYMENT_NAME=${SERVICE}-${NEXT_VERSION}
kubectl set image deployment/${DEPLOYMENT_NAME} ${SERVICE}=${IMAGE_PATH}
# ensure there's at least one pod running for staging deployment (will be zero after deploy-production)
kubectl scale deployment/${DEPLOYMENT_NAME} --replicas=1
set +e
while : ; do
sleep 3
READY=$(kubectl get deployments ${DEPLOYMENT_NAME} -o jsonpath='{.status.conditions[?(@.reason=="MinimumReplicasAvailable")].status}')
[[ "$READY" != "True" ]] || break
done
# ensure staging service routes to this staging deployment
kubectl patch svc ${SERVICE}-staging -p "{\"spec\":{\"selector\": {\"app\": \"${SERVICE}\", \"version\": \"${NEXT_VERSION}\"}}}"
echo "Staging became ${NEXT_VERSION}"
echo "Test staging then trigger next step manually through gitlab"
#!/usr/bin/env bash
SERVICE=barista
REPLICA_COUNT=3
OLD_PRODUCTION_VERSION=$(kubectl get service ${SERVICE}-production -o jsonpath='{.spec.selector.version}')
CURRENT_STAGING_VERSION=$(kubectl get service ${SERVICE}-staging -o jsonpath='{.spec.selector.version}')
echo "Staging is ${CURRENT_STAGING_VERSION}"
# decrease old production replicas to 1
kubectl scale deployment/${SERVICE}-${OLD_PRODUCTION_VERSION} --replicas=1
# route production service to our new deployment (previously staging)
kubectl patch svc "${SERVICE}-production" -p "{\"spec\":{\"selector\": {\"app\": \"${SERVICE}\", \"version\": \"${CURRENT_STAGING_VERSION}\"}}}"
# increase new production replicas
kubectl scale deployment/${SERVICE}-${CURRENT_STAGING_VERSION} --replicas=${REPLICA_COUNT}
sleep 5 # wait a little for new pods to be running
# no staging pods needed anymore (till next deploy-staging)
kubectl scale deployment/${SERVICE}-${OLD_PRODUCTION_VERSION} --replicas=0
echo "Production became ${CURRENT_STAGING_VERSION}"
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: barista-blue
spec:
replicas: 5
selector:
matchLabels:
app: barista
template:
metadata:
labels:
app: barista
version: blue
spec:
containers:
- name: barista
image: # our internal docker registry url
ports:
- containerPort: 80
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: barista-green
spec:
replicas: 5
selector:
matchLabels:
app: barista
template:
metadata:
labels:
app: barista
version: green
spec:
containers:
- name: barista
image: # our internal docker registry url
ports:
- containerPort: 80
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: barista-production
spec:
tls:
- hosts:
- cafebazaar.ir
rules:
- host: cafebazaar.ir
http:
paths:
- backend:
serviceName: barista-production
servicePort: 80
path: /
apiVersion: v1
kind: Service
metadata:
name: barista-production
labels:
name: barista-production
spec:
ports:
- port: 80
targetPort: 80
selector:
app: barista
version: green
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: barista-staging
spec:
tls:
- hosts:
- staging.xyz
rules:
- host: staging.xyz
http:
paths:
- backend:
serviceName: barista-staging
servicePort: 80
path: /
apiVersion: v1
kind: Service
metadata:
name: barista-staging
labels:
name: barista-staging
spec:
ports:
- port: 80
targetPort: 80
selector:
app: barista
version: blue
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment