CircleCI pipeline for GKE

CircleCI pipeline for GKE

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

  1. Logged to your bastion Host

  2. Run this command ssh-keygen

  3. First copy the id_rsa.pub and paste this in the metadata of the GCP cloud

  4. 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.

LinkedIn