Deep Dive Into the Whole Story Behind Building and Maintenance Helm Package for Microservice App (Moleculer Nodejs Framework)

Mahmoud Almasri
Knawat Ninja
6 min readNov 16, 2021

--

Part2: This story is a part of the CI/CD process that we are using at

Knawat

In the previous article, we talked about how to deploy your microservice application on K8s using moleculer helm package in one command.

Today we are going to talk more in-depth about the moleculer helm package and how we have created it.

Introduction:

Helm: Package manager for Kubernetes.

Helm Chart: Helm uses a packaging format called charts. A chart is a collection of files that describe a related set of Kubernetes resources. A single chart might be used to deploy something simple, like a memcached pod, or something complex, like a full web app stack with HTTP servers, databases, caches, and so on.

Moleculer: Progressive microservices framework for Node.js.

Moleculer’s Laboratory: It’s an APM service for moleculer app.

Moleculer’s Laboratory is a developer tool for Moleculer-based microservices projects. It’s not a cloud-based APM service.

Moleculer’s Laboratory Service

The infrastructure of the App:

Scenario 1:

Deployment Scenario 1 — All Services in the same k8s Deployment

In this scenario, we are deploying all the services of the App into one k8s deployment (one container), We use this scenario for testing propose.

Scenario 2:

Deployment Scenario 2— Each Service in a different Deployment

In this scenario, we are deploying each service of the App into a k8s deployment.

Deployment Ways:

Without helm:

We have to create a configuration file (yaml file) for:

1. Each k8s deployment

2. Each k8s service

3. Ingress

4. FrontEnd and BackEnd Configuration for the Loadbalancer

5. SSL Certificate

6. Secrets

7. Configuration map

In the end, you will find that you need to write more than 10 configuration files if you have for example 5 services in your app to deploy the app to the Kubernetes cluster.

deployment files for one app

With moleculer’s helm package:

helm repo add helm-charts https://knawat.github.io/helm-charts
helm install [RELEASE_NAME] helm-charts/molecule

And that’s it!.

You don’t need to do more than that, all you need now is to specify your needed configuration.

You can find all the options in the repo.

How we created the moleculer’s helm package:

First, we grouped the configuration of the k8s deployment into three main sections:
1. Deployment Configuration: this will contain all yaml configuration for the k8s Deployments type.

2. Service configuration: this will contain all yaml configurations for the k8s Service type.

3. Ingress Configuration: this includes: ingress configuration, SSL certificate configuration, and frontend configurations, and these configurations will create a load balancer for us and set its configurations.

Second, we started to build the Helm chart:

The structure of the helm chart

For moleculer based app we have only two services two it exposed to the outside (API service, Lab service), so we have created service.yaml file:

In this chart, we tell helm that if we have a service called “API” we specified in the helm variable “container.services” go and create a k8s service and point it to the api deployment.

helm repo add helm-charts https://knawat.github.io/helm-charts
helm upgrade [RELEASE_NAME] helm-charts/moleculer \
--install \
-n [NAMESPACE] \
--create-namespace \
....
--set container.services="{api,gdpr,oms,stores,zones}" \
....

And if you enabled the Moleculer Lab via the helm variable “laboratory.enabled” it will create a service for the Moleculer Laboratory.

helm repo add helm-charts https://knawat.github.io/helm-charts
helm upgrade [RELEASE_NAME] helm-charts/moleculer \
--install \
-n [NAMESPACE] \
--create-namespace \
....
--set laboratory.enabled=false \
....

For the deployment, we tell helm if we need to deploy each service of our app in a different container throw this variable “container.separateContainer”

So, if we set the variable to true, it’s will loop into the value of this variable “container.services” and create a deployment for each service, else it will create one deployment which contains all services

helm repo add helm-charts https://knawat.github.io/helm-charts
helm upgrade [RELEASE_NAME] helm-charts/moleculer \
--install \
-n [NAMESPACE] \
--create-namespace \
....
--set container.separateContainer=true \
--set container.services="{api,gdpr,oms,stores,zones}" \

