Deep dive into Kubernetes (part - II) :
Tags: kubernetes, microservices, devops
Published: 2020-11-27 19:52:52

# __Setup k8s in our local environment :__

We are going to install __minikube__ for this purpose because that runs a single node Kubernetes cluster on your computer .

__Install :__
```$ curl -LO https://storage.googleapis.com/minikube/releases/latest/minikube_latest_amd64.deb```

```$ sudo dpkg -i minikube_latest_amd64.deb```

* When we install __minikube__ it also install kubectl . No need to install separately .

* Initiate __minikube cluster__  
```$ minikube start ``` 

You can now use kubectl commands :
```$ kubectl get pods ```
etc .....

# __Kubernetes services :__

### __What is Kubernetes service :__
* __Services__ provides a abstraction layer over the Kubernetes cluster so that our application is not exposed directly .
* Using services we can make sure that our application is secure and it can be accessible through defined service .
* We can use a static ip address using services .

![Sample k8s service](https://dev-to-uploads.s3.amazonaws.com/i/6b1efm1cvuozp1ixl38a.png)

### __Types of service such as :__
   
* __ClusterIP Service :__
This is default service type . Exposes the service on a cluster internal IP. And the incoming request comes from the browser through the ingress which make sure that the service is only reachable within the cluster. 

* __NodePort Service :__ 
Exposes the cluster IP of each node at a static port . We can able to contact to the nodeport service from outside .  

* __LoadBalancer Service :__
Load balancer can route your incoming request to the clusters .

* __Headless Service :__
Specifically designed for stateful  application . Suppose there is a MongoDB database running and obviously running on master slave architecture where write happens on master and slave have to sync with master . 

* But how your k8s service knows which cluster to route the request ?
The answer is through the __selectors__ it knows about the forwarding request . 


### __Hand's on :__

* A sample Nginx deployment file :
```yaml
apiVersion: apps/v1 # for versions before 1.9.0 use apps/v1beta2
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  selector:
    matchLabels:
      app: nginx
  replicas: 2 # tells deployment to run 2 pods matching the template
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.14.2
        ports:
        - containerPort: 80
```
Then use the kubectl apply command with your respective file name .
```$ kubectl apply -f nginx-depl.yaml```
```$ kubectl get pods ```

### __Hands on :__

so the __request__ comes from the __browser__ which then goes to the __external service__ of the __mongo express__ application which then forward the request to the __internal service__ of __MongoDB__ the it forwarded it to the __MongoDB pod__ which then __authenticate__ it using the __credentials__ .  

* Make sure you have the __Minikube cluster__ running .
```$minikube start```

* create a deployment file of mongo-express . 
```$ touch mongo-depl.yml ``` 
```yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: mongodb-dep
  labels:
    app: mongodb
spec:
  replicas: 1
  selector:
    matchLabels:
      app: mongodb
  template:
    metadata:
      labels:
        app: mongodb
    spec:
      containers:
      - name: mongodb
        image: mongo
```

* Now check for the Mongo image on __DockerHub(public repository for storing container images . similar to GitHub)__  for the configuratio ,port , environment variables .

![Mongo Docker Hub](https://dev-to-uploads.s3.amazonaws.com/i/e8ov91p5bfwah0hc9mok.png)

* We need to add these environment variables and port to our deployment file after image on deployment file .

```yaml
ports :
        - containerport : 27017
        env:
        - name: MONGO_INITDB_ROOT_USERNAME
          value :
        - name : MONGO_INITDB_ROOT_PASSWORD
          value :
```

* create a secret where our root user name and password will lie .

```$ touch mongo-secret.yml ```

``` yaml
apiVersion: v1
kind: Secret
metadata:
  name: mongodb-secret
type: Opaque
data:
    mongo-root-username: dXNlcm5hbWU=
    mongo-root-password: cGFzcw==
```

The username and password must be base64 encoded :
```$ echo -n 'admin' | base64 ```
```$ echo -n 'password' | base64 ```

And now we gonna reference it in our deployment file 

```$ kubectl apply -f mongo-secret.yml ```

* Now we have the root user name and password then we can referred from secret . 

```yaml
env:
        - name : MONGO_INITDB_ROOT_USERNAME
          valueFrom:
            secretKeyRef:
              name: mongo-secret
              key : mongo-root-username 
        - name : MONGO_INITDB_ROOT_PASSWORD
          valueFrom:
            secretKeyRef:
              name: mongo-secret
              key : mongo-root-password
```

```$ kubectl apply -f mongo-depl.yaml ```
```$ kubectl gel pod ```

* Now we have to create a internal service so that other pods or containers can talk to MongoDB .

```yaml
---
apiVersion : v1
kind: Service
metadata:
  name: mongodb-service
spec:
  selector:
    app: mongodb
  ports:
  - protocol: TCP
    port: 27017
    targetPort: 27017 
```
__selector__ -- connect to the pod through label 
__port__ -- service port
__target port__ -- container port

```$ kubectl apply -f mongo-depl.yaml```
```$ kubectl get service ```
```$ kubectl describe service (service name)```
```$ kubectl get pod -o wide ``` 

* Now we have to create a Mongo-express deployment and service and a config map .

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/2bm12liwrpatqd7ar8zl.png)

* We need to configure following :
1. MongoDB URL
2. admin name
3. password

```yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: mongo-express
  labels:
    app: mongo-express
spec:
  replicas: 1
  selector:
    matchLabels:
      app: mongo-express
  template:
    metadata:
      labels:
        app: mongo-express
    spec:
      containers:
      - name: mongo-express
        image: mongo-express
        ports:
        - containerPort: 8081
        env:
        - name : ME_CONFIG_MONGODB_ADMINUSERNAME
          valueFrom:
            secretKeyRef:
              name: mongodb-secret
              key : mongo-root-username 
        - name: ME_CONFIG_MONGODB_ADMINPASSWORD
          valueFrom:
            secretKeyRef:
              name: mongodb-secret
              key : mongo-root-password
        - name: ME_CONFIG_MONGODB_SERVER 
          valueFrom:
            configMapKeyRef:
              name: mongodb-configmap
              key : database_url
```

### __configmap :__

* external configuration
* centralized
* other components can use it

```yaml
apiVersion: v1
kind : ConfigMap
metadata:
  name: mongodb-configmap
data:
  database_url: mongodb-service
```
key-value pair and the database URL

__The order of creation matters__

```$ kubectl apply -f mongo-config.yaml```
```$ kubectl apply -f mongo-express.yaml``` 
```$ kubectl get pod```
```$ kubectl logs mongo-express-(some number) ```

```
you can see 
server is running
```
### __FINALLY :__
* create a mongo-express service and it is a loadbalacer type(external load balancer)

* nodePort  port where the external ip address is open and it has actually a range 30000 - 32767

* mongo-express service (The external service also got some externa IP)

```yaml
apiVersion : v1  
kind : Service
metadata:
  name: mongo-express-service
spec:
  selector :
    app: mongo-express
  type : LoadBalancer 
  ports:
  - protocol: TCP
    port: 8081
    targetport: 8081
    nodePort : 30000
```

```$ kubectl get service ```
```$ minikube service mongo-express-service```

### __Now you can see the application dashboard :__

### __Thanks for your patience reading__ 🔥🔥🔥