DataOps part 3: deploy Titanic to kubernetes
Tags: kubernetes, helm, data, machinelearning
Published: 2019-11-01 03:38:09



![Alt Text](https://thepracticaldev.s3.amazonaws.com/i/kc7zjtf72f9wooqrh8do.jpg)
***Image Source: Blue Star Line***

This is the last part of dataops series, if you haven’t gone through the first and second ones, here is the link: [part1](https://dev.to/calvintran/kubernetes-on-local-with-vagrant-and-kubeadm-5bed), [part2](https://dev.to/calvintran/dataops-part-2-sail-the-titanic-to-api-2p2o)

## Prerequisite

We have to make sure that our kubernetes cluster has an ingress installed. If you have configured, here is the way how to do it

* For vagrant kubernetes

```bash
$ kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/master/deploy/static/mandatory.yaml

$ kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/master/deploy/static/provider/baremetal/service-nodeport.yaml
```

* For microk8s

```bash
$ kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/master/deploy/static/mandatory.yaml

$ microk8s.enable ingress
```

## Deployment

Before starting with deployment process, let’s go through the process flow.

![Kubernetes process flow](https://cdn-images-1.medium.com/max/2000/1*75OTEtD4D6YeDLU0y8xGfw.png)

That are the steps for deploy machine learning model on kubernete the easy way.

1. Create a deployment (*Deployment runs multiple replicas of your application and automatically replaces any instances that fail or become unresponsive — google k8s*).

1. Expose deployment to services (*Services for expose your pods into network, there are different type of services like NodePort or LoadBalancer*).

1. Create ingress (*Ingress exposes HTTP and HTTPS routes from outside the cluster to services within the cluster, on another way, ingress help outside traffic access to our API).*

###Create Deployment

Deployment is an object in kubernetes that let you manage a set of identical pods. Without the deployment, you have to create, update, delete the pod manually

```yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: titanic-app
  labels:
    app: titanic-app
    tier: backend
    version: v1
spec:
  selector:
    matchLabels:
      app: titanic-app
  replicas: 2
  template:
    metadata:
      labels:
        app: titanic-app
    spec:
      containers:
      - name: titanic-app
        image: canhtran/titanic-app-demo:latest
        ports:
        - containerPort: 5000
```

I create two replicas (2 pods) for our api, the default port is flask port 5000.

```bash
# Apply deployment
$ kubectl apply -f deployment-titanic.yaml
deployment.apps/titanic-app created
```

We can check the pods status.

```bash
$ kubectl get pod
NAME                           READY   STATUS              RESTARTS   AGE
titanic-app-6f4fdf8668-7nctk   1/1     Running             0          64s
titanic-app-6f4fdf8668-zhghw   0/1     ContainerCreating   0          64s
```

###Expose services

Unlike deployment is used to keep a set of pods running by creating pods from a template, service is used to allow network access to a set of pods.

```bash
$ kubectl expose deployment titanic-app --type=LoadBalancer --port=5000
service/titanic-app exposed
```

Also get our service status

```bash
$ kubectl get svc
NAME          TYPE           CLUSTER-IP    EXTERNAL-IP   PORT(S)          AGE
titanic-app   LoadBalancer   10.102.5.24   <pending>     5000:32755/TCP   14
```

###Create ingress

Finally, an ingress so that our service can be accessible from outside.

```yaml
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: titanic-ingress
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
    nginx.ingress.kubernetes.io/ssl-redirect: "false"
spec:
  rules:
  - http:
      paths:
        - path: /
          backend:
            serviceName: titanic-app
            servicePort: 5000
```

```bash
$ kubectl apply -f ingress-titanic.yaml
ingress.extensions/titanic-ingress created
```

**Let's wrap it up and test our API**

```bash
$ curl -i -X POST -H "Content-Type:application/json" http://10.98.11.201/predict -d '{"Pclass":3,"Sex":1,"Age":2,"Fare":7,"Embarked":0,"Title":1,"FamilySize":2,"IsAlone":0,"Age_Class":6, "FarePerPerson":3}'

HTTP/1.1 200 OK
Server: openresty/1.15.8.1
Date: Mon, 29 Jul 2019 12:00:10 GMT
Content-Type: application/json
Content-Length: 13
Connection: keep-alive

{"result":1}
```

The API have been up and running as expected :)