Setup Microservices on Kubernetes — Write a Configuration File | by Quân Huỳnh | Jul, 2022

Deployed the microservice to Kubernetes

Photograph by Savannah Wakefield on Unsplash

On this tutorial, we’ll learn to arrange a Microservices System on Kubernetes. Partially one we’re going to discuss easy methods to write a configuration file for every element of the microservice system.

That is half one within the sequence Arrange Microservice on Kubernetes:

  1. Arrange a Microservices on Kubernetes – Write Config File.
  2. Arrange a Microservices on Kubernetes – Automating Kubernetes with ArgoCD.
  3. Arrange a Microservices on Kubernetes – Implement CI/CD.

We use a framework known as Moleculer to construct a microservices system within the above diagram. Moleculer is a quick, trendy, and highly effective microservices framework for Node.js. It lets you construct environment friendly, dependable & scalable providers. Moleculer gives many options for constructing and managing your microservices.

API Gateway exposes Moleculer providers to end-users. The gateway is a daily Moleculer service operating a (HTTP, WebSockets, and many others.) server.

NATS, which is the transporter, it’s a communication bus that providers use to alternate messages. It transfers occasions, requests, and responses.

Classes and Information providers are a easy JavaScript module containing some a part of a posh software. It’s remoted and self-contained.

Cache System makes use of Redis and Database makes use of Postgres.

I’ve briefly talked in regards to the structure that we are going to deploy on Kubernetes, we’ll begin working now.

Clone supply code from https://github.com/hoalongnatsu/microservices. Go to the folder microservices/code and run the next instructions to construct a picture. The picture title ought to be <docker-hub-username>/microservice.

git clone https://github.com/hoalongnatsu/microservices.git && cd microservices/code
docker construct . -t 080196/microservice
docker push 080196/microservice

Subsequent, we’re going to write a configuration file for every element.

First, we write a config file for API Gateway. Create a file named api-gateway-deployment.yaml.

apiVersion: apps/v1
type: Deployment
metadata:
title: api-gateway
labels:
element: api-gateway
spec:
revisionHistoryLimit: 1
selector:
matchLabels:
element: api-gateway
template:
metadata:
labels:
element: api-gateway
spec:
containers:
- title: api-gateway
picture: 080196/microservice
ports:
- title: http
containerPort: 3000
protocol: TCP
livenessProbe:
httpGet:
path: /
port: http
readinessProbe:
httpGet:
path: /
port: http
env:
- title: NODE_ENV
worth: testing
- title: SERVICEDIR
worth: dist/providers
- title: SERVICES
worth: api
- title: PORT
worth: "3000"
- title: CACHER
worth: redis://redis:6379
- title: DB_HOST
worth: postgres
- title: DB_PORT
worth: "5432"
- title: DB_NAME
worth: postgres
- title: DB_USER
worth: postgres
- title: DB_PASSWORD
worth: postgres
- title: TRANSPORTER
worth: nats://nats:4222

The picture named 080196/microservice, that now we have beforehand constructed, together with three providers named api, classes, and information. We choose the service that should run by passing the title of the service into an atmosphere variable named SERVICES.

Within the above config file, we cross the worth as api for API gateway.

If you happen to take a look at the code within the file code/providers/api.service.ts, we’ll see the setting for the API gateway on line 15.

