Xavis
Xavis

Reputation: 99

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

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!

Upvotes: 0

Views: 7501

Answers (3)

Martin Colley
Martin Colley

Reputation: 1

Not sure if the op has solved this, but in case anyone else still has this requirement, this should be possible with two ingresses, using the app-root annotation.

apiVersion: networking.k8s.io/v1
kind: Ingress 
metadata:
  annotations:
    nginx.ingress.kubernetes.io/app-root: /site1
  name: site-one-ingress
spec:
  ingressClassName: nginx
  rules:
  - host: site-one.mydomain.com
    http:
      paths:
      - backend:
          serviceName: nginx-service
          servicePort: 80
---
apiVersion: networking.k8s.io/v1
kind: Ingress 
metadata:
  annotations:
    nginx.ingress.kubernetes.io/app-root: /site2
  name: site-two-ingress
spec:
  ingressClassName: nginx
  rules:
  - host: site-two.mydomain.com
    http:
      paths:
      - backend:
          serviceName: nginx-service
          servicePort: 80

Requesting http://site-one.mydomain.com will result in a redirect to http://site-one.mydomain.com/site-one, which is served by the nginx-service. The file site-one/index.html of the document root will be served.

Similarly, a request to http://site-two.mydomain.com will result in a redirect to http://site-two.mydomain.com/site-two served by the same nginx-service, this time from the site-two/index.html file.

Upvotes: 0

suren
suren

Reputation: 8786

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.

Upvotes: 1

dippynark
dippynark

Reputation: 3003

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 /.

Upvotes: 1

Related Questions