6

I have two deployments

deployment 1

apiVersion: v1
kind: Service
metadata:
  name: first-service
spec:
  selector:
    key: app1
  ports:
    - port: 81
      targetPort: 5050

---

apiVersion: apps/v1
kind: Deployment
metadata:
  name: first-deployment
spec:
  replicas: 1
  selector:
    matchLabels:
      run: app1
  template:
    metadata:
      labels:
        run: app1
    spec:
      containers:
      - name: ocr
        image: ocr_app
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 5050

deployment 2

apiVersion: v1
kind: Service
metadata:
  name: second-service
spec:
  selector:
    key: app2
  ports:
    - port: 82
      targetPort: 5000

---

apiVersion: apps/v1
kind: Deployment
metadata:
  name: second-deployment
spec:
  replicas: 1
  selector:
    matchLabels:
      run: app2
  template:
    metadata:
      labels:
        run: app2
    spec:
      containers:
      - name: ner
        image: ner_app
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 5000

After enabling ingress on minikube I applied ingess

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

In my hosts file I have

192.168.177.71  demo.local

Where 192.168.177.71 is my current minikube ip

I then ran this command

kubectl port-forward nginx-ingress-controller-6fc5bcc8c9-p6mvj 3000:80 --namespace kube-system

And in the console is outputs

Forwarding from 127.0.0.1:3000 -> 80
Forwarding from [::1]:3000 -> 80

But when I make a request to demo.local:3000/ocr using postman there is no response

Could not get any response There was an error connecting to demo.local:3000.

EDIT: using minikube service first-service gives this output

PS D:\docker> minikube service first-service
|-----------|---------------|-------------|--------------|
| NAMESPACE |     NAME      | TARGET PORT |     URL      |
|-----------|---------------|-------------|--------------|
| default   | first-service |             | No node port |
|-----------|---------------|-------------|--------------|
* service default/first-service has no node port
erotavlas
  • 4,274
  • 4
  • 45
  • 104
  • 1
    Just to clear some thoughts. You are using Kubernetes 1.16+. Did you enable ingress in minikube `minikube addons enable ingress`? You have issue only with `/ocr` or also with `/ner`? – PjoterS Jan 31 '20 at 14:24
  • @PjoterS yes enabled ingress, same issue on both paths – erotavlas Jan 31 '20 at 15:18

2 Answers2

5

@erotavlas as Mafor provided answer which help you resolve your issue please accept his answer.

I am posting extended answer which might help someone else.

Root cause of this Issue was with selector/labels.

In first-service, spec.selector was set to key: app1, however in deployment spec.selector.matchLabels was set to run: app1.

To proper work you need to have the same selectors. So you would need to change in service, spec.selector to run: app1 or change deployment spec.selector.matchLabels to key: app1. Same situation with second-service and second-deployment. More details can be found here.

I've tried to use Ingress on Minikube based on official docs and your YAMLs.

As addition, to use Ingress on Minikube, Ingress addon must be enabled.

$ minikube addons list | grep ingress
- ingress: disabled

If it's disabled, you have to enable it.

$ minikube addons enable ingress
✅  ingress was successfully enabled

targetPort: is the port the container accepts traffic on / port where application runs inside the pod
port: is the abstracted Service port, which can be any port other pods use to access the Service.

OP used own images where application was running on ports 5050 and 5000, for this example I will use GCP hello world on port 8080. Labels/matchLabels were changed to have the sam value in deployment and service.

First service

apiVersion: v1
kind: Service
metadata:
  name: first-service
spec:
  selector:
    key: app1
  ports:
    - port: 81
      targetPort: 8080

---

apiVersion: apps/v1
kind: Deployment
metadata:
  name: first-deployment
spec:
  replicas: 1
  selector:
    matchLabels:
      key: app1
  template:
    metadata:
      labels:
        key: app1
    spec:
      containers:
      - name: hello1
        image: gcr.io/google-samples/hello-app:1.0
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 8080

service/first-service created
deployment.apps/first-deployment created

Second Service

apiVersion: v1
kind: Service
metadata:
  name: second-service
spec:
  selector:
    key: app2
  ports:
    - port: 82
      targetPort: 8080

---

apiVersion: apps/v1
kind: Deployment
metadata:
  name: second-deployment
spec:
  replicas: 1
  selector:
    matchLabels:
      key: app2
  template:
    metadata:
      labels:
        key: app2
    spec:
      containers:
      - name: hello2
        image: gcr.io/google-samples/hello-app:2.0
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 8080

service/second-service created
deployment.apps/second-deployment created

It crated services as ClusterIP type. If need you can use NodePort but it's not neccessary.

Apply Ingress

Ingress provided in question is enough to tests.

As mentioned in official docs. You should add minikube ip to host file.

Note: If you are running Minikube locally, use minikube ip to get the external IP. The IP address displayed within the ingress list will be the internal IP.

In Ubuntu OS it's /etc/hosts (need to use sudo to edit). In Windows OS please check this article

For my cluster (Using GCE):

$ minikube ip
10.132.15.208

Added to hosts file value:

10.132.15.208 demo.local

Below responses.

$ curl demo.local/ocr
Hello, world!
Version: 1.0.0
Hostname: first-deployment-85b75bf4f9-qlzrp
$ curl demo.local/ner
Hello, world!
Version: 2.0.0
Hostname: second-deployment-5b5bbb7f4-9sbqr

However, version with rewrite provided by Mafor is more versatile.

In addition, You could also consider use LoadBalancer on Minikube. More information can be found in Minikube docs.

PjoterS
  • 12,841
  • 1
  • 22
  • 54
3

First thing, you don't need kubectl port-forward. Ingress is exposed on your minikube ip, port 80.

Second, probably you need some rewrite rules in the ingress configuration. By default, ingress forwards requests "as they are", i.e demo.local:3000/ocr is forwarded to first-service:81/ocr. Probably it is not what you want, unless first-service is deployed to /ocr context.

I guess, you need something like this:

apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: ingress
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /$2
spec:
  rules:
  - host: demo.local
    http:
      paths:
      - path: /ocr(/|$)(.*)
        backend:
          serviceName: first-service
          servicePort: 81
      - path: /ner(/|$)(.*)
        backend:
          serviceName: second-service
          servicePort: 82

See https://kubernetes.github.io/ingress-nginx/user-guide/nginx-configuration/annotations/#rewrite

Mafor
  • 9,668
  • 2
  • 21
  • 36
  • I don't understand what you mean by "unless first-service is deployed to /ocr context" . Just to be clear, I'm trying to expose two separate routes one that sends request to one service and another to the other service. For example first deployment is a container with a flask rest api and I specified the route I want to call as "/ocr" – erotavlas Jan 31 '20 at 03:00
  • What I mean is: does the flask api itself contains the `/ocr` route, or should it be rather called with `/`? – Mafor Jan 31 '20 at 08:43
  • Flask app contains this `@app.route("/ocr", methods=['POST'])` – erotavlas Jan 31 '20 at 15:19
  • Ok, than ignore my answer, I'll delete it. But the part about `kubectl port-forward` is still valid. And check if you are not trying to connect with https. – Mafor Jan 31 '20 at 15:52
  • I just tried to add another deployment for hello world using these instructions https://kubernetes.io/docs/tasks/access-application-cluster/ingress-minikube/ and I added their path to my ingress yaml and I was able to access the service. When they deploy the service they also expose NodePort `kubectl expose deployment web --target-port=8080 --type=NodePort` - could this be what's wrong with mine, I didn't specify NodePort in the service? – erotavlas Jan 31 '20 at 15:57
  • No, NodePort is not necessary. Try looking into ingress-controller and your apps logs, maybe you will find there something. Are you able to connect to the services directly (`minikube service`)? – Mafor Jan 31 '20 at 16:05
  • see my edit in original post for output from minikube service – erotavlas Jan 31 '20 at 16:17
  • Right, for `minikube service` you need the NodePort – Mafor Jan 31 '20 at 16:41
  • I think the selector in my service is wrong, its supposed to be `run: app1` is that right? when I fixed it, I get a different error instead of 503 I get 404, the requested url doesn't exist on the server. – erotavlas Jan 31 '20 at 16:44
  • 1
    OMG its working now, I removed the rewrite ` annotations: nginx.ingress.kubernetes.io/rewrite-target: /$1` and fixed the selector for both services to match the labels in the deployments. thanks for sticking around to help :) might as well include what i found in your answer – erotavlas Jan 31 '20 at 16:49