Kubernetes Ingress routing by service label

11/17/2019

Is it possible to route Ingress requests based on service labels instead of a service name?

I would like to have 2 services with the same name but different label values. Can Ingress route traffic like this?

service-name.labelA.com -> service with label = A
service-name.labelB.com -> service with label = A

Is it possible to do so? Because in the Docs it uses routing by service name and port (no labels):

spec:
  rules:
  - http:
      paths:
      - path: /testpath
        backend:
          serviceName: test
          servicePort: 80
-- Anatolii Stepaniuk
kubernetes-ingress

1 Answer

11/18/2019

Kubernets won't let you creating two services with the same name

$ cat service_A.yaml apiVersion: v1
kind: Service
metadata: 
  name: portfwd-srv-a 
spec: 
  ports: 
    - 
      nodePort: 30010
      port: 88
      name: knp1
  selector: 
    app: nginx
  type: NodePort

cat service_B.yaml apiVersion: v1
kind: Service
metadata: 
  name: portfwd-srv-a 
spec: 
  ports: 
    - 
      nodePort: 30011
      port: 88
      name: knp1
  selector: 
    app: nginx
  type: NodePort

$ kubectl create -f service_A.yaml 
service/portfwd-srv-a created

$ kubectl create -f service_B.yaml 
Error from server (AlreadyExists): error when creating "service_B.yaml": services "portfwd-srv-a" already exists

$  kubectl get svc -o wide
NAME                 TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)                      AGE    SELECTOR
kubernetes           ClusterIP   10.0.0.1     <none>        443/TCP                      6d3h   <none>
portfwd-srv-a        NodePort    10.0.5.233   <none>        88:30010/TCP                 3m     app=nginx
web                  NodePort    10.0.4.73    <none>        8080:31881/TCP               3d     run=web

However, it is possible to target the same service (or any service of your choice with the Ingress). The example below is influenced by the Ingress documentation.

$ cat ingress_namebased.yaml 
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: name-virtual-host-ingress
spec:
  rules:
  - host: foo.bar.com
    http:
      paths:
      - backend:
          serviceName: web
          servicePort: 8080
  - host: bar.foo.com
    http:
      paths:
      - backend:
          serviceName: web
          servicePort: 8080

here I'm serving requests sent to foo.bar.com and bar.foo.com with the web service:

$ kubectl get ingress 
NAME                        HOSTS                     ADDRESS         PORTS   AGE
name-virtual-host-ingress   foo.bar.com,bar.foo.com   35.186.*.*      80      134m

$ kubectl get svc -o wide
NAME       TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)               AGE    SELECTOR
web        NodePort    10.0.4.73    <none>        8080:31881/TCP        3d     run=web
...

that points to a few pods/end_points:

$ kubectl get pods -o wide
NAME                     READY   STATUS    RESTARTS   AGE     IP          NODE                    NOMINATED NODE   READINESS GATES
web-ddb799d85-7x2v4      1/1     Running   0          3d      10.12.0.6   cluster-1-pool-1-6v3n   <none>           <none>
web-ddb799d85-p2cq8      1/1     Running   0          2d21h   10.12.1.8   cluster-1-pool-1-m7z8   <none>           <none>

$ kubectl get ep -o wide
NAME                 ENDPOINTS                       AGE
web                  10.12.0.6:8080,10.12.1.8:8080   3d

and here the example of how it works from "end user" prospective ( round robin because I have 2 end points ):

$ curl foo.bar.com
Hello, world!
Version: 1.0.0
Hostname: web-ddb799d85-7x2v4

$ curl foo.bar.com
Hello, world!
Version: 1.0.0
Hostname: web-ddb799d85-p2cq8

curl bar.foo.com
Hello, world!
Version: 1.0.0
Hostname: web-ddb799d85-p2cq8

$ curl bar.foo.com
Hello, world!
Version: 1.0.0
Hostname: web-ddb799d85-7x2v4
-- Nick
Source: StackOverflow