Deploy nodejs Helm chart on EKS using GitHub Actions [2 Steps]

In this article we are going to cover Deploy nodejs Helm chart on EKS using GitHub Actions.

Step #1:Create Amazon EKS cluster using eksctl:

Please follow below article to Create Amazon EKS cluster using eksctl.

How to Create Amazon EKS cluster using eksctl

Step #2:Create node.js Hello world application

In this step we need to create node.js code Hello world code using below code

Create package.json file

package.json

{
  "name": "docker_web_app",
  "version": "1.0.0",
  "description": "Node.js on Docker",
  "author": "First Last <[email protected]>",
  "main": "server.js",
  "scripts": {
    "start": "node server.js"
  },
  "dependencies": {
    "express": "^4.18.2"
  }
}

Create server.js file

'use strict';

const express = require('express');

// Constants
const PORT = 8080;
const HOST = '0.0.0.0';

// App
const app = express();
app.get('/', (req, res) => {
  res.send('Hello World');
});

app.listen(PORT, HOST, () => {
  console.log(`Running on http://${HOST}:${PORT}`);
});

Create nodejs Dockerfile

A Dockerfile for a Node.js application allows you to create a container image that includes all the necessary dependencies and configurations to run your Node.js application. Below is an example of a simple Dockerfile for a Node.js application:

# Use the official Node.js image as the base image
FROM node:18

# Set the working directory inside the container
WORKDIR /usr/src/app

# Install app dependencies
# A wildcard is used to ensure both package.json AND package-lock.json are copied
# where available (npm@5+)
# Copy package.json and package-lock.json to the working directory
COPY package*.json ./

# Install Node.js dependencies
RUN npm install
# If you are building your code for production
# RUN npm ci --omit=dev

# Bundle app source
COPY . .

# Expose the port on which your Node.js application will run
EXPOSE 8080

# Command to run your Node.js application
CMD [ "node", "server.js" ]

Create .dockerignore file

node_modules
npm-debug.log

Here’s a breakdown of each step:

  1. FROM node:18: This sets the base image for the container. In this case, we are using the official Node.js image with version 14. You can choose a different version based on your application’s requirements.
  2. WORKDIR /usr/src/app: This sets the working directory inside the container to /usr/src/app. It is a good practice to use a consistent location for your application files.
  3. COPY package*.json ./: This copies the package.json and package-lock.json files from the host (where your Dockerfile is located) to the working directory inside the container.
  4. RUN npm install: This installs the Node.js dependencies based on the package.json file. It is executed during the image build process, ensuring the application’s dependencies are installed within the container.
  5. COPY . .: This copies all the remaining application files from the host to the working directory inside the container.
  6. EXPOSE 3000: This exposes port 3000 on the container. If your Node.js application runs on a different port, modify this value accordingly.
  7. CMD ["npm", "start"]: This specifies the command that will be executed when the container starts. In this case, it runs npm start, which should be defined in your package.json as the start script for your Node.js application.

Step #3:Build and run Node.js docker image

Building your image:
Go to the directory that has your Dockerfile and run the following command to build the Docker image. The -t flag lets you tag your image so it’s easier to find later using the docker images command

Note: Before run this command you need to install docker and give some permission

sudo apt  install docker.io  
sudo usermod -aG docker $USER
sudo chmod 666 /var/run/docker.sock 

To build the Docker image, navigate to the directory containing your Dockerfile and run the following command:

docker build . -t <your username>/node-app

Your image will now be listed by Docker:

docker images

Output:

ubuntu@ip-172-31-5-137:~$ docker images
REPOSITORY                TAG       IMAGE ID       CREATED       SIZE
devopshint/node-web-app   latest    d832f1fd89ca   2 hours ago   1.1GB
node                      18        d9ad63743e72   2 days ago    1.09GB

Run the image:
Running your image with -d runs the container in detached mode, leaving the container running in the background. The -p flag redirects a public port to a private port inside the container.

docker run -p 49160:8080 -d <your username>/node-app


To test your app, get the port of your app that Docker mapped:

docker ps

output:

CONTAINER ID   IMAGE                     COMMAND                  CREATED       STATUS       PORTS                                         NAMES
5d17d04e0f42   devopshint/node-web-app   "docker-entrypoint.s…"   2 hours ago   Up 2 hours   0.0.0.0:49160->8080/tcp, :::49160->8080/tcp   lucid_austin

Step #4:Run Docker image on browser

Now let access in browser so copy your instance ip and port number

Deploy nodejs Helm chart on EKS using GitHub Actions [2 Steps] 1

Step #5:Push Node.js code and Docker on GitHub Repository:

Firstly let’s clone your repo using below command:

git clone <your-repo-HTTPS>

Copy your node.js and docker files and paste in your repo folder

Then push this code into your repo using below commands:

git add .
git commit -m "files added"
git push

Step #6:Add Secrets in GitHub Repository

