Kubernetes Deployment: Automating NodeJS Deployment on GKE with GitHub Actions

Niranjan Gawali
Globant
Published in
10 min readJul 25, 2023
Automating NodeJS Deployment on GKE with GitHub Actions

This is the third blog in a comprehensive five-part series on Kubernetes deployments. The previous and remaining parts are outlined below.

In this third installment, we will take the series to the next level by automating the deployment of the NodeJS application to GKE using the powerful tool of GitHub Actions. It is important to note that this blog is a continuation of the previous articles, so please ensure that you have completed the necessary steps, such as creating the GKE cluster, deploying the GKE deployments, and configuring the GKE services.

In this blog, I will walk you through the steps of setting up a GitHub Actions workflow to deploy your NodeJS application on GKE. By the end of this blog, you will better understand how to automate your deployment process and improve your development workflow.

We will explore how to automate this process using GitHub Actions, making it even more convenient to deploy our app. Automating a NodeJS application's deployment process can save developers time and effort, especially when multiple deployments are needed. GitHub Actions provides an easy and flexible way to automate this process by allowing developers to create workflows that automatically build, test, and deploy their applications. With GitHub Actions, developers can easily integrate code changes with their deployment pipeline and streamline the development process.

Essential Requirements

Before we start setting up the GitHub Actions workflow, there are a few prerequisites that you need to have in place. Firstly, you should have a working knowledge of GitHub, including creating a repository and managing its contents. Additionally, you should have a basic understanding of YAML, as we will be using YAML files to configure our workflow. Finally, you will need a Google Cloud Platform account, enabling you to connect to the necessary resources for the deployment process.

To automate the workflow for this NodeJS application, you will also need to have a Docker account. This will enable you to store and manage the container images used to build and deploy the application.

All these prerequisites will ensure a smooth and efficient setup of the GitHub Actions workflow for your Node.js application deployment.

Configuring the NodeJS Application

In Part III of our Kubernetes Deployment series, we will use the same NodeJS application repository we used in the previous blog (Part II). All the necessary Kubernetes configuration files can be found in the kubernetes folder of this GitHub repository. Additionally, the Dockerfile used to package the application as a container image is available in the root directory of the same repository. We will be referring to these files in this blog to automate the deployment of the NodeJS application to the GKE using GitHub actions

For more detailed information about the Docker and Kubernetes configuration we will use, kindly refer to the preceding blog.

Please refer to the following screenshot of the project structure for reference.

Node Application Project Structure

GitHub Account Setup

To enable secure communication between GitHub and the GKE cluster, you must set up certain repository secrets. You can set up these secrets by navigating to the repository's settings page and selecting the Secrets option from the left-hand menu. For more details about GitHub Secrets, please refer to this link.

Please set up the secrets as shown below.

  • Docker Username: In the repository, secrets add the docker username with the key of DOCKER_USERNAME.
  • Docker Token: By logging into the docker hub account, please generate the token and add its value in the GitHub secret with the key of DOCKER_TOKEN.
  • GKE Cluster Name: You must also add the cluster name you created. In the earlier blog, we created a cluster kubernetes-demo , So add the cluster name with the key of GKE_CLUSTER_NAME.
  • GKE Cluster Zone: You will need to add the Cluster location in the GitHub secrets with the key GKE_CLUSTER_ZONE. The cluster we have created is in asia-south1 location.
  • GKE Service Account: To facilitate the automated deployment, you will also need a service account. You need to create the service account key and add that key to the GitHub secret with the name GKE_SA. Please refer to the section below for the steps to create the service account, generate the service account key, and add it to GitHub.

Managing service accounts for GKE

  • Open the cloud shell by clicking on the top right corner of the GCP console and set the default project using the following command.
glcoud config set project <project-id>
  • Create the service account using the following command. You can skip this step if you already have a service account.
gcloud iam service-accounts create <service-account-name>
  • You need to grant the service account access to your cluster. The following command grants the roles/container developer IAM role to the service account.
glcoud config set project <project-id> gcloud projects add-iam-policy-binding <project-id> \
--member=serviceAccount:<service-account-name>@<project-id>.iam.gserviceaccount.com \
--role=roles/container.developer
  • Create and download the key for the service account.
