Pemrograman

Implementation Microservices Architecture using Kubernetes

On this occasion we will try to create an application that has implemented Microservice Architecture using Kubernetes. To better illustrate how we will try to make it, we can look at the picture below.

voting microservice architecture

In the picture we can see that we have the applications voting-app, result-app and worker where the support for all these applications requires Redis as a cache and Postgre as storage data for each vote that will be carried out by the application.

The following is a more complete explanation:

  1. Voting-App: website used to carry out web-based voting
  2. Result-App: website that displays voting results in real time.
  3. Worker: background process application that synchronizes voting with live voting results.
  4. Redis: temporary storage mechanism used to support voting-app.
  5. Postgre: as permanent data storage which will later be used to display the results of all ongoing voting.

After we know all the functions of each Pod, we need to analyze what needs to be done if the application architecture is like this.

This microservice stage can be deployed into Kubernetes so it needs analysis to produce something like this:

  1. Deploy PODs: we analyze each service or application into individual Pods, namely: a. voting-app b. result-app c. workers d. Redis e. Postgres This stage means that later we will create Pods with each need.
  2. We create Services (ClusterIP) so that each service can communicate with Redis and Postgres. Why do we use ClusterIP? because we need to access Redis and Postgres from the application only using the cluster, not directly to a particular node. a. Redis b. Postgres
  3. Create services (NodePort) used for communication from applications to users so that later every website can be accessed by users. a. voitng-app b. result-app

We have imagined the stages so we will try to implement them in the form of a YAML file so we can understand better.

Create a Deployment

As explained above, the first step we need to do is make each POD into a YAML deployment file.

Create voting-app Deployments

We try to create a file with the name voting-app-deployment.yaml and fill the file as below.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: voting-app-deployment
  labels:
    app: demo-voting-app
spec:
  replicas: 3
  selector:
    matchLabels:
      name: voting-app-pod
      app: demo-voting-app
  template:
    metadata:
      name: voting-app-pod
      labels:
        name: voting-app-pod
        app: demo-voting-app

    spec:
      containers:
      - name: voting-app
        image: dockersamples/examplevotingapp_vote
        ports:
        - containerPort: 80

In this file we will replicate our service into 3 so that later we will see the voting-app service 3 Pods.

then next we create it with the command below

➜ kubectl create -f code/demo/voting-app/voting-app-deployment.yaml 
pod/voting-app-deployment created

Create result-app Deployments

We continue by creating a file with the name result-app-deployment.yaml and fill the file with the code below.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: result-app-deployment
  labels:
    app: demo-voting-app
spec:
  replicas: 1
  selector:
    matchLabels:
      name: result-app-pod
      app: demo-voting-app
  template:
    metadata:
      name: result-app-pod
      labels:
        name: result-app-pod
        app: demo-voting-app

    spec:
      containers:
      - name: result-app
        image: dockersamples/examplevotingapp_result
        ports:
        - containerPort: 80

For the result-app service, we only make 1 replication because we don’t need to have a lot of requirements.

then continue create with this command

➜ kubectl create -f code/demo/result-app/result-app-deployment.yaml 
pod/result-app-deployment created

Create a worker-app Deployment

We continue by creating a file with the name worker-app-deployment.yaml and fill the file with the code below.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: worker-app-deployment
  labels:
    app: demo-voting-app
spec:
  replicas: 3
  selector:
    matchLabels:
      name: worker-app-pod
      app: demo-voting-app
  template:
    metadata:
      name: worker-app-pod
      labels:
        name: worker-app-pod
        app: demo-voting-app

    spec:
      containers:
      - name: worker-app
        image: dockersamples/examplevotingapp_worker

We make the replication equal to 3 if we look at the YAML file. Then continue creating with this command

➜ kubectl create -f code/demo/worker-app/worker-app-deployment.yaml 
pod/worker-app-deployment created

Create a Redis Deployment

This Redis deployment is used for temporary storage by creating the file below

apiVersion: apps/v1
kind: Deployment
metadata:
  name: redis-deployment
  labels:
    app: demo-voting-app
spec:
  replicas: 1
  selector:
    matchLabels:
      name: redis-pod
      app: demo-voting-app
  template:
    metadata:
      name: redis-pod
      labels:
        name: redis-pod
        app: demo-voting-app

    spec:
      containers:
      - name: redis
        image: redis
        ports:
        - containerPort: 6379

Redis usually has a standard port, namely 6379, although in fact it can be any number, but to suit the application standards, we set it according to its needs.

then continue create with this command

➜ kubectl create -f code/demo/redis/redis-deployment.yaml 
pod/redis-deployment created

Create a Postgres Deployment

These Postgres Pods are used for permanent storage of the final results of the voting app by creating the file below

apiVersion: apps/v1
kind: Deployment
metadata:
  name: postgres-deployment
  labels:
    app: demo-voting-app
spec:
  replicas: 1
  selector:
    matchLabels:
      name: postgres-pod
      app: demo-voting-app
  template:
    metadata:
      name: postgres-pod
      labels:
        name: postgres-pod
        app: demo-voting-app

    spec:
      containers:
      - name: postgres
        image: postgres:9.4
        ports:
        - containerPort: 5432
        env:
          - name: POSTGRES_HOST_AUTH_METHOD
            value: trust

We also set Postgres as a database with Port 5432 because Postgres defaults to using that port.

