<p>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 <code>LoadBalancer</code> or <code>NodePort</code>. </p>

<p>So far, so good. I followed a <a href="https://docs.traefik.io/v1.7/user-guide/kubernetes/" rel="nofollow noreferrer">guide</a> 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.</p>

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

<pre><code>---
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
</code></pre>

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

<pre><code>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
</code></pre>

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

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

Daniel
<p>That's how an ingress controller is supposed to work.</p>

<p>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 (<code>traefik-web-ui</code> service in your case).</p>

<p>This image, taken from <a href="https://medium.com/google-cloud/kubernetes-nodeport-vs-loadbalancer-vs-ingress-when-should-i-use-what-922f010849e0" rel="nofollow noreferrer">this</a> 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.
<a href="https://i.stack.imgur.com/oT2Sw.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/oT2Sw.png" alt="enter image description here"></a></p>
