Create and expose Services in Kubernetes
Published: 2024-01-11 06:36:41

In Kubernetes, a service has following purposes/advantages.
1. Expose Application to outside world.
2. Service Discovery: Labels and Selectors.
3. LoadBalancer or NodePort Mode.
4. Install [Kubeshark](https://github.com/kubeshark/kubeshark/releases/tag/v52.0.0)

#### Pre-requisites: 

- Create deploy.yml file
- Create service.yml file
- Deploy deploy.yml
- Deploy service.yml 

## 1. Expose Application to outside world
##### - a) Create `deploy.yml` file as below.

```
apiVersion: apps/v1
kind: Deployment
metadata: 
  name: sample-python-deployment
  labels: 
    app: sample-python-app
spec: 
  replicas: 2
  selector: 
    matchLabels: 
      app: sample-python-app
  template: 
    metadata: 
      labels: 
        app: sample-python-app
    spec:
      containers:
      - name: python-app
        image: jasper475/d37-k8s-services-py-django-app:v2
        ports:
        - containerPort: 8000
```



##### - b) Create `service.yml` file as below.

```
apiVersion: v1
kind: Service
metadata:
  name: sample-python-service
spec:
  type: NodePort
  selector:
    app: sample-python-app
  ports:
    - port: 80
      targetPort: 8000
      nodePort: 30007
```
##### - c) Deploy `deploy.yml` file as below.
`kubectl apply -f deploy.yaml`

```
$ kubectl apply -f deploy.yaml
deployment.apps/sample-python-deployment created

```

##### - d) Deploy `service.yml` file as below.
`kubectl apply -f service.yaml`

```
$ kubectl apply -f deploy.yaml
service/sample-python-service configured

```
##### - e) NodePort service Type: service deployed as NodePort type
```
kubectl get svc
NAME                    TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)        AGE
kubernetes              ClusterIP   10.96.0.1        <none>        443/TCP        11d
sample-python-service   NodePort    10.103.136.137   <none>        80:30007/TCP   2s
```
##### - f) Notice `IP` Address of Pod: Notice `IP` below
```
$ kubectl get pods -o wide
NAME                                        READY   STATUS    RESTARTS   AGE     IP            NODE       NOMINATED NODE   READINESS GATES
sample-python-deployment-5787bd6b9f-656fn   1/1     Running   0          3h54m   10.244.0.35   minikube   <none>           <none>
sample-python-deployment-5787bd6b9f-t9ttj   1/1     Running   0          3h50m   10.244.0.36   minikube   <none>           <none>
```
##### - g) Access Application via `IP Addr:Port`: Note, Python application is exposed via `Port 8000`
```
$ minikube ssh
curl -L http://10.244.0.35:8000/demo ####Access via Pod IP Address  *** It works ***
```


## 2. Service Discovery: Labels and Selectors.

- Edit 'service.yml' file 

FROM: 

```
 spec:
  type: NodePort
  selector:
    app: sample-python-app***
  ports:
    - port: 80
```

TO

```
spec:
  type: NodePort
  selector:
    app: sample-python-a***
  ports:
    - port: 80
```


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bv88pdf8fpoglrms115g.png)

## 3. LoadBalancer or NodePort Mode.

#### - a) get svc: `kubectl get svc `
```
$ kubectl get svc                        
NAME                    TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)        AGE
kubernetes              ClusterIP   10.96.0.1        <none>        443/TCP        11d
sample-python-service   NodePort    10.103.136.137   <none>        80:30007/TCP   33m
```