And we also add an environment such as a user and password that is used to connect to the Postgres database.

  • POSTGRES_HOST_AUTH_METHOD = trust

then continue create with this command

➜ kubectl create -f code/demo/postgres/postgres-deployment.yaml 
pod/postgres-deployment created

Create Services

There are two types of services that we will use in this application, namely ClusterIP and NodePort.

Cluster IP for Redis

We will create a ClusterIP service for Redis so that it can communicate with our voting application, namely with the code below.

apiVersion: v1
kind: Service
metadata:
  name: redis
  labels:
    name: redis-service
    app: demo-voting-app
spec:
  ports:
  - port: 6379
    targetPort: 6379
  selector:
    name: redis-pod
    app: demo-voting-app

ClusterIP for Postgres

Create a ClusterIP for Postgres so that our service can communicate with the database. Below is the service YAML code that we need to create.

apiVersion: v1
kind: Service
metadata:
  name: db
  labels:
    name: db-service
    app: demo-voting-app
spec:
  ports:
  - port: 5432
    targetPort: 5432
  selector:
    name: postgres-pod
    app: demo-voting-app

LoadBalancer for voting-app

The type in the voting-app is NodePort because we will establish the port for the user so we use NodePort. The following is the YAML file that we have to create.

apiVersion: v1
kind: Service
metadata:
  name: voting-service
  labels:
    name: voting-service
    app: demo-voting-app
spec:
  type: LoadBalancer
  ports:
  - port: 80
    targetPort: 80
  selector:
    name: voting-app-pod
    app: demo-voting-app

LoadBalancer for results-app

The type in the result-app is NodePort too because we will establish the port for the user so we use NodePort. The following is the YAML file that we have to create.

apiVersion: v1
kind: Service
metadata:
  name: result-service
  labels:
    name: result-service
    app: demo-voting-app
spec:
  type: LoadBalancer
  ports:
  - port: 80
    targetPort: 80
  selector:
    name: result-app-pod
    app: demo-voting-app

create all services with this command below.

➜ kubectl create -f code/demo/postgres/postgres-service.yaml 
service/db created
➜ kubectl create -f code/demo/redis/redis-service.yaml      
service/redis created
➜ kubectl create -f code/demo/voting-app/voting-app-service.yaml 
service/voting-service created
➜ kubectl create -f code/demo/result-app/result-app-service.yaml 
service/result-service created

if we want to see all services so, tried to typing this command.

➜ kubectl get all                                                  
NAME                                         READY   STATUS    RESTARTS   AGE
pod/postgres-deployment-7d47dd5bd8-hrsgq     1/1     Running   0          54s
pod/redis-deployment-58bdbddb55-6x4nk        1/1     Running   0          46s
pod/result-app-deployment-6ff54bbb5-9gz7q    1/1     Running   0          37s
pod/voting-app-deployment-5bd496ccd8-cmb5x   1/1     Running   0          28s
pod/voting-app-deployment-5bd496ccd8-nq4zl   1/1     Running   0          28s
pod/voting-app-deployment-5bd496ccd8-tqhwt   1/1     Running   0          28s
pod/worker-app-deployment-785b6c695d-28np4   1/1     Running   0          16s
pod/worker-app-deployment-785b6c695d-2gfnz   1/1     Running   0          16s
pod/worker-app-deployment-785b6c695d-gz7jx   1/1     Running   0          16s

NAME                     TYPE           CLUSTER-IP      EXTERNAL-IP   PORT(S)        AGE
service/db               ClusterIP      10.97.181.193   <none>        5432/TCP       51s
service/kubernetes       ClusterIP      10.96.0.1       <none>        443/TCP        25d
service/redis            ClusterIP      10.109.77.202   <none>        6379/TCP       44s
service/result-service   LoadBalancer   10.100.125.49   <pending>     80:31289/TCP   34s
service/voting-service   LoadBalancer   10.97.64.194    <pending>     80:31266/TCP   23s

NAME                                    READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/postgres-deployment     1/1     1            1           54s
deployment.apps/redis-deployment        1/1     1            1           46s
deployment.apps/result-app-deployment   1/1     1            1           37s
deployment.apps/voting-app-deployment   3/3     3            3           28s
deployment.apps/worker-app-deployment   3/3     3            3           16s

NAME                                               DESIRED   CURRENT   READY   AGE
replicaset.apps/postgres-deployment-7d47dd5bd8     1         1         1       54s
replicaset.apps/redis-deployment-58bdbddb55        1         1         1       46s
replicaset.apps/result-app-deployment-6ff54bbb5    1         1         1       37s
replicaset.apps/voting-app-deployment-5bd496ccd8   3         3         3       28s
replicaset.apps/worker-app-deployment-785b6c695d   3         3         3       16s

It can be seen that all services are running by looking at the Running status and so that we can try it in the browser we can use the command below for the voting-app service.

➜ minikube service voting-service --url
http://127.0.0.1:58820
❗  Because you are using a Docker driver on darmoveStaleState removing state" podUID="b50bbc4f-004b-4d1f-86cf-db77a85b0f7d" containerName="redi

If we access it using a browser it will look like the image below.

voting-app browser

And for the result-app service, we also need to look at the command below.

➜ minikube service result-service --url
http://127.0.0.1:58860
❗  Because you are using a Docker driver on darwin, the terminal needs to be open to run it.

If we look and access it using a browser for the result-app service it will look like the image below.

result-app browser

comments powered by Disqus