#047 Kubernetes - voting app (example)
Tags: kubernetes, devops, tutorial
Published: 2020-08-08 23:04:43

# Introduction
![intro](https://media1.tenor.com/images/f15057a41413c960db1f328ca5a732e3/tenor.gif?itemid=6203225)

this is part 47 from the journey it's a long journey(360 day) so go please check previous parts , and if you need to walk in the journey with me please make sure to follow because I may post more than once in 1 Day but surely I will post daily at least one 😍.

And I will cover lot of tools as we move on.
***
# prepare files

The original files can be found here
{% github dockersamples/example-voting-app no-readme %}
the files for this lab is same of the voting app from previous part (in Docker).
the files we need are located inside the k8s-specifications folder.
But since we don't know what is namespace so I edit the files and remove namespaces from them.

The edited files can be found in my github repo here
{% github OmarElKhatibCS/DevOpsJourney no-readme %} 
if you already have it just pull , if not clone it.
the source code usually hold the same chapter number we are in 047 so app_047 is what we are looking for.
***
# Understand the app
![what](https://media1.tenor.com/images/5c36b5497629f905d0c011d16f01c0ff/tenor.gif?itemid=10312546)
This part will be a warm up to all what we take so far by using the example of voting app.

first let's take a look at the diagram ,
![diagram](https://raw.githubusercontent.com/dockersamples/example-voting-app/master/architecture.png)
the vote and result are front-end so we need to access them from outside the cluster , so we need a NodPort service for each of them in order to access it from outside the cluster.
for the redis and postgresDB we need an clusterIP service because it's still inside the cluster.
if we look at the source code of the worker we can see that he connect to each database using their services and update the votes from the redis to postgres. so technically no one is accessing the worker so we don't need a service for him.
let' take a look at the configuration files first.
my objective from reviewing the files is to remember all what we talk about.
```yaml
# db-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: db
  name: db
spec:
  replicas: 1
  selector:
    matchLabels:
      app: db
  template:
    metadata:
      labels:
        app: db
    spec:
      containers:
      - image: postgres:9.4
        name: postgres
        env:
        - name: POSTGRES_USER
          value: postgres
        - name: POSTGRES_PASSWORD
          value: postgres
        ports:
        - containerPort: 5432
          name: postgres
        volumeMounts:
        - mountPath: /var/lib/postgresql/data
          name: db-data
      volumes:
      - name: db-data
        emptyDir: {} 
```
this is an deployment kind is Deployment so it can be scaled up or down , metadata are descriptive data about the deployment it self , namespace is the topic of the next part :) , spec  will take the specifications about the deployment we need 1 replica of this pod selector we will use it to be able to access it , template will take the configuration of the pod without apiVersion and kind .
this is for deployment same for the other deployments.
now let's take a look at services.
```yaml
# db-service.yaml
apiVersion: v1
kind: Service
metadata:
  labels:
    app: db
  name: db
spec:
  type: ClusterIP
  ports:
  - name: "db-service"
    port: 5432
    targetPort: 5432
  selector:
    app: db
```
it will take type of ClusterIP(only allow access from inside cluster) and kind Service , and port of it and port of the target which in this case is the port of the postgresDB.
```yaml
# result-service.yml
apiVersion: v1
kind: Service
metadata:
  labels:
    app: result
  name: result
spec:
  type: NodePort
  ports:
  - name: "result-service"
    port: 5001
    targetPort: 80
    nodePort: 31001
  selector:
    app: result
```
this is a NodePort service so it will take as an extra the nodePort which is the port of the entire Node.
***
# Lab
![mad](https://media1.tenor.com/images/4800838e793768298c7d6132734abca4/tenor.gif?itemid=11957205)

now let's create all of those yml files.
since they are all located in single folder we can pass the folder name and he will create them all.
![create](https://dev-to-uploads.s3.amazonaws.com/i/gf5zu1nerace5wtr2ejv.png)
```bash
kubectl create -f app_047
```

![get_pods](https://dev-to-uploads.s3.amazonaws.com/i/dxyblg0dy4jmmyxn5d7g.png)
```bash
kubectl get pods
```
my last container is still onCreating for 52 minute because I have the best connection in the world.
if we go to the app now we can interact with it but it not gonna update on results page because the worker is not ready yet. let's take a look

![ip](https://dev-to-uploads.s3.amazonaws.com/i/yxtgr6copzgqqczff8v6.png)
```bash
minikube ip
```
my ip is 192.168.99.100 and if we take a look at the configuration files
![ports](https://dev-to-uploads.s3.amazonaws.com/i/6kygal0q6zgaoz81orec.png)
NodePorts are 31000 and 31001 (I can get them from kubernetes also) , so we can access the app from [192.168.99.100:31000](192.168.99.100:31000) and [192.168.99.100:31001](192.168.99.100:31001)

![browser](https://dev-to-uploads.s3.amazonaws.com/i/gqw6yiy3bxmgzxvu0hyb.png)
when I vote in the left the results are not updated yet because the worker is not ready yet.

Now when the worker finish building it's still not updating let's investigate it.
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/elbhg322jtm90wc17omf.png)
```bash
kubectl logs db-6789fcc76c-hvrs6 | tail
```
(I delete the deployments and run them in investigation so names are changed)
db-6789fcc76c-hvrs6 is the name of db pod
tail is Linux command will get last few lines of the input.

we can see it's say password error and it's because the image is outdated , we can fix it by building new one and push it to docker this will take time and a lot of edits. So I am going to hard fix it.
Let's start
![bash](https://dev-to-uploads.s3.amazonaws.com/i/uenrxksesltixdxkc967.png)
```bash
kubectl exec db-6789fcc76c-hvrs6 -- bash
```
we are now in the root bash , let's install vim and edit the pg_hba.conf
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/zb3lhj3s8czaftz2r940.png)
```bash
apt update && apt install vim 
```
after we have the vim installed let's edit our file
![edit_vim](https://dev-to-uploads.s3.amazonaws.com/i/39bqlhkya4w4d364itdp.png)
```bash
vim /var/lib/postgresql/data/pg_hba.conf
```
![edit](https://dev-to-uploads.s3.amazonaws.com/i/n7vcptc7j7pi1qjezpg3.png)
go to the last line and change md5 to trust press i to enter edit mode in vim.
after editing it press ESC then :wq to save and quit.
![12](https://dev-to-uploads.s3.amazonaws.com/i/plda2q5hsof5a87ocztm.png)
now let's access the postgress shell using
```bash
su - postgres
```
![13](https://dev-to-uploads.s3.amazonaws.com/i/3m3lklq2bnxk0evjp78n.png)
let's reload our Database configurations using
```bash
psql
SELECT pg_reload_conf();
\q
```
and \q used to quit
then
![exit](https://dev-to-uploads.s3.amazonaws.com/i/cnbqul8pu79ub97wyk6l.png)
```bash
exit
exit
```
exit to exit first  bash , and exit to exit second bash XD XD
![reloaded](https://dev-to-uploads.s3.amazonaws.com/i/fzu6ef1cj8ies1i4jl7g.png)
```bash
kubectl logs db-6789fcc76c-hvrs6
```
if we scroll down we can see now it's updated and working let's go to the browser.
![updated](https://dev-to-uploads.s3.amazonaws.com/i/776hvv5bdo7irc1wvt5a.png)
now it's updated congrats , we have full app deployed :D
We see also how we can troubleshoot our app , amazing isn't it ?

![congrats](https://media1.tenor.com/images/ca01b285840c2d033015e0c85fb4091c/tenor.gif?itemid=17929880)