#### - b) SVC Type: NodePort
```
kubectl get svc
NAME                    TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)        AGE
kubernetes              ClusterIP   10.96.0.1        <none>        443/TCP        11d
sample-python-service   NodePort    10.103.136.137   <none>        80:30007/TCP   2s
```
#### - c) Access SVC: via NodePort Mode
```
minikube ssh
$ pwd
/home/docker
$ curl -L http://10.103.136.137:8000/demo ####Access via Cluster IP of svc on port 8000 - ******* Doesn't work*********
curl: (28) Failed to connect to 10.103.136.137 port 8000 after 131079 ms: Connection timed out
$ curl -L http://10.103.136.137:80/demo ####Access via Cluster IP of svc on port 80 - ******* Hurray, it works !!! *********
$ curl -L http://10.103.136.137:8000/demo ####Access via Pod IP Address

                         _             _
            _         _ ( )           ( )
  ___ ___  (_)  ___  (_)| |/')  _   _ | |_      __
/' _ ` _ `\| |/' _ `\| || , <  ( ) ( )| '_`\  /'__`\
| ( ) ( ) || || ( ) || || |\`\ | (_) || |_) )(  ___/
(_) (_) (_)(_)(_) (_)(_)(_) (_)`\___/'(_,__/'`\____)

$ curl -L http://10.103.136.137:80
<!DOCTYPE html>
<html lang="en">
<head>
  <meta http-equiv="content-type" content="text/html; charset=utf-8">
  <title>Page not found at /</title>
  <meta name="robots" content="NONE,NOARCHIVE">
  <style type="text/css">
    html * { padding:0; margin:0; }
    body * { padding:10px 20px; }
    body * * { padding:0; }
    body { font:small sans-serif; background:#eee; color:#000; }
    body>div { border-bottom:1px solid #ddd; }
    h1 { font-weight:normal; margin-bottom:.4em; }
    h1 span { font-size:60%; color:#666; font-weight:normal; }
    table { border:none; border-collapse: collapse; width:100%; }
    td, th { vertical-align:top; padding:2px 3px; }
    th { width:12em; text-align:right; color:#666; padding-right:.5em; }
    #info { background:#f6f6f6; }
    #info ol { margin: 0.5em 4em; }
    #info ol li { font-family: monospace; }
    #summary { background: #ffc; }
    #explanation { background:#eee; border-bottom: 0px none; }
    pre.exception_value { font-family: sans-serif; color: #575757; font-size: 1.5em; margin: 10px 0 10px 0; }
  </style>
</head>
<body>
  <div id="summary">
    <h1>Page not found <span>(404)</span></h1>

    <table class="meta">
      <tr>
        <th>Request Method:</th>
        <td>GET</td>
      </tr>
      <tr>
        <th>Request URL:</th>
        <td>http://10.103.136.137/</td>
```

#### - d) Edit svc: `kubectl edit svc service-name `
```
$ kubectl edit svc sample-python-service 
-------------------------------------------------------------------
# Please edit the object below. Lines beginning with a '#' will be ignored,
# and an empty file will abort the edit. If an error occurs while saving this file will be
# reopened with the relevant failures.
#
apiVersion: v1
kind: Service
metadata:
  annotations:
    kubectl.kubernetes.io/last-applied-configuration: |
      {"apiVersion":"v1","kind":"Service","metadata":{"annotations":{},"name":"sample-python-service","namespace":"default"},"spec":{"ports":[{"nodePort":30007,"port":80,"targetPort":8000}],"selector":{"app":"sample-python-app"},"type":"NodePort"}}
  creationTimestamp: "2024-01-11T02:51:02Z"
  name: sample-python-service
  namespace: default
  resourceVersion: "16469"
  uid: bd9bd510-e633-4dc1-adc1-1cc4704378d3
spec:
  allocateLoadBalancerNodePorts: true
  clusterIP: 10.103.136.137
  clusterIPs:
  - 10.103.136.137
  externalTrafficPolicy: Cluster
  internalTrafficPolicy: Cluster
  ipFamilies:
  - IPv4
  ipFamilyPolicy: SingleStack
  ports:
  - nodePort: 30007
    port: 80
    protocol: TCP
    targetPort: 8000
  selector:
    app: sample-python-app
  sessionAffinity: None
  type: ***LoadBalancer***
status:
  loadBalancer: {}
-------------------------------------------------------------------
service/sample-python-service edited
```

> SVC Type: LoadBalancer - notice `EXTERNAL-IP` is `<pending>` state. Because, in Minikube this won't be creating an IP address whereas, in any cloud providers such as AWS EC2 or Azure VM or GCP Engine - `EXTERNAL-IP` will be assigned via `Cloud-Control Manager`

```
kubectl get svc
NAME                    TYPE           CLUSTER-IP       EXTERNAL-IP   PORT(S)        AGE
kubernetes              ClusterIP      10.96.0.1        <none>        443/TCP        11d
sample-python-service   LoadBalancer   10.103.136.137   <pending>     80:30007/TCP   34m
```

#### Get `Minikube ip'

```
$ minikube ip
192.168.59.105
```

Access via browser http://192.168.59.105:30007/demo
or curl -L http://192.168.59.105:30007/demo


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/w99s1zv4dpuschmkf5oh.png)

## 4. Install Kubeshark

#### - a) Install Kubeshark as below
`git clone: git clone https://github.com/kubeshark/kubeshark`

```
PS C:\Users\Jasper> git clone https://github.com/kubeshark/kubeshark
Cloning into 'kubeshark'...
remote: Enumerating objects: 20781, done.
remote: Counting objects: 100% (1668/1668), done.
remote: Compressing objects: 100% (262/262), done.
remote: Total 20781 (delta 1525), reused 1491 (delta 1406), pack-reused 19113
Receiving objects: 100% (20781/20781), 26.38 MiB | 19.53 MiB/s, done.
Resolving deltas: 100% (14618/14618), done.
PS C:\Users\Jasper>
```