gcloud iam service-accounts keys create gsa-key.json \
--iam-account=<service-account-name>@<project-id>.iam.gserviceaccount.com
  • Before adding the service account to the GitHub Secret, you must encode the service account key into base64 format. Once you have done that, copy the encoded secret key and add it to the GitHub secrets.
cat gsa-key.json | base64 #add the response to GitHub Secret

For more details about the service account usage, please refer to the link.

Once all the GitHub secrets have been added, they will be displayed below.

GitHub Secrets

Creating a GitHub Actions Workflow

Creating a folder .github at the root of the project and a subfolder workflows within it is necessary to enable GitHub Actions for the project. GitHub Actions is a powerful automation tool provided by GitHub that allows you to automate various tasks, such as building, testing, and deploying your code.

By creating the .github folder and placing a workflows subfolder within it, you are following the standard convention recognized by GitHub. This is where GitHub looks for configuration files related to GitHub Actions.

Inside the workflows folder, create a file named build-and-deploy.yaml.
In this YAML file, we will add the configuration for the specific GitHub Action that will handle your project's build and deployment process.

Let's understand the steps of the GitHub actions configuration file.

name: Docker build and Deploy

on:
push:
branches: [main]
pull_request:
branches: [main]

It defines the workflow with the name Docker build and Deploy that should be triggered in response to events in the GitHub repository.

The on keyword specifies the events that should trigger the workflow. In this case, the workflow will be triggered when there is a push to the main branch of the GitHub repository, or a pull request is opened targeting the main branch.

Therefore, whenever a developer pushes code changes to the main branch or opens a pull request targeting the main branch of the GitHub repository, the workflowDocker build and Deploy will be triggered.

Let's understand the next section of the configuration, jobs.

jobs:
create-image-and-push-to-dockerhub:

name: Create Image and Push to Dockerhub
runs-on: ubuntu-latest

steps:
- name: checkout
uses: actions/checkout@v3

- name: Docker Login
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_TOKEN }}

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2

- name: Build and push
uses: docker/build-push-action@v4
with:
context: .
file: ./Dockerfile
push: true
tags: niranjang2/books_management_service:${{ github.sha }}

Afterward, we define the job create-image-and-push-to-dockerhub as the name dictates in this job, we will create the docker image and push it to the docker hub. The following steps are followed in this workflow.

  • The name key provides a name for the job and runs-on specifies that the job should run on an Ubuntu environment.
  • The steps key lists a series of steps to be performed in the job, each with a name and an action to perform.
  • The first step is to check out the code from the repository using the actions/checkout@v3 action.
  • The second step uses the docker/login-action@v2 action to log in to DockerHub using the Docker credentials stored in GitHub Secrets in the earlier section.
  • The third step uses the docker/setup-buildx-action@v2 action to set up the Docker Buildx builder, which is used to build multi-architecture Docker images.
  • In the fourth step, the docker/build-push-action@v4 action is utilized to build and push the Docker image specified in the Dockerfile to DockerHub. The action tags the image with the Git commit hash, a unique identifier for the triggering commit. This approach ensures that each Docker image is versioned according to the specific code changes that triggered the workflow. Using the Git commit hash as a tag, different image versions can be easily tracked, managed, and rolled back if needed.

Let's check the next job setup-and-deploy .

  setup-and-deploy:
needs: [create-image-and-push-to-dockerhub]

name: Setup and Deploy
runs-on: ubuntu-latest

permissions:
contents: 'read'
id-token: 'write'

steps:
- name: Checkout
uses: actions/checkout@v3

- name: Authenticate to Google Cloud
uses: google-github-actions/auth@v1
with:
credentials_json: ${{ secrets.GKE_SA }}

- name: Get GKE Credentials
uses: google-github-actions/get-gke-credentials@v1
with:
cluster_name: ${{ secrets.GKE_CLUSTER_NAME }}
location: ${{ secrets.GKE_CLUSTER_ZONE }}

- name: Deploy on the GKE
run: |-
sed -i -e 's/DOCKER_IMG_TAG/'${{ github.sha }}'/' ./kubernetes/book-mgmt-api-deploy.yaml
kubectl apply -f ./kubernetes/