In our repository we need to add two secrets here

  1. AWS_ACCESS_KEY_ID
  2. AWS_SECRET_ACCESS_KEY
Deploy nodejs Helm chart on EKS using GitHub Actions [2 Steps] 2

Step #7:Create github Action workflow to build and push docker image to ECR

Let’s create workflow using below code:

name: Node js app deploy to EKS
on:
  push:
    branches: [ "main" ]
  pull_request:
    branches: [ "main" ]

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
    - name: Checkout code
      uses: actions/checkout@v3

    - name: Install kubectl
      uses: azure/[email protected]
      with:
        version: 'v1.27.0' # default is latest stable
      id: install

    - name: Configure AWS Credentials
      uses: aws-actions/configure-aws-credentials@v1
      with:
        aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
        aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
        aws-region: ap-south-1

    - name: Login to Amazon ECR
      id: login-ecr
      uses: aws-actions/amazon-ecr-login@v1

    - name: Build, tag, and push docker image to Amazon ECR
      env:
        REGISTRY: ${{ steps.login-ecr.outputs.registry }}
        REPOSITORY: devops-img
        IMAGE_TAG: latest
      run: |
        docker build -t $REGISTRY/$REPOSITORY:$IMAGE_TAG .
        docker push $REGISTRY/$REPOSITORY:$IMAGE_TAG

    - name: Update kube config
      run: aws eks update-kubeconfig --name sample

Step #8:Run GitHub Action workflow

Deploy nodejs Helm chart on EKS using GitHub Actions [2 Steps] 3

Step #9:Install Helm on EKS cluster

Download the helm installation script using below command:

curl -fsSL -o get_helm.sh https://raw.githubusercontent.com/helm/helm/master/scripts/get-helm-3

Add execute permissions to the downloaded script:

chmod +x get_helm.sh

Execute the installation script:

./get_helm.sh

Validate helm installation by executing the helm command:

helm

Check helm version:

helm version

Step #10:Create node-app helm chart

We will create a Helm chart node-app-chart for the Node.js application. To create the Helm chart, run this Helm command:

helm create node-app-chart
Deploy nodejs Helm chart on EKS using GitHub Actions [2 Steps] 4
  1. Charts folder

This folder contains any other dependencies for the node-app-chart.

  1. Template folder

This folder contains all Kubernetes YAML or manifest files for creating Kubernetes objects such as Kubernetes Deployment, Kubernetes Service, Configmaps, and Secrets. In this guide, we will only require the deployment.yaml and service.yaml. We will modify these two files and add our configurations for deploying the Node.js application.

  1. Chart.yaml

This YAML file contains descriptive information about the Helm chart such as the chart name and version.

  1. Values.yaml

This YAML file contains the application configuration values that the other YAML files in the template folder will use. These values include the image name, container name, port mapping, number of pods, and the type of Kubernetes service.

Step #11:modify helm chart files

Lets modify values.yaml, deployment.yaml and service.yaml files using below code

values.yaml
# Default values for node-app.
# This is a YAML-formatted file.
# Declare variables to be passed into your templates.

replicaCount: 1

image:
  repository: 908198849120.dkr.ecr.ap-south-1.amazonaws.com/devops-img
  pullPolicy: IfNotPresent
  # Overrides the image tag whose default is the chart appVersion.
  tag: "latest"

imagePullSecrets: []
nameOverride: ""
fullnameOverride: ""

serviceAccount:
  # Specifies whether a service account should be created
  create: true
  # Annotations to add to the service account
  annotations: {}
  # The name of the service account to use.
  # If not set and create is true, a name is generated using the fullname template
  name: ""

podAnnotations: {}

podSecurityContext: {}
  # fsGroup: 2000

securityContext: {}
  # capabilities:
  #   drop:
  #   - ALL
  # readOnlyRootFilesystem: true
  # runAsNonRoot: true
  # runAsUser: 1000

service:
  type: LoadBalancer
  port: 80
  targetPort: 8080
  protocol: TCP
  name: node-app

ingress:
  enabled: false
  className: ""
  annotations: {}
    # kubernetes.io/ingress.class: nginx
    # kubernetes.io/tls-acme: "true"
  hosts:
    - host: chart-example.local
      paths:
        - path: /
          pathType: ImplementationSpecific
  tls: []
  #  - secretName: chart-example-tls
  #    hosts:
  #      - chart-example.local

resources: {}
  # We usually recommend not to specify default resources and to leave this as a conscious
  # choice for the user. This also increases chances charts run on environments with little
  # resources, such as Minikube. If you do want to specify resources, uncomment the following
  # lines, adjust them as necessary, and remove the curly braces after 'resources:'.
  # limits:
  #   cpu: 100m
  #   memory: 128Mi
  # requests:
  #   cpu: 100m
  #   memory: 128Mi

autoscaling:
  enabled: false
  minReplicas: 1
  maxReplicas: 100
  targetCPUUtilizationPercentage: 80
  # targetMemoryUtilizationPercentage: 80

