Kubernetes - Exposing Two Services Using Ingress

Prerequisites

  • kubectl
  • minikube
  • Docker

Description

In the previous posts Containerizing an ML Model - Part 1 and Containerizing an ML Model - Part 2 I showed how to create the docker container for a single machine learning model.

In this post we will deploy that service along with an additional service in Kubernetes and expose them outside the cluster so users can use them to process their data. To do that we must use Ingress - an API object that defines rules which allow external access to services in a cluster.

Before Beginning

Make sure you have installed minikube and configured the kubectl command-line tool to communicate with your cluster.

Also to speed up development you should re-use the docker daemon within minikube. This way when you build your docker containers they will be directly accessible to the kubernetes deployments and you don’t have to go through the extra steps of pushing, then pulling them from an external container registry. To get the command for your shell run minikube docker-env.

For example on Windows we use the following command

For more information plese refer to the section Use local images by re-using the Docker daemon

Finally, make note of the minikube IP address by running this command. You will need this IP later when testing the docker containers.

Service 1 - NER

This is the NER service from previous posts. You can find the code to build the docker container here.

NER Service

  • Build using docker build . -t ner
  • Run using docker run -p 5001:5000 ner:latest
  • Test by sending the sample text from file test-text.txt in the body of the POST request. You should get the following response. Remember to send it to the minikube IP - your URL should look like 192.168.100.148:5001/entities

In Postman the request is like this (your IP and port may be different).

The response should look like this:

[
    {
        "end": 24,
        "label": "PERSON",
        "start": 13,
        "text": "John Smith'"
    }
]

Service 2 - OCR

As our second service we will build an application that performs OCR on JPEG images of text and returns the text.

Download the code from here.

OCR Service

  • Build using docker build . -t ocr
  • Run using docker run -p 5002:5000 ocr:latest
  • Test by sending the sample image file test-image.jpg as form-data in the body of the POST request. Specify the key as file and the value as the image file. Remember to send it to the minikube IP - your URL should look like 192.168.100.148:5002/ocr

In Postman the request should look like this (your IP and port may be different).

The response should look like this:

{
    "file": "test-image.jpg",
    "pages": {
        "1": "From today's featured list\n‘American actress and singer Jennifer Love Hewitt has released four studio albums, a compilation album, seven music videos, and\nthirteen singles, as well as five promotional singles. She released her debut studio album, Love Songs, under the name \"Love Hewitt\"\nin March 1992; it included three singles: \"Dancing Queen\", \"What's It Gonna Take\", and \"Please Save Us the World”. Hewitt received\nattention for her performance in the family drama Party of Five. During this success, she signed with Atlantic and released two studio\nalbums: Let's Go Bang in September 1995 and a self-titled album in September 1996. Hewitt recorded the single \"How Do | Deal\" for\nthe soundtrack of the 1998 slasher film / Still Know What You Did Last Summer, in which she had a starring role. The song reached\nnumber 59 on the Billboard Hot 100, as well as number 8 on the Australian songs chart and number 5 on the New Zealand songs\nchart. It received a gold certification from the Australian Recording Industry Association and is the best-selling song of her career.\n(Full list...)\n"
    }
}

Enable Ingress

Before you can use ingress in minikube, you must first enable it. Do so by running the following command. For more details refer to the documentation Enable the Ingress controller

Create deployments

There will be three deployment files, one for each service and one for the ingress.

NER Service Deployment

apiVersion: v1 
kind: Service 
metadata: 
  name: ner-service 
spec: 
  selector: 
    run: ner 
  ports: 
    - port: 80 
      targetPort: 5000 
 
--- 
 
apiVersion: apps/v1 
kind: Deployment 
metadata: 
  name: ner-deployment 
spec: 
  replicas: 1 
  selector: 
    matchLabels: 
      run: ner 
  template: 
    metadata: 
      labels: 
        run: ner 
    spec: 
      containers: 
        - name: ner 
          image: ner:latest 
          imagePullPolicy: IfNotPresent 
          ports: 
          - containerPort: 5000

OCR Service Deployment

apiVersion: v1 
kind: Service 
metadata: 
  name: ocr-service 
spec: 
  selector: 
    run: ocr 
  ports: 
    - port: 80 
      targetPort: 5000 
 
--- 
 
apiVersion: apps/v1 
kind: Deployment 
metadata: 
  name: ocr-deployment 
spec: 
  replicas: 1 
  selector: 
    matchLabels: 
      run: ocr 
  template: 
    metadata: 
      labels: 
        run: ocr 
    spec: 
      containers: 
        - name: ocr 
          image: ocr:latest
          imagePullPolicy: IfNotPresent 
          ports: 
          - containerPort: 5000

Ingress

apiVersion: networking.k8s.io/v1beta1 
kind: Ingress 
metadata: 
  name: ingress 
spec: 
  rules: 
  - host: demo.local 
    http: 
      paths: 
      - path: /ocr 
        backend: 
          serviceName: ocr-service 
          servicePort: 80 
      - path: /entities 
        backend: 
          serviceName: ner-service 
          servicePort: 80

NOTE: you need to edit your hosts file to create a mapping between a domain name of your choosing and the IP address of minikube. In this example I set the domain name to demo.local and assigned it to the minikube ip address.

The hosts file is located here on Windows

C:\Windows\System32\drivers\etc

On Linux you can find the hosts file under

/etc/hosts

Apply deployments

Run kubectl apply to update the kubernetes cluster to match the state defined in the above configuration .yaml files.

Check that pods are running with kubectl get pods --all-namespaces. Your output should look similar to the following.

Test

You should now be able to access the NER service from this URL - demo.local\entities and the OCR Service from this URL - demo.local\ocr

Sample Code

References