Can a host be redirected to a service path in Kubernetes?

3/15/2018

I'm trying to try to match a host address to a service path, as an example, let's think i have an nginx pod servying to sites: site1 and site2. Let's think about a service called my-nginx-service which services my two sites as paths:

- my-nginx-service (178.123.55.37:80) - /site1 - /site2

There exists a way to map it to something like:

- host: site-one.mydomain.com http: paths: - backend: serviceName: nginx-service servicePort: 80 servicePath: /site2 - host: site-two.mydomain.com http: paths: - backend: serviceName: nginx-service servicePort: 80 servicePath: /site2

? I have not found anything about it in docs. Or maybe I've not understood well them.

Thank you very much for your time!

-- Xavis
devops
docker
google-compute-engine
kubernetes

2 Answers

3/20/2018

What you are trying to do (if I understood right) is impossible, because services are unaware of host names. You might be able to reach what you want by modifying nginx configuration within the pod, but that would not be a K8s approach.

What you need to do is to add an ingress resource. Ingresses are aware of host names. They do load balancing between services. So, /site1 one would go to one service, and /site2 to the other one.

This is what the ingress should look like:

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: ingress
spec:
  rules:
  - host: site-one.mydomain.com
    http:
      paths:
      - backend:
          serviceName: nginx-service1
          servicePort: 80
  - host: site-two.mydomain.com
    http:
      paths:
      - backend:
          serviceName: nginx-service2
          servicePort: 80

As you can see site1 and site2 would be running in different deployments, with different services targeting them. Ingress, which is L7 Load Balancer would be able to check the host name and forward the request to the right service, which in the end would hit the right pod.

You can also add paths to each host, so site-one.mydomain.com/path1, site-one.mydomain.com/path2 and site-two.mydomain.com/path1 (for example), would be forwarded to different services.

The Ingress yaml file would look like this:

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: ingress
spec:
  rules:
  - host: site-one.mydomain.com
    http:
      paths:
      - path: /path1
        backend:
          serviceName: nginx-service1
          servicePort: 80
      - path: /path2
        backend:
          serviceName: nginx-service2
          servicePort: 8080
      - path: /
        backend:
          serviceName: nginx-service3
          servicePort: 80
  - host: site-two.mydomain.com
    http:
      paths:
      - path: /path1
        backend:
          serviceName: nginx-service1
          servicePort: 80

I know this is not what you exactly are asking, but this is the right way to achieve what you want.

-- suren
Source: StackOverflow

3/15/2018

You can see from the output below of kubectl explain that the servicePath field above does not exist (at least on version 1.9.3).

kubectl explain ingress.spec.rules.http.paths.backend:

...
FIELDS:
   serviceName  <string> -required-
     Specifies the name of the referenced service.

   servicePort  <string> -required-
     Specifies the port of the referenced service.
...

You need to specify your path in the following field: ingress.spec.rules.http.paths.path so that when that path is hit the request is routed using the Service specified at ingress.spec.rules.http.paths.backend.serviceName. If you're using nginx or trafficserver ingress the annotation nginx.ingress.kubernetes.io/rewrite-target: / can be used to redirect the request to /.

-- dippynark
Source: StackOverflow