mirror of
https://github.com/tektoncd/catalog.git
synced 2024-11-21 05:55:35 +00:00
Add namespace support in blue-green-deployment
As of now blue-green-deployment task assumes the namespace to be the current namespace in which pipeline is running but everytime this might not be the case. Added an extra parameter, `NAMESPACE` which user needs to supply as the parameter in which the existing deployment and service are present. Also added an optional parameter `IMAGE` in order to improve the flexibility for the user Signed-off-by: vinamra28 <jvinamra776@gmail.com>
This commit is contained in:
parent
5f899c0d54
commit
bb5c8e97cf
89
task/blue-green-deploy/0.2/README.md
Normal file
89
task/blue-green-deploy/0.2/README.md
Normal file
@ -0,0 +1,89 @@
|
||||
# Blue Green Deploy on Kubernetes
|
||||
|
||||
The following task can help you to deploy an application using the Blue-Green deployment strategy. This task gives you the flexibility to deploy a version of the application from the blue zone to the green zone without disturbing the previous version in the blue zone. It works by making the service point to the newer version of the application deployed.
|
||||
|
||||
- If you are deploying the first version of the application then it will go into the blue zone and for that you need to provide deployment and service manifests via the `workspaces` and in the `params` the service name and version. Sample Kubernetes manifests for version v1 can be found [here](./samples/v1-deploy).
|
||||
- For further new deployments, it will get deployed in the other zone and then the current service will now point to the new deployment. For example if we have a deployment running in the blue zone then we will deploy the next deployment in the green zone and make the service point to the green zone or vice versa.
|
||||
|
||||
## Installing the Task
|
||||
|
||||
```
|
||||
kubectl apply -f https://api.hub.tekton.dev/v1/resource/tekton/task/blue-green-deploy/0.2/raw
|
||||
```
|
||||
|
||||
## Installing the ClusterRoleBinding
|
||||
|
||||
```
|
||||
kubectl apply -f https://raw.githubusercontent.com/tektoncd/catalog/main/task/blue-green-deploy/0.2/support/clusterrolebinding.yaml
|
||||
```
|
||||
|
||||
## Optional Workspaces
|
||||
|
||||
- **manifest-dir**: Manifest files can be provided via the workspaces
|
||||
- **kubeconfig-dir**: If you want to deploy you application to another cluster then you can mount your `kubeconfig` file via this `workspace`
|
||||
|
||||
## Parameters
|
||||
|
||||
- **SERVICE_NAME**: The service name pointing to the existing deployment. (_Note_: The service name for the new deployment should be same)
|
||||
- **NEW_VERSION**: The version of the deployment to be deployed in the green/blue zone
|
||||
- **MANIFEST**: The deployment manifest URL file path provided in case the manifest is present on Github. (_Example_: "https://raw.githubusercontent.com/tektoncd/catalog/main/task/blue-green-deploy/0.2/samples/v1-deploy/blue-deployment.yaml")
|
||||
- **NAMESPACE**: Target namespace in which operation needs to be performed
|
||||
- **IMAGE**: Image which has kubectl binary present (_Default_: `quay.io/openshift/origin-cli:4.9`)
|
||||
|
||||
## Platforms
|
||||
|
||||
The Task can be run on `linux/amd64` platform.
|
||||
|
||||
# Usage
|
||||
|
||||
This TaskRun runs the Task to deploy the given Kubernetes resource in the green/blue zone and toggle the service to point to the new zone.
|
||||
|
||||
## Without using ConfigMap
|
||||
|
||||
TaskRun :-
|
||||
|
||||
```yaml
|
||||
apiVersion: tekton.dev/v1beta1
|
||||
kind: TaskRun
|
||||
metadata:
|
||||
name: blue-green-deploy-run
|
||||
spec:
|
||||
taskRef:
|
||||
name: blue-green-deploy-k8s
|
||||
params:
|
||||
- name: SERVICE_NAME
|
||||
value: myapp
|
||||
- name: NEW_VERSION
|
||||
value: v2
|
||||
- name: MANIFEST
|
||||
value: "https://raw.githubusercontent.com/tektoncd/catalog/main/task/blue-green-deploy/0.2/samples/v2-deploy/green-deployment.yaml"
|
||||
```
|
||||
|
||||
## Using ConfigMap
|
||||
|
||||
1. Create the `ConfigMap`
|
||||
|
||||
```bash
|
||||
kubectl create configmap manifests --from-file="green-deployment.yaml"
|
||||
```
|
||||
|
||||
2. TaskRun:-
|
||||
|
||||
```yaml
|
||||
apiVersion: tekton.dev/v1beta1
|
||||
kind: TaskRun
|
||||
metadata:
|
||||
name: blue-green-deploy-run
|
||||
spec:
|
||||
taskRef:
|
||||
name: blue-green-deploy-k8s
|
||||
params:
|
||||
- name: SERVICE_NAME
|
||||
value: myapp
|
||||
- name: NEW_VERSION
|
||||
value: v2
|
||||
workspaces:
|
||||
- name: manifest-dir
|
||||
configMap:
|
||||
name: manifests
|
||||
```
|
153
task/blue-green-deploy/0.2/blue-green-deploy.yaml
Normal file
153
task/blue-green-deploy/0.2/blue-green-deploy.yaml
Normal file
@ -0,0 +1,153 @@
|
||||
apiVersion: tekton.dev/v1beta1
|
||||
kind: Task
|
||||
metadata:
|
||||
name: blue-green-deploy
|
||||
labels:
|
||||
app.kubernetes.io/version: "0.2"
|
||||
annotations:
|
||||
tekton.dev/pipelines.minVersion: "0.17.0"
|
||||
tekton.dev/categories: Deployment
|
||||
tekton.dev/tags: deployment
|
||||
tekton.dev/displayName: "blue green deployment"
|
||||
tekton.dev/platforms: "linux/amd64"
|
||||
spec:
|
||||
description: >-
|
||||
This task can be used to do Blue-Green deployment
|
||||
workspaces:
|
||||
- name: manifest-dir
|
||||
description: Consisting of kubernetes manifests
|
||||
optional: true
|
||||
- name: kubeconfig-dir
|
||||
description: Can be used in case kubeconfig file is mounted
|
||||
optional: true
|
||||
params:
|
||||
- name: SERVICE_NAME
|
||||
type: string
|
||||
description: Name of the service which is pointing to existing deployment
|
||||
- name: NEW_VERSION
|
||||
type: string
|
||||
description: The version of newer deployment which is to be patched to existing service
|
||||
- name: MANIFEST
|
||||
type: string
|
||||
default: "."
|
||||
description: The newer version of the deployment to be deployed in another zone
|
||||
- name: NAMESPACE
|
||||
type: string
|
||||
description: Target namespace in which operation needs to be performed
|
||||
- name: IMAGE
|
||||
description: Image which has kubectl binary present
|
||||
type: string
|
||||
default: "quay.io/openshift/origin-cli:4.9"
|
||||
steps:
|
||||
- name: change-deployment
|
||||
image: $(params.IMAGE)
|
||||
script: |
|
||||
#!/usr/bin/env bash
|
||||
set -u -o pipefail
|
||||
|
||||
[[ "$(workspaces.manifest-dir.bound)" == "true" ]] && cd $(workspaces.manifest-dir.path)
|
||||
|
||||
if [[ "$(workspaces.kubeconfig-dir.bound)" == "true" ]] && [[ -f $(workspaces.kubeconfig-dir.path)/kubeconfig ]]; then
|
||||
export KUBECONFIG=$(workspaces.kubeconfig-dir.path)/kubeconfig
|
||||
fi
|
||||
|
||||
getReasons() {
|
||||
local deploy_name=$1
|
||||
kubectl -n $(params.NAMESPACE) get deploy "$deploy_name" \
|
||||
-o jsonpath='{range .status.conditions[*]}{.reason}{"\n"}{end}'
|
||||
}
|
||||
|
||||
# Getting the status at particular index
|
||||
getStatusAtIndex() {
|
||||
local deploy_name=$1
|
||||
local index=$2
|
||||
kubectl -n $(params.NAMESPACE) get deploy "$deploy_name" \
|
||||
-o jsonpath='{range .status.conditions['$index']}{.status}{"\n"}{end}'
|
||||
}
|
||||
|
||||
# Checking for unavailable pods in case the deployment is
|
||||
# patched with a newer image
|
||||
checkUnavailableReplicas() {
|
||||
local deploy_name=$1
|
||||
local replicasUnavailable=$(kubectl -n $(params.NAMESPACE) get deploy "$deploy_name" -o jsonpath='{.status.unavailableReplicas}')
|
||||
[[ "$replicasUnavailable" == "" ]] && return 0 || return 1
|
||||
}
|
||||
|
||||
getMinimumReplicaStatus() {
|
||||
local deploy_name=$1
|
||||
local INDEX=0
|
||||
for reason in $(getReasons $deploy_name); do
|
||||
if [[ "$reason" == "MinimumReplicasAvailable" ]]; then
|
||||
local ready=$(getStatusAtIndex $deploy_name ${INDEX})
|
||||
[[ "$ready" != "True" ]] && return 1 || return 0
|
||||
fi
|
||||
((INDEX++))
|
||||
done
|
||||
return 1
|
||||
}
|
||||
|
||||
checkProgressDeadline() {
|
||||
local deploy_name=$1
|
||||
local INDEX=0
|
||||
for reason in $(getReasons $deploy_name); do
|
||||
if [[ "$reason" == "ProgressDeadlineExceeded" ]]; then
|
||||
local status=$(getStatusAtIndex $deploy_name ${INDEX})
|
||||
[[ "$status" == "True" ]] && return 0 || return 1
|
||||
fi
|
||||
((INDEX++))
|
||||
done
|
||||
return 1
|
||||
}
|
||||
|
||||
switchService() {
|
||||
kubectl -n $(params.NAMESPACE) patch svc ${service} \
|
||||
-p "{\"spec\":{\"selector\": {\"app\": \"${service}\", \"version\": \"${version}\"}}}"
|
||||
}
|
||||
|
||||
main() {
|
||||
local deploy_name=$(params.SERVICE_NAME)-$(params.NEW_VERSION)
|
||||
local service=$(params.SERVICE_NAME)
|
||||
local version=$(params.NEW_VERSION)
|
||||
|
||||
kubectl -n $(params.NAMESPACE) apply -f $(params.MANIFEST)
|
||||
|
||||
# Wait until the Deployment is ready by checking the
|
||||
# MinimumReplicasAvailable condition.
|
||||
# Also checking for the ProgressDeadlineExceeded
|
||||
# condition
|
||||
while true; do
|
||||
getMinimumReplicaStatus ${deploy_name}
|
||||
[[ $? -eq 0 ]] && break
|
||||
checkProgressDeadline ${deploy_name}
|
||||
[[ $? -eq 0 ]] && break
|
||||
sleep 5
|
||||
done
|
||||
# If ProgressDeadlineExceeded then break from the main
|
||||
# and avoid checking for the next condition
|
||||
checkProgressDeadline ${deploy_name}
|
||||
if [[ $? -eq 0 ]]; then
|
||||
echo "Failed to change the service" && break
|
||||
fi
|
||||
# If MinimumReplicas are available then check
|
||||
# for the unavailable Pods
|
||||
# Also checking for the ProgressDeadlineExceeded condition
|
||||
while true; do
|
||||
checkUnavailableReplicas ${deploy_name}
|
||||
[[ $? -eq 0 ]] && break
|
||||
checkProgressDeadline ${deploy_name}
|
||||
[[ $? -eq 0 ]] && break
|
||||
sleep 5
|
||||
done
|
||||
|
||||
# Update the service selector with the new version
|
||||
# if ProgressDeadline not exceeded
|
||||
checkProgressDeadline ${deploy_name}
|
||||
if [[ $? -eq 0 ]]; then
|
||||
echo "Failed to change the service"
|
||||
else
|
||||
switchService ${service} ${version}
|
||||
[[ $? -eq 0 ]] && echo "Done." || exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
main "$@"
|
16
task/blue-green-deploy/0.2/samples/run.yaml
Normal file
16
task/blue-green-deploy/0.2/samples/run.yaml
Normal file
@ -0,0 +1,16 @@
|
||||
apiVersion: tekton.dev/v1beta1
|
||||
kind: TaskRun
|
||||
metadata:
|
||||
name: blue-green-deploy-run
|
||||
spec:
|
||||
taskRef:
|
||||
name: blue-green-deploy
|
||||
params:
|
||||
- name: SERVICE_NAME
|
||||
value: myapp
|
||||
- name: NEW_VERSION
|
||||
value: v2
|
||||
- name: MANIFEST
|
||||
value: "https://raw.githubusercontent.com/vinamra28/blue-green-deployment-k8s/master/deployment%2Bservice/green-deployment.yaml"
|
||||
- name: NAMESPACE
|
||||
value: default
|
@ -0,0 +1,23 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: myapp-v1
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: myapp
|
||||
version: v1
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: "myapp"
|
||||
version: "v1"
|
||||
spec:
|
||||
containers:
|
||||
- name: myapp
|
||||
image: quay.io/vinamra2807/social-client:v1
|
||||
imagePullPolicy: IfNotPresent
|
||||
ports:
|
||||
- containerPort: 3000
|
||||
name: http
|
14
task/blue-green-deploy/0.2/samples/v1-deploy/service.yaml
Normal file
14
task/blue-green-deploy/0.2/samples/v1-deploy/service.yaml
Normal file
@ -0,0 +1,14 @@
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: myapp
|
||||
labels:
|
||||
app: myapp
|
||||
spec:
|
||||
type: NodePort
|
||||
ports:
|
||||
- port: 3000
|
||||
name: http
|
||||
selector:
|
||||
app: myapp
|
||||
version: v1
|
@ -0,0 +1,23 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: myapp-v2
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: myapp
|
||||
version: v2
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: "myapp"
|
||||
version: "v2"
|
||||
spec:
|
||||
containers:
|
||||
- name: myapp
|
||||
image: quay.io/vinamra2807/social-client:v2
|
||||
imagePullPolicy: IfNotPresent
|
||||
ports:
|
||||
- containerPort: 3000
|
||||
name: http
|
12
task/blue-green-deploy/0.2/support/clusterrolebinding.yaml
Normal file
12
task/blue-green-deploy/0.2/support/clusterrolebinding.yaml
Normal file
@ -0,0 +1,12 @@
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRoleBinding
|
||||
metadata:
|
||||
name: default-blue-green
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
name: default
|
||||
namespace: default
|
||||
roleRef:
|
||||
kind: ClusterRole
|
||||
name: cluster-admin
|
||||
apiGroup: rbac.authorization.k8s.io
|
46
task/blue-green-deploy/0.2/tests/pre-apply-task-hook.sh
Normal file
46
task/blue-green-deploy/0.2/tests/pre-apply-task-hook.sh
Normal file
@ -0,0 +1,46 @@
|
||||
#!/bin/bash
|
||||
#This will create a sample deployment version v1 of the application and a service which will point to that deployment
|
||||
|
||||
cat <<EOF | kubectl apply -f- -n "${tns}"
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: myapp-v1
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: myapp
|
||||
version: v1
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: "myapp"
|
||||
version: "v1"
|
||||
spec:
|
||||
containers:
|
||||
- name: myapp
|
||||
image: quay.io/vinamra2807/social-client:v1
|
||||
imagePullPolicy: IfNotPresent
|
||||
ports:
|
||||
- containerPort: 3000
|
||||
name: http
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: myapp
|
||||
labels:
|
||||
app: myapp
|
||||
spec:
|
||||
type: NodePort
|
||||
ports:
|
||||
- port: 3000
|
||||
name: http
|
||||
selector:
|
||||
app: myapp
|
||||
version: v1
|
||||
EOF
|
||||
|
||||
kubectl -n "${tns}" wait --for=condition=available --timeout=600s deployment/myapp-v1
|
37
task/blue-green-deploy/0.2/tests/resources.yaml
Normal file
37
task/blue-green-deploy/0.2/tests/resources.yaml
Normal file
@ -0,0 +1,37 @@
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
name: blue-green-account
|
||||
namespace: blue-green-deploy-0-2
|
||||
---
|
||||
kind: ClusterRole
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
metadata:
|
||||
name: blue-green-cluster-role
|
||||
rules:
|
||||
# Core API
|
||||
- apiGroups: [""]
|
||||
resources: ["services", "pods", "deployments", "configmaps", "secrets"]
|
||||
verbs: ["get", "list", "create", "update", "delete", "patch", "watch"]
|
||||
# Apps API
|
||||
- apiGroups: ["apps"]
|
||||
resources: ["deployments", "daemonsets", "jobs"]
|
||||
verbs: ["get", "list", "create", "update", "delete", "patch", "watch"]
|
||||
# Tekton API
|
||||
- apiGroups: ["tekton.dev"]
|
||||
resources: ["*"]
|
||||
verbs: ["*"]
|
||||
---
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRoleBinding
|
||||
metadata:
|
||||
name: blue-green-binding
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
name: blue-green-account
|
||||
namespace: blue-green-deploy-0-2
|
||||
roleRef:
|
||||
kind: ClusterRole
|
||||
name: blue-green-cluster-role
|
||||
apiGroup: rbac.authorization.k8s.io
|
17
task/blue-green-deploy/0.2/tests/run.yaml
Normal file
17
task/blue-green-deploy/0.2/tests/run.yaml
Normal file
@ -0,0 +1,17 @@
|
||||
apiVersion: tekton.dev/v1beta1
|
||||
kind: TaskRun
|
||||
metadata:
|
||||
name: blue-green-deploy-run
|
||||
spec:
|
||||
serviceAccountName: blue-green-account
|
||||
taskRef:
|
||||
name: blue-green-deploy
|
||||
params:
|
||||
- name: SERVICE_NAME
|
||||
value: myapp
|
||||
- name: NEW_VERSION
|
||||
value: v2
|
||||
- name: MANIFEST
|
||||
value: "https://raw.githubusercontent.com/vinamra28/blue-green-deployment-k8s/master/deployment%2Bservice/green-deployment.yaml"
|
||||
- name: NAMESPACE
|
||||
value: blue-green-deploy-0-2
|
Loading…
Reference in New Issue
Block a user