Kubernetes Deployment: GKE ReactJS Automation via GitHub Actions

Niranjan Gawali
Globant
Published in
9 min readMay 14, 2024

In the Kubernetes deployment series, we have already covered four topics:

In our previous blog, we successfully deployed a ReactJS app on Google Kubernetes Engine. Now, in this final blog, we will automate the deployment process using GitHub Actions.

GitHub Actions is a tool by GitHub that helps automate tasks in our development process. GitHub Actions allows us to create workflows. These workflows build, test, and deploy our applications. This saves time and effort, especially when managing multiple deployments.

By integrating code changes with the deployment pipeline, GitHub Actions simplifies application deployment. It ensures consistent and reliable deployments, improving our development process.

This blog will teach how to automate deploying a NodeJS app on GKE with GitHub Actions. Deploying our application is easier, improving our development workflow.

Configuring the ReactJS Application

Part V will use the ReactJS app repository from the last blog. The necessary configuration files for Kubernetes can be found in the GitHub repository’s kubernetes folder. The Dockerfile packages the application as a container image. It’s in the repository’s root directory.

We will automate deploying the ReactJS app to GKE with GitHub Actions in this blog. We will refer to the Kubernetes and Docker configuration files. This will help us accomplish the task.

Please check the previous blog for more details on the Docker and Kubernetes configuration we’ll be using.

Please refer to the provided screenshot of the project structure. It includes a kubernetes folder containing essential configuration files for our deployment.

React Application Project Structure

GitHub Account Setup

To communicate securely, you must set up secrets in your repository for GitHub and the GKE cluster. To do this, go to your repository’s settings page and choose the Secrets option from the menu on the left. For more information about GitHub Secrets, you can visit this link.

Please follow the instructions below to configure the GitHub secrets:

  • 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 will also need to add the cluster name that you have 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: To add the Cluster location in the GitHub secrets, use the key GKE_CLUSTER_ZONE. The cluster we have created is located in the asia-south1 region.
  • REACT_APP_BASE_URL: To include the base URL that the React Application uses, you must add it to your GitHub repository's secrets. Use the key REACT_APP_BASE_URL for this purpose.
  • GKE Service Account: To automate the deployment process, you need a service account for GKE. Follow these steps to create the service account and generate its key, then add the key to GitHub as a secret using the key GKE_SA.

The GitHub secrets mentioned earlier, except for the GKE Service Account, are ready for you to use. Here are the steps to create a GCP service account and add it to the GitHub secrets, based on the provided guidelines.

  • Open the cloud shell by clicking on the top right corner of the GCP console. Set the default project with this command.
glcoud config set project <project-id>
  • Create the service account with this command. Skip if you already have one.
gcloud iam service-accounts create <service-account-name>
  • You need to grant the service account access to your cluster. The command grants the 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
  • Encode the service account key into base64 format before adding it to the GitHub Secret.
cat gsa-key.json | base64 #add the response to the GitHub Secret

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

Once all the GitHub secrets are added it looks as below.

GitHub Secrets
GitHub Secrets

Creating a GitHub Actions Workflow

Create a folder .github at the root of the project and create a subfolder workflows within it. In the workflows folder create a file with the name build-and-deploy.yaml. In this file, we will add the configuration of the GitHub actions.

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

name: Docker build and Deploy
on:
push:
branches: [main]
pull_request:
branches: [main]

You can define a workflow called Docker build and Deploy in your GitHub repository. This workflow will be triggered by events that occur in the repository.

The on keyword specifies the events that should trigger the workflow. The workflow triggers when the main branch receives a push or a pull request opens for it.

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/book-management-app:${{ github.sha }}
build-args: REACT_APP_BASE_URL=${{ secrets.REACT_APP_BASE_URL }}

We define the job create-image-and-push-to-dockerhub as the name suggests. In this job, we will create the docker image and push it to the docker hub.

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.

In the second step of the workflow, the docker/login-action@v2 action is used to log in to DockerHub. This action uses Docker credentials stored in GitHub Secrets. It was mentioned in the previous section.

The third step docker/setup-buildx-action@v2 is used to set up the Docker Buildx builder. It builds multi-architecture Docker images.

In the fourth step of the GitHub deployment process, the docker/build-push-action@v4 action is used. This action builds the Docker image based on the instructions specified in the Dockerfile. It also tags the image with a unique Git commit hash and pushes it to the DockerHub registry.

The action also allows you to pass environment variables that are needed during the build process. You can do this by using the build-args parameter. The REACT_APP_BASE_URL environment variable is passed via a parameter. Its value is retrieved from the secrets.REACT_APP_BASE_URL secret in GitHub. By using build arguments, developers can customize their Docker image with values that are specific to the environment, without having to make changes to the Dockerfile itself.

The git commit hash in this step refers to the unique identifier of the triggering commit. The hash is a 40-character string that is generated by Git to uniquely identify each commit in a repository.

In the workflow, we use the Git commit hash as a tag for the Docker image. Each image has a unique identifier and version linked to the code changes. This correlation triggers the workflow. By using the commit hash as a tag, it becomes easier to track and manage different image versions. It also provides the flexibility to roll back to a specific version if necessary.

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-app-deploy.yaml
kubectl apply -f ./kubernetes/

This job is the second step in the configuration process. It focuses on automating the deployment of a Kubernetes application to a Google Kubernetes Engine (GKE) cluster. The workflow for this job starts when the create-image-and-push-to-dockerhub job is completed.

This job has a dependency on the create-image-and-push-to-dockerhub job. It requires the successful completion of that job, which involves building and pushing the Docker image to DockerHub. Only after the create-image-and-push-to-dockerhub job finishes can this job 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 contents of the repository and write access to an ID token.

There are multiple steps performed in this job.

  1. The first step checks out the code from the repository using the actions/checkout@v3 action.
  2. The second step is to authenticate to Google Cloud using the google-github-actions/auth@v1 action. To complete this step, you will need a JSON file with credentials stored in GitHub Secrets.
  3. In the third step, the google-github-actions/get-gke-credentials@v1 action is used to fetch the GKE credentials for the specified cluster. The cluster name and location are stored in GitHub Secrets.
  4. Moving to the fourth step, the Kubernetes application is deployed to the GKE cluster. The DOCKER_IMG_TAG Kubernetes configuration file is replaced with the Git commit hash. This hash comes from the Docker image uploaded to DockerHub. This ensures the correct version of the Docker image is deployed. The kubectl apply command deploys the Kubernetes resources from the kubernetes/ directory.

Please take a look at the complete configuration file provided 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/book-management-app:${{ github.sha }}
build-args: REACT_APP_BASE_URL=${{ secrets.REACT_APP_BASE_URL }}

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-app-deploy.yaml
kubectl apply -f ./kubernetes/

Once you submit a pull request or apply changes, the automated workflow will be initiated. You can monitor the workflow’s progress within the Actions tab of the project’s interface. Refer to the image below to review the status of GitHub jobs.

GitHub Workflow
GitHub Workflow

Removing GKE resources

If you achieve your goal and want to delete resources to reduce the billing. Use the following commands to remove the resources.

#To delete deployments,services,pods,replicasets
kubectl delete all --all -n development

Conclusion

We automated deploying the ReactJS app on Google Kubernetes Engine using GitHub Actions. This automation saves time and reduces errors. GitHub Actions is a flexible platform for automating deployment pipelines. GKE offers a stable platform for deploying and managing apps.

You can find the GitHub Action Configuration file in the GitHub folder. Refer to the GitHub URL for guidance. Note that 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.

--

--