...
settings: {
port: course of.env.PORT || 3001,
...

With the PORT env, the API gateway listens on port 3000. The CACHER env use to declare the Redis host that the service makes use of. The env with prefix DB_ is used for Database. Run the next command to create Deployment.

kubectl apply -f api-gateway-deployment.yaml

Consequence.

$ kubectl get deploy
NAME READY UP-TO-DATE AVAILABLE AGE
api-gateway 0/1 1 0 100s

We now have created the API Gateway, however while you get the pod. You will note that it doesn’t run efficiently however might be restarted time and again.

$ kubectl get pod
NAME READY STATUS RESTARTS AGE
api-gateway-79688cf6f5-g88f2 0/1 Working 2 93s

Examine logs to search out out why.

$ kubectl logs api-gateway-79688cf6f5-g88f2
...
[2021-11-07T14:53:37.449Z] ERROR api-gateway-79688cf6f5-g88f2-28/CACHER: Error: getaddrinfo EAI_AGAIN redis
at GetAddrInfoReqWrap.onlookup [as oncomplete] (dns.js:60:26)
errno: 'EAI_AGAIN',
code: 'EAI_AGAIN',
syscall: 'getaddrinfo',
hostname: 'redis'

The error proven here’s a pod can not hook up with Redis, as a result of now we have not created any Redis but, subsequent we’ll create Redis.

Create a file named redis-deployment.yaml.

apiVersion: apps/v1
type: Deployment
metadata:
title: redis
labels:
element: redis
spec:
technique:
kind: Recreate
selector:
matchLabels:
element: redis
template:
metadata:
labels:
element: redis
spec:
containers:
- title: redis
picture: redis
ports:
- containerPort: 6379

Run the next instructions.

$ kubectl apply -f redis-deployment.yaml
deployment.apps/redis created
$ kubectl get deploy
NAME READY UP-TO-DATE AVAILABLE AGE
api-gateway 0/1 1 0 16m
redis 1/1 1 1 14s

Subsequent, if we need to hook up with Redis, we have to create a Service useful resource for it. Create a file named redis-service.yaml.

apiVersion: v1
type: Service
metadata:
title: redis
labels:
element: redis
spec:
selector:
element: redis
ports:
- port: 6379

Working a command.

kubectl apply -f redis-service.yaml

Restarting the API Gateway Deployment.

kubectl rollout restart deploy api-gateway

Examine logs of the API Gateway and we nonetheless see it’s not operating.

$ kubectl logs api-gateway-7f4d5f54f-lzgkd
...
[2021-11-07T15:05:10.388Z] INFO api-gateway-7f4d5f54f-lzgkd-28/CACHER: Redis cacher related.
Sequelize CLI [Node: 12.13.0, CLI: 6.2.0, ORM: 6.6.5]Loaded configuration file "migrate/config.js".
Utilizing atmosphere "testing".
ERROR: join ECONNREFUSED 127.0.0.1:5432Error: Command failed: sequelize-cli db:migrate
ERROR: join ECONNREFUSED 127.0.0.1:5432
at ChildProcess.exithandler (child_process.js:295:12)
at ChildProcess.emit (occasions.js:210:5)
at maybeClose (inside/child_process.js:1021:16)
at Course of.ChildProcess._handle.onexit (inside/child_process.js:283:5)
killed: false,
code: 1,
sign: null,
cmd: 'sequelize-cli db:migrate'

Sequelize CLI [Node: 12.13.0, CLI: 6.2.0, ORM: 6.6.5]
Loaded configuration file "migrate/config.js".
Utilizing atmosphere "testing".
ERROR: join ECONNREFUSED 127.0.0.1:5432
...

The error proven is a pod can’t hook up with the Database. Subsequent, we’ll create a Database.

To deploy the Database, we use StatefulSet. Create a file named postgres-statefulset.yaml.

apiVersion: apps/v1
type: StatefulSet
metadata:
title: postgres
labels:
element: postgres
spec:
selector:
matchLabels:
element: postgres
serviceName: postgres
template:
metadata:
labels:
element: postgres
spec:
containers:
- title: postgres
picture: postgres:11
ports:
- containerPort: 5432
volumeMounts:
- mountPath: /var/lib/postgresql/knowledge
title: postgres-data
env:
- title: POSTGRES_DB
worth: postgres
- title: POSTGRES_USER
worth: postgres
- title: POSTGRES_PASSWORD
worth: postgres
volumeClaimTemplates:
- metadata:
title: postgres-data
spec:
accessModes:
- ReadWriteOnce
storageClassName: hostpath
sources:
requests:
storage: 5Gi

The storageClassName area relies on your Kubernetes cluster, you’ll specify the corresponding storageClassName area. Run the next command to create STS.

kubectl apply -f postgres-statefulset.yaml

Create a file named postgres-service.yaml for the Database Service sources.

apiVersion: v1
type: Service
metadata:
title: postgres
labels:
element: postgres
spec:
selector:
element: postgres
ports:
- port: 5432

Create it.

kubectl apply -f postgres-service.yaml

Restarting the API Gateway Deployment.

kubectl rollout restart deploy api-gateway

Examine logs of the API Gateway and we’ll see it’s operating efficiently.

Subsequent, we deploy classes and information providers.

Create a file named categories-news-deployment.yaml.

apiVersion: apps/v1
type: Deployment
metadata:
title: categories-service
labels:
element: categories-service
spec:
revisionHistoryLimit: 1
selector:
matchLabels:
element: categories-service
template:
metadata:
labels:
element: categories-service
spec:
containers:
- title: categories-service
picture: 080196/microservice
env:
- title: NODE_ENV
worth: testing
- title: SERVICEDIR
worth: dist/providers
- title: SERVICES
worth: classes
- title: CACHER
worth: redis://redis:6379
- title: DB_HOST
worth: postgres
- title: DB_PORT
worth: "5432"
- title: DB_NAME
worth: postgres
- title: DB_USER
worth: postgres
- title: DB_PASSWORD
worth: postgres
- title: TRANSPORTER
worth: nats://nats:4222
---
apiVersion: apps/v1
type: Deployment
metadata:
title: news-service
labels:
element: news-service
spec:
revisionHistoryLimit: 1
selector:
matchLabels:
element: news-service
template:
metadata:
labels:
element: news-service
spec:
containers:
- title: news-service
picture: 080196/microservice
env:
- title: NODE_ENV
worth: testing
- title: SERVICEDIR
worth: dist/providers
- title: SERVICES
worth: information
- title: CACHER
worth: redis://redis:6379
- title: DB_HOST
worth: postgres
- title: DB_PORT
worth: "5432"
- title: DB_NAME
worth: postgres
- title: DB_USER
worth: postgres
- title: DB_PASSWORD
worth: postgres
- title: TRANSPORTER
worth: nats://nats:4222

Create it.

kubectl apply -f categories-news-deployment.yaml

Subsequent, we create a NATS transporter for our moleculer providers can talk with others.

Create a file named nats-deployment.yaml.

apiVersion: apps/v1
type: Deployment
metadata:
title: nats
labels:
element: nats
spec:
technique:
kind: Recreate
selector:
matchLabels:
element: nats
template:
metadata:
labels:
element: nats
spec:
containers:
- title: nats
picture: nats
ports:
- containerPort: 4222

Create it.

kubectl apply -f nats-deployment.yaml

Create a file named nats-service.yaml for NATS.

apiVersion: v1
type: Service
metadata:
title: nats
labels:
element: nats
spec:
selector:
element: nats
ports:
- port: 4222

Create it.

kubectl apply -f nats-service.yaml

Examine logs of the API Gateway and we’ll see classes and information providers are related to API Gateway.

So our software has run efficiently 😁.

However did you discover that the env variables we declare are a bit lengthy and repetitive in our deployment recordsdata? We will make it clearer.

We will use ConfigMap for centralized configuration. Create a file named microservice-cm.yaml.

apiVersion: v1
type: ConfigMap
metadata:
title: microservice-cm
labels:
element: microservice-cm
knowledge:
NODE_ENV: testing
SERVICEDIR: dist/providers
TRANSPORTER: nats://nats:4222
CACHER: redis://redis:6379
DB_NAME: postgres
DB_HOST: postgres
DB_USER: postgres
DB_PASSWORD: postgres
DB_PORT: "5432"

Create it.

kubectl apply -f microservice-cm.yaml

Replace file api-gateway-deployment.yaml.

apiVersion: apps/v1
type: Deployment
metadata:
title: api-gateway
labels:
element: api-gateway
spec:
revisionHistoryLimit: 1
selector:
matchLabels:
element: api-gateway
template:
metadata:
labels:
element: api-gateway
spec:
containers:
- title: api-gateway
picture: 080196/microservice
ports:
- title: http
containerPort: 3000
protocol: TCP
livenessProbe:
httpGet:
path: /
port: http
readinessProbe:
httpGet:
path: /
port: http
env:
- title: SERVICES
worth: api
- title: PORT
worth: "3000"
envFrom:
- configMapRef:
title: microservice-cm

Replace file categories-news-deployment.yaml.

apiVersion: apps/v1
type: Deployment
metadata:
title: categories-service
labels:
element: categories-service
spec:
revisionHistoryLimit: 1
selector:
matchLabels:
element: categories-service
template:
metadata:
labels:
element: categories-service
spec:
containers:
- title: categories-service
picture: 080196/microservice
env:
- title: SERVICES
worth: classes
envFrom:
- configMapRef:
title: microservice-cm
---
apiVersion: apps/v1
type: Deployment
metadata:
title: news-service
labels:
element: news-service
spec:
revisionHistoryLimit: 1
selector:
matchLabels:
element: news-service
template:
metadata:
labels:
element: news-service
spec:
containers:
- title: news-service
picture: 080196/microservice
env:
- title: SERVICES
worth: information
envFrom:
- configMapRef:
title: microservice-cm

Replace it.

kubectl apply -f api-gateway-deployment.yaml
kubectl apply -f categories-news-deployment.yaml

Examine our system.

$ kubectl get pod
NAME READY STATUS RESTARTS
api-gateway-86b67895fd-cphmv 1/1 Working 0
categories-service-84c74cd87c-zjtd2 1/1 Working 0
nats-65687968fc-2drwp 1/1 Working 0
news-service-69f45b8668-kv9dm 1/1 Working 0
postgres-0 1/1 Working 0
redis-58c4799ccc-qhv2z 1/1 Working 0

More Posts