🇧🇷 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
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
Notice the structure:
- Each item in
rulesrepresents a different domain (host); - Within each rule,
pathsdefines which paths of that domain are routed and to whichservice(with the correspondingport) the traffic should go; -
pathType: "Prefix"means any URL starting with the givenpath(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
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
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)