Kubernetes is now the de-facto standard for container orchestration. With more and more organizations adopting Kubernetes, it is essential that we get our fundamental ops-infra in place before any migration. This post will focus on pushing out new releases of the application to our Kubernetes cluster i.e. Continuous
Continuous Delivery Pipeline for Kubernetes
Although this post is about the CD system using Spinnaker. I want to briefly go over the CI pipeline so that the bigger picture is clear.
Properties File
TAG=1.7-SNAPSHOT
ACTION=DEPLOY
This is the crucial part. Spinnaker offers a ton of options for Kubernetes deployments. You can either consume manifests from GCS or S3 bucket or you can provide manifest as text within the pipeline.
Consuming manifests from GCS or S3 buckets includes more moving parts, and since this is an introductory blog, it is beyond this article’s scope right now. However, with that being said, I extensively use that approach as it is best in scenarios where you need to deploy a large number of micro-services running in Kubernetes as such pipelines are highly templatized and re-usable.
Today, we will deploy a sample Nginx Service which reads the app version from a
pom.xml
file and renders it on the browser. Application code and Dockerfile can be found here. The part where index.html
is updated can be seen below (This is what the Jenkins job does basically).
#!/bin/bash
#Author: Vaibhav Thakur
#Checking whether commit was in master of not.
if_master=`echo $payload | jq '.ref' | grep master`
if [ $? -eq 1 ]; then
echo "Pipeline should not be triggered"
exit 2
fi
#Getting tag from pom.xml
TAG=`grep SNAPSHOT pom.xml | sed 's|[<,>,/,version ]||g'`
echo $TAG
#Getting action from commit message
ACTION=$(echo $payload | jq -r '.commits[0].message' | cut -d',' -f2)
#Updating index.html
sed -i -- "s/VER/${TAG}/g" app/index.html
#Pushing to dockerhub
docker build -t vaibhavthakur/nginx-demo:$TAG .
docker push vaibhavthakur/nginx-demo:$TAG
echo TAG=${TAG} > trigger.properties
echo ACTION=${ACTION} >> trigger.properties
The manifest for the Nginx deployment and service is below:
apiVersion: v1
kind: Namespace
metadata:
name: nginx
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
namespace: nginx
name: nginx-deployment
spec:
replicas: 1
template:
metadata:
annotations:
prometheus.io/path: "/status/format/prometheus"
prometheus.io/scrape: "true"
prometheus.io/port: "80"
labels:
app: nginx-server
spec:
affinity:
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
labelSelector:
matchExpressions:
- key: app
operator: In
values:
- nginx-server
topologyKey: kubernetes.io/hostname
containers:
- name: nginx-demo
image: vaibhavthakur/nginx-demo:1.0-SNAPSHOT
imagePullPolicy: Always
resources:
limits:
cpu: 2500m
requests:
cpu: 2000m
ports:
- containerPort: 80
name: http
---
apiVersion: v1
kind: Service
metadata:
namespace: nginx
name: nginx-service
annotations:
cloud.google.com/load-balancer-type: Internal
spec:
ports:
- port: 80
targetPort: 80
name: http
selector:
app: nginx-server
type: LoadBalancer
#k8s #kubernetes #cicd #continuous-integration #continuous-delivery #kubernetes-cluster #pipeline #jenkins