In my previous post, I shared the story of my journey into the world of Kubernetes, highlighting the challenges and triumphs along the way. However, I realized that there was one crucial step I inadvertently omitted from my narrative—the transition of my personal application’s Continuous Integration process to seamlessly deploy using Kubernetes.
Executing the migration turned out to be a straightforward process, primarily because I had a well-established CI pipeline already in place for my application. This presented an ideal opportunity to address a flaw in my previous deployment process—one that had been consistently pulling the latest Docker image rather than fetching the one associated with the specific commit that triggered the build.
Leveraging Circle CI for my Continuous Delivery (CD) pipeline made implementing the change remarkably straightforward. I introduced a simple yet effective modification by including the commit hash as a parameter for the scripts executed via SSH during the deployment process. Here’s the deployment steps in .circleci/config.yml
are as of now:
- run:
name: Publish Docker Image to Docker Hub
command: |
echo "$DOCKER_PASS" | docker login --username $DOCKER_USER --password-stdin
docker build -t <image>:latest -t <image>:$CIRCLE_SHA1 .
docker push <image>
- run:
name: Deploy
command: |
ssh -o StrictHostKeyChecking=no deployer@<my host> "cd /<script diretory> && ./deploy-app.sh <app-k8s-file> $CIRCLE_SHA1"
The real magic unfolds within the deploy-app.sh
script. This script performs a series of steps, starting with extracting information from the running deployment. It then patches the necessary file with the new image tag, applies these changes, and monitors the rollout status.
#!/usr/bin/env bash
function image_name() {
kubectl get -f $1 -o jsonpath='{.items[?(@.kind=="Deployment")].spec.template.spec.containers[0].image}' \
| sed 's/\//\\\//g'
}
function deployment_name() {
kubectl get -f $1 -o jsonpath='{.items[?(@.kind=="Deployment")].metadata.name}'
}
deployment_file="$1"
new_image_tag="$2"
image=`image_name $deployment_file`
deployment_name=`deployment_name $deployment_file`
image_name="${image%%:*}"
image_tag="${image#*:}"
cat $deployment_file \
| sed "s/image: $image_name:$image_tag/image: $image_name:$new_image_tag/g" \
| kubectl apply -f -
kubectl rollout status -w deployment/$deployment_name
So, there you have it—my approach to integrating Kubernetes into my Continuous Delivery pipeline. It may seem deceptively simple, but that’s the beauty of it.