Interplay between Ingress and Service

12/18/2019

Ingress can be used to route traffic from an endpoint (or name) to a service which is then forwarded to a pod with matching labels. However, an ingress does not expose arbitrary ports or protocols, which is why services need to be either of type LoadBalancer or NodePort.

So far, so good. I followed a guide to install Traefik as an ingress controller and everything is up and running, but I don't understand why it even works. This question is not related to Traefik; I saw this pattern many times.

The first manifest consists of the ingress deployment and a service called traefik-ingress-service of type LoadBalancer (works with NodePort as well).

---
kind: Deployment
apiVersion: extensions/v1beta1
metadata:
  name: traefik-ingress-controller
  labels:
    k8s-app: traefik-ingress-lb-dep
spec:
  replicas: 1
  selector:
    matchLabels:
      k8s-app: traefik-ingress-lb
  template:
    metadata:
      labels:
        k8s-app: traefik-ingress-lb
        name: traefik-ingress-lb
    spec:
      terminationGracePeriodSeconds: 60
      containers:
      - image: traefik:v1.7
        name: traefik-ingress-lb
        ports:
        - name: http
          containerPort: 80
        - name: admin
          containerPort: 8080
        args:
        - --api
        - --kubernetes
        - --logLevel=INFO
---
kind: Service
apiVersion: v1
metadata:
  name: traefik-ingress-service
spec:
  selector:
    k8s-app: traefik-ingress-lb
  ports:
    - protocol: TCP
      port: 80
      name: web
    - protocol: TCP
      port: 8080
      name: admin
  # type: NodePort (works as well, but don't forget to add port to uri)
  type: LoadBalancer

In order to expose Traefik's UI there is another manifest including a second service (type: default) traefik-web-ui and an Ingress which connects traffic from / to traefik-web-ui.

apiVersion: v1
kind: Service
metadata:
  name: traefik-web-ui
spec:
  #type: NodePort
  selector:
    k8s-app: traefik-ingress-lb
  ports:
  - name: web
    port: 80
    targetPort: 8080
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: traefik-web-ui
  annotations:
    kubernetes.io/ingress.class: traefik 
spec:
  rules:
  - host: dashboard.localhost #optional, otherwise cluster's ip
    http:
  #- http:
      paths:
      - path: /
        backend:
          serviceName: traefik-web-ui
          servicePort: web

I don't understand why this is working, because service traefik-web-ui should not be reachable from external. The other service traefik-ingress-service is, but they are not connected. So, how does this work?

Moreover, I'm curious why I would not just create one service traefik-web-ui of type NodePort or LoadBalancer?

-- Daniel
kubernetes
kubernetes-ingress
traefik
traefik-ingress

1 Answer

12/18/2019

That's how an ingress controller is supposed to work.

You have one load balancer managed by the ingress controller. Each time you create an ingress resource, the traefik configuration (running in your traefik pod) is updated accordingly to route the traffic to your services internally (traefik-web-ui service in your case).

This image, taken from this very good article, is quite illustrative. The ingress controller (the service + deployment in your first manifest) is the big Ingress box, routing the traffic to the internal services. enter image description here

-- Seba Arriagada
Source: StackOverflow