This is the second job in the configuration, responsible for automating the deployment of a Kubernetes application to a Google Kubernetes Engine (GKE) cluster. The workflow is triggered upon the completion of the create-image-and-push-to-dockerhub job. The following steps are followed in this workflow.

  • The needs keyword specifies that this job is dependent on the completion of the create-image-and-push-to-dockerhub job. Therefore, the Docker image must have been successfully built and pushed to DockerHub before this particular job can start its execution.
  • The name key provides a name for the job and runs-on specifies that the job should run on an Ubuntu environment.
  • The permissions key sets the permissions for the workflow. In this case, the workflow is given read access to the repository's contents and write access to an ID token.
  • The first step checks out the code from the repository using the actions/checkout@v3 action.
  • The second step authenticates to Google Cloud using the google-github-actions/auth@v1 action, which requires a JSON file with credentials stored in GitHub Secrets.
  • The third step retrieves the GKE credentials for the specified cluster using the google-github-actions/get-gke-credentials@v1 action, which requires the cluster name and location stored in GitHub Secrets.
  • The fourth step deploys the Kubernetes application to the GKE cluster. This step first replaces the DOCKER_IMG_TAG placeholder in the Kubernetes deployment configuration file with the Git commit hash of the Docker image that was pushed to DockerHub. This ensures that the correct version of the Docker image is deployed. Finally, the kubectl apply command is used to deploy the Kubernetes resources specified in the kubernetes/ repository's directory.

The complete configuration file will look as below.

name: Docker build and Deploy

on:
push:
branches: [main]
pull_request:
branches: [main]

jobs:
create-image-and-push-to-dockerhub:

name: Create Image and Push to Dockerhub
runs-on: ubuntu-latest

steps:
- name: checkout
uses: actions/checkout@v3

- name: Docker Login
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_TOKEN }}

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2

- name: Build and push
uses: docker/build-push-action@v4
with:
context: .
file: ./Dockerfile
push: true
tags: niranjang2/books_management_service:${{ github.sha }}

setup-and-deploy:
needs: [create-image-and-push-to-dockerhub]

name: Setup and Deploy
runs-on: ubuntu-latest

permissions:
contents: 'read'
id-token: 'write'

steps:
- name: Checkout
uses: actions/checkout@v3

- name: Authenticate to Google Cloud
uses: google-github-actions/auth@v1
with:
credentials_json: ${{ secrets.GKE_SA }}

- name: Get GKE Credentials
uses: google-github-actions/get-gke-credentials@v1
with:
cluster_name: ${{ secrets.GKE_CLUSTER_NAME }}
location: ${{ secrets.GKE_CLUSTER_ZONE }}

- name: Deploy on the GKE
run: |-
sed -i -e 's/DOCKER_IMG_TAG/'${{ github.sha }}'/' ./kubernetes/book-mgmt-api-deploy.yaml
kubectl apply -f ./kubernetes/

Once you submit a pull request or commit changes to the main branch of the GitHub repository, the automated workflow will be triggered automatically. To track the workflow's progress, you can monitor it in the Actions section of the project's interface. For a clearer understanding, please refer to the image below.

GitHub Workflow

Removing GKE resources

If you have achieved your goal of automating the deployment process of your NodeJS application on GKE using GitHub Actions, then to reduce the billing, please use the following commands to remove the resources.

#To delete deployments,services,pods,replicasets
kubectl delete all --all -n development
#To delete the configmap database-config
kubectl delete configmap/database-config -n development

#To delete the secret mysql-credentials
kubectl delete secret/mysql-credentials -n development

Conclusion

We have successfully automated the deployment process of the NodeJS application on Google Kubernetes Engine (GKE) with GitHub Actions, which saves time and reduces errors. GitHub Action is a flexible platform for automating deployment pipelines, and GKE provides a reliable infrastructure for deploying and managing applications easily.

You can find the GitHub Action Configuration file in the GitHub folder by referring to the GitHub URL provided. Note that in the repository, the folder is intentionally named as github. If you are using a fork of this repository, please rename the github folder to .github .

If you have any comments or queries about this, please mention them in the comments section below.

--

--