DEV Community

Celso Nery
Celso Nery

Posted on

Kubernetes: Setting Up an Ingress Controller (NGINX)

🇧🇷 Leia a versão em português aqui.

So far, to expose an application outside the cluster, we've used NodePort or LoadBalancer type Services. These approaches work well for a single isolated service, but become limiting once the cluster hosts several applications, each needing its own domain (or subdomain), possibly with HTTPS — managing a different NodePort for each application doesn't scale well.

That's the problem the Ingress solves: a Kubernetes object that centralizes HTTP/HTTPS routing for multiple domains to the correct Services, through a single entry point. For Ingress to work, an Ingress Controller needs to be installed in the cluster — in this article, we use the most popular one, ingress-nginx.

Installing the Ingress Controller via Helm

The official ingress-nginx project provides a ready-to-use Helm chart:

🔗 https://kubernetes.github.io/ingress-nginx/

To install (or update, if it already exists) the controller in a dedicated namespace:

helm upgrade --install ingress-nginx ingress-nginx \
  --repo https://kubernetes.github.io/ingress-nginx \
  --namespace ingress-nginx --create-namespace
Enter fullscreen mode Exit fullscreen mode

Notice the use of helm upgrade --install instead of helm install: this combination installs the chart if it doesn't exist yet, or updates the existing installation — useful both for the first installation and future version upgrades, without needing to memorize two different commands.

The --create-namespace flag automatically creates the ingress-nginx namespace, if it doesn't already exist.

Creating an Ingress

With the controller installed, the next step is creating Ingress-type manifests, which define the routing rules — which domain (host) routes to which Service in the cluster.

An example with multiple domains, each pointing to a different Service:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: ingress-hosts
  annotations:
    kubernetes.io/ingress.class: "nginx"
spec:
  rules:
  - host: api.bagarote.com.br
    http:
      paths:
      - pathType: "Prefix"
        path: "/"
        backend:
          service:
            name: api
            port:
              number: 8082
  - host: adm.bagarote.com.br
    http:
      paths:
      - pathType: "Prefix"
        path: "/"
        backend:
          service:
            name: adm
            port:
              number: 80
  - host: site.bagarote.com.br
    http:
      paths:
      - pathType: "Prefix"
        path: "/"
        backend:
          service:
            name: site
            port:
              number: 80
Enter fullscreen mode Exit fullscreen mode

Notice the structure:

  • Each item in rules represents a different domain (host);
  • Within each rule, paths defines which paths of that domain are routed and to which service (with the corresponding port) the traffic should go;
  • pathType: "Prefix" means any URL starting with the given path (in this case, /, meaning everything) will be routed to that backend.

In this example, three different domains (api, adm, and site, all under bagarote.com.br) are routed through the same Ingress Controller, each to the corresponding Service already existing in the cluster.

Applying the manifest:

kubectl apply -f ingress.yaml
Enter fullscreen mode Exit fullscreen mode

Pointing the DNS

For this Ingress to actually work, the configured domains (api.bagarote.com.br, adm.bagarote.com.br, site.bagarote.com.br, in the example) need their DNS records pointing to the Ingress Controller's external IP — generally the IP of one of the cluster's nodes (or a load balancer, in environments where one is provisioned).

To find out the IP and port exposed by the controller:

kubectl get service -n ingress-nginx
Enter fullscreen mode Exit fullscreen mode

Final thoughts

With the Ingress Controller installed and domains correctly routed, the cluster now exposes multiple applications through a single entry point, using domain names instead of scattered ports — a configuration much closer to what's expected in a production environment. The natural next step from here is adding HTTPS to these domains, automating TLS certificate issuance — the topic of the next article in this addons series, about cert-manager.

Top comments (0)