nodeSelector: {}

tolerations: []

affinity: {}

As you can see in image repository section we need to paste ECR URI

Deploy nodejs Helm chart on EKS using GitHub Actions [2 Steps] 5

deployment.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: {{ include "node-app.fullname" . }}
  labels:
    {{- include "node-app.labels" . | nindent 4 }}
spec:
  {{- if not .Values.autoscaling.enabled }}
  replicas: {{ .Values.replicaCount }}
  {{- end }}
  selector:
    matchLabels:
      {{- include "node-app.selectorLabels" . | nindent 6 }}
  template:
    metadata:
      {{- with .Values.podAnnotations }}
      annotations:
        {{- toYaml . | nindent 8 }}
      {{- end }}
      labels:
        {{- include "node-app.selectorLabels" . | nindent 8 }}
    spec:
      {{- with .Values.imagePullSecrets }}
      imagePullSecrets:
        {{- toYaml . | nindent 8 }}
      {{- end }}
      serviceAccountName: {{ include "node-app.serviceAccountName" . }}
      securityContext:
        {{- toYaml .Values.podSecurityContext | nindent 8 }}
      containers:
        - name: {{ .Chart.Name }}
          securityContext:
            {{- toYaml .Values.securityContext | nindent 12 }}
          image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
          imagePullPolicy: {{ .Values.image.pullPolicy }}
          ports:
            - name: http
              containerPort:  {{ .Values.service.targetPort }}
              protocol: TCP
          livenessProbe:
            httpGet:
              path: /
              port: http
          readinessProbe:
            httpGet:
              path: /
              port: http
          resources:
            {{- toYaml .Values.resources | nindent 12 }}
      {{- with .Values.nodeSelector }}
      nodeSelector:
        {{- toYaml . | nindent 8 }}
      {{- end }}
      {{- with .Values.affinity }}
      affinity:
        {{- toYaml . | nindent 8 }}
      {{- end }}
      {{- with .Values.tolerations }}
      tolerations:
        {{- toYaml . | nindent 8 }}
      {{- end }}

service.yaml

apiVersion: v1
kind: Service
metadata:
  name: {{ include "node-app.fullname" . }}
  labels:
    {{- include "node-app.labels" . | nindent 4 }}
spec:
  type: {{ .Values.service.type }}
  ports:
    - port: {{ .Values.service.port }}
      targetPort: {{ .Values.service.targetPort }}
      protocol: {{ .Values.service.protocol }}
      name: {{ .Values.service.name }}
  selector:
    {{- include "node-app.selectorLabels" . | nindent 4 }}

Step #12:Push node-app folder to GitHub repo

After modifying files then we need to push this node-app folder to GitHub repository

firstly clone your repo then paste this node-app folder to your github repo folder then push this code on your repo using below commands

git add .
git commit -m "node-app added"
git push

Deploy nodejs Helm chart on EKS using GitHub Actions

Step #13:Update GitHub Action workflow

Now lets update our github workflow so here lets add new stage in GHA workflow

name: Node js app deploy to EKS
on:
  push:
    branches: [ "main" ]
  pull_request:
    branches: [ "main" ]
jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
    - name: Checkout code
      uses: actions/checkout@v3

    - name: Install kubectl
      uses: azure/[email protected]
      with:
        version: 'v1.27.0' # default is latest stable
      id: install

    - name: Configure AWS Credentials
      uses: aws-actions/configure-aws-credentials@v1
      with:
        aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
        aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
        aws-region: ap-south-1

    - name: Login to Amazon ECR
      id: login-ecr
      uses: aws-actions/amazon-ecr-login@v1

    - name: Build, tag, and push docker image to Amazon ECR
      env:
        REGISTRY: ${{ steps.login-ecr.outputs.registry }}
        REPOSITORY: devops-img
        IMAGE_TAG: latest
      run: |
        docker build -t $REGISTRY/$REPOSITORY:$IMAGE_TAG .
        docker push $REGISTRY/$REPOSITORY:$IMAGE_TAG

    - name: Update kube config
      run: aws eks update-kubeconfig --name sample
      
    - name: Deploy nodejs helm chart to EKS
      run: |
        helm install nodeapp ./node-app

You can use Github repo Deploy nodejs Helm chart on EKS using GitHub Actions

Step #14:Check pods, deployment and service on EKS

After successfully run our workflow lets check pods, deployment and service using below command:

kubectl get pods
kubectl get deploment
kubectl get service

Output:

Deploy nodejs Helm chart on EKS using GitHub Actions [2 Steps] 6

Now lets access our image in browser using Extername ip

Deploy nodejs Helm chart on EKS using GitHub Actions [2 Steps] 7

Conclusion:

We have covered Deploy nodejs Helm chart on EKS using GitHub Actions.

Shweta Mamidwar

I am Shweta Mamidwar working as a Intern in Product Company. Likes to share knowledge.

Leave a Comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Share via
Copy link
Powered by Social Snap