....

Here you need to specify the image URL that you are going to use to deploy the container:

helm repo add helm-charts https://knawat.github.io/helm-charts
helm upgrade [RELEASE_NAME] helm-charts/moleculer \
--install \
-n [NAMESPACE] \
--create-namespace \
....
--set container.separateContainer=true \
--set container.services="{api,gdpr,oms,stores,zones}"
\
--set image.repository=”gcr.io/PROJECT_ID/REPO_NAME” \
--set image.tag=”[TAG]” \

....

Also, we create a configuration map to store the environment variables of the application

To add environment variables to your app you need just to add this configuration:

helm repo add helm-charts https://knawat.github.io/helm-charts
helm upgrade [RELEASE_NAME] helm-charts/moleculer \
--install \
-n [NAMESPACE] \
--create-namespace \
....
--set environment.env.VARIABLE_1="VALUE" \
--set environment.env.VARIABLE_2="VALUE" \

....

And if you need to save your environment variables into a secret, we created a secrets configuration file:

To add secrets, you need to add this configuration:

helm repo add helm-charts https://mhm0ud.github.io/helm-charts
helm upgrade [RELEASE_NAME] helm-charts/moleculer \
--install \
-n [NAMESPACE] \
--create-namespace \
....
--set environment.secret.MONGO_URI=$MONGO_URL \
....

Also, to add a cron job we created a cron job configuration file:

This cron will be enabled if you set this configuration:

helm repo add helm-charts https://mhm0ud.github.io/helm-charts
helm upgrade [RELEASE_NAME] helm-charts/moleculer \
--install \
-n [NAMESPACE] \
--create-namespace \
....
--set cron.enabled=true \
....

The cron will call a moleculer action via moleculer cli, to configure the cron you have to add these configurations:

helm repo add helm-charts https://knawat.github.io/helm-charts
helm upgrade [RELEASE_NAME] helm-charts/moleculer \
--install \
-n [NAMESPACE] \
--create-namespace \
....
--set cron.list[0].name=[CRON_NAME] \
--set cron.list[0].schedule=[CRON_SCHEDULE] \
--set cron.list[0].command=[MOLECULE_COMMAND] \
....

You can add as many crons as you want.

Finally, for the ingress configuration we created this file:

First, it will create an SSL certificate for the domain name, then the ingress controller, you need to specify here the DNS, host path, and the name of the static IP that you are going to use it.

helm repo add helm-charts https://knawat.github.io/helm-charts
helm upgrade [RELEASE_NAME] helm-charts/moleculer \
--install \
-n [NAMESPACE] \
--create-namespace \
....
--set ingress.annotations."kubernetes\.io/ingress\.global-static-ip-name"="[NAME_OF_STATIC_IP]" \
--set image.hosts[0].host="[DNS]" \
--set image.hosts[0].paths[0].path="/*" \
--set image.hosts[0].paths[0].backend.serviceName="api" \
--set image.hosts[0].paths[0].backend.servicePort="80" \

....

In Conclusion:

A full example of all configurations this helm chart

helm repo add helm-charts https://knawat.github.io/helm-charts
helm upgrade [RELEASE_NAME] helm-charts/moleculer \
--install \
-n [NAMESPACE] \
--create-namespace \
....
--set ingress.annotations."kubernetes\.io/ingress\.global-static-ip-name"="[NAME_OF_STATIC_IP]" \
--set image.hosts[0].host="[DNS]" \
--set image.hosts[0].paths[0].path="/*" \
--set image.hosts[0].paths[0].backend.serviceName="api" \
--set image.hosts[0].paths[0].backend.servicePort="80" \
--set container.name="[CONTAINER_NAME]" \
--set container.services="{api,gdpr,oms,stores,zones}" \
--set image.repository="gcr.io/mp-dev-266506/mp-image" \
--set image.tag="$BUDDY_EXECUTION_REVISION" \
--set cron.enabled=false \

--set environment.secret.MONGO_URI=$MONGO_URL \
--set environment.env.VARIABLE_1="VALUE"

--

--