In my latest blog, I guide you through setting up CircleCI from scratch for Google Kubernetes Engine (GKE). I cover everything from pipeline configuration to deploying your application with the latest image tags. Learn how to streamline your CI/CD process by automating image builds and updates directly in your GCP artifact repository.
Setup a new project
Click on the very first option (Build, test and deploy your software application)
Mention your project details here
Mention the pipeline steps here
Select your repository and branch, remember you need to configure your repo first from github. Go to the setting of the github and click to the Github Apps.
Click here and select your repository after this step
After selecting, click to the Next button
Now remember, circle will create a separate branch for you by the name of this, and it will create a dummy file under this branch which is .circleci/config.yml you have to delete that file and folder.
Project is created, now you have to configure the pipeline and trigger for the project
Now you have to click to the project setting which is present on the right side
Create the Pipeline
After the pipeline, create trigger for the pipeline
Mention the name, select the right repository and the pipeline
We need Environment Variables for Pipeline
I am mentioning the ENV for the GCP cloud:
GCLOUD_SERVICE_KEY
This is responsible for accessing the GCR
SSH_HOST
This is our bastion host where our config-map is configured
SSH_USER
This is our bastion host where our config-map is configured.
Configuring the Private Key of the Cloud
Like below, remember if you are setting up freshly circleci for the organisation you to keep few points in your mind such as
Logged to your bastion Host
Run this command ssh-keygen
First copy the id_rsa.pub and paste this in the metadata of the GCP cloud
Copy the private key and upload this into the SSH key like below.
Pipeline Script
Create a .circleci/config.yml in your deployment branch which could be any such as prod, main, dev or any.
version: 2.1
executors:
docker-executor:
docker:
- image: cimg/base:stable
working_directory: ~/repo
resource_class: small
jobs:
checkout:
executor: docker-executor
steps:
- checkout
- setup_remote_docker:
docker_layer_caching: true
- run:
name: Install Node.js and npm
command: |
sudo apt-get update && sudo apt-get install -y curl
curl -fsSL <https://deb.nodesource.com/setup_lts.x> | sudo bash -
sudo apt-get install -y nodejs
- run:
name: Verify Node.js and npm versions
command: |
node --version
npm --version
- run:
name: Install Node.js dependencies
command: npm install --force
build-and-deploy:
executor: docker-executor
steps:
- checkout
- setup_remote_docker:
docker_layer_caching: true
- run:
name: Debug Environment Variables
command: |
echo "GCP_PROJECT_ID=dev-dev"
echo "IMAGE_NAME=mention-your-gcr-image-name-here"
echo "CIRCLE_BUILD_NUM=${CIRCLE_BUILD_NUM}"
- run:
name: Build Docker Image
command: |
# Mention your gcr or ecr image name uri here
IMAGE="asia-south1-docker.pkg.dev/dev-dev/dev-dev/gcr-image-name-here"
TAG="${CIRCLE_BUILD_NUM}"
echo "Building Docker image: ${IMAGE}"
docker build -t ${IMAGE}:latest .
echo "Tagging Docker image: ${IMAGE}:${TAG}"
docker tag ${IMAGE}:latest ${IMAGE}:${TAG}
- run:
name: Install Google Cloud SDK and gke-gcloud-auth-plugin
command: |
# Download the Google Cloud SDK tarball
curl -L -o google-cloud-sdk-linux-x86_64.tar.gz <https://dl.google.com/dl/cloudsdk/channels/rapid/downloads/google-cloud-sdk-457.0.0-linux-x86_64.tar.gz>
# Extract the tarball
tar -xzf google-cloud-sdk-linux-x86_64.tar.gz -C /tmp
# Install Google Cloud SDK
/tmp/google-cloud-sdk/install.sh --quiet
# Add Google Cloud SDK to PATH
echo 'export PATH=$PATH:/tmp/google-cloud-sdk/bin' >> $BASH_ENV
source $BASH_ENV
# Install the gke-gcloud-auth-plugin
gcloud components install gke-gcloud-auth-plugin
# Verify installation
gcloud version
- run:
name: Authenticate with Google Cloud
command: |
# Create a temporary file for the service key
echo "$GCLOUD_SERVICE_KEY" > ${HOME}/gcloud-service-key.json
# Authenticate with Google Cloud
gcloud auth activate-service-account --key-file=${HOME}/gcloud-service-key.json
# Configure Docker for Artifact Registry
gcloud auth configure-docker asia-south1-docker.pkg.dev --quiet
# Verify authentication
if ! gcloud auth list; then
echo "Authentication with Google Cloud failed."
exit 1
fi
# Get GKE cluster credentials
gcloud container clusters get-credentials dev-dev --zone asia-south1 --project dev-dev
cat ~/.kube/config
# Clean up the temporary file
rm ${HOME}/gcloud-service-key.json
- run:
name: Push Docker Image to Artifact Registry
command: |
# Mention your gcr or ecr image name here
IMAGE="asia-south1-docker.pkg.dev/dev-dev/dev-dev/gcr-image-name-here"
TAG="${CIRCLE_BUILD_NUM}"
echo "Pushing Docker image: ${IMAGE}:latest"
docker push ${IMAGE}:latest
echo "Pushing Docker image: ${IMAGE}:${TAG}"
docker push ${IMAGE}:${TAG}
- run:
name: Set Environment Variable for GKE Auth Plugin
command: |
echo "export USE_GKE_GCLOUD_AUTH_PLUGIN=True" >> $BASH_ENV
source $BASH_ENV
- run:
name: Install kubectl
command: |
curl -LO "<https://dl.k8s.io/release/v1.26.4/bin/linux/amd64/kubectl>"
chmod +x ./kubectl
sudo mv ./kubectl /usr/local/bin/kubectl
kubectl version --client
- run:
name: Add SSH Key and Known Hosts
command: |
mkdir -p ~/.ssh
echo "$SSH_PRIVATE_KEY" > ~/.ssh/id_rsa
chmod 600 ~/.ssh/id_rsa
ssh-keyscan $SSH_HOST >> ~/.ssh/known_hosts
- run:
name: Deploy to GKE
command: |
IMAGE="asia-south1-docker.pkg.dev/dev-dev/dev-dev/gcr-image-name-here"
TAG="${CIRCLE_BUILD_NUM}"
DEPLOYMENT_NAME="you-can-find-this-from-deployment.yaml-file"
CONTAINER_NAME="you-can-find-this-from-deployment.yaml-file"
NAMESPACE="enter-namespace-for-deployment"
ssh $SSH_USER@$SSH_HOST "export KUBECONFIG='/home/$SSH_USER/.kube/config'; \\
kubectl set image deployment/${DEPLOYMENT_NAME} ${CONTAINER_NAME}=${IMAGE}:${TAG} -n ${NAMESPACE} && \\
kubectl rollout restart deployment/${DEPLOYMENT_NAME} -n ${NAMESPACE}"
workflows:
version: 2
build_and_deploy:
jobs:
- checkout:
filters:
branches:
only:
- dev #mention the branch name
- build-and-deploy:
requires:
- checkout
filters:
branches:
only:
- dev #mention the branch name
Thank you for reading my blog, and I hope you find it informative and inspiring. If you have any feedback or questions, please feel free to reach out.