Ingress Controllers in Kubernetes
The front door and traffic director of your cluster: what an Ingress and an Ingress controller really are, how a request travels through them, how to secure and monitor them, and how to choose between the many options, explained from zero.
Think of a large shopping mall with one main entrance. Hundreds of shops sit inside: a bakery, a bookstore, a pharmacy, a cinema. Visitors do not walk around the outside of the building looking for a separate door for each shop. They come in through the main entrance, where a guard and a signboard point them to the right shop. The mall pays for one entrance, one security desk and one set of doors, instead of hundreds.
A Kubernetes cluster can hold hundreds of applications, each with its own address inside the cluster. Visitors on the internet cannot reach those addresses directly. You could give every application its own public door, but each public door costs money, needs its own security setup and its own certificate. That quickly becomes messy and expensive.
An Ingress controller is the mall’s main entrance and guide. It receives all web traffic from outside, reads the address and path the visitor asked for, and sends the request to the right application inside. In this guide you will learn what an Ingress is, what a controller is, how they work together, how traffic and encryption flow through them, how to run them safely in production, and how they are changing as the newer Gateway API takes over. Every new word is explained the first time it appears.
1What Is an Ingress Controller?
Two names that beginners mix up all the time: Ingress and Ingress controller. They are different things.
An Ingress is a Kubernetes object, a written set of routing rules. It says things like “requests for shop.example.com should go to the shop application, and requests for shop.example.com/blog should go to the blog application”. On its own, an Ingress does nothing at all. It is only a note.
An Ingress controller is a program running inside the cluster that reads those notes and does the actual work of receiving traffic and forwarding it. It is usually a reverse proxy, which is a server that stands in front of other servers, accepts requests on their behalf and passes each one to the correct place.
Kubernetes does not include an Ingress controller by default. You must choose one and install it. The Ingress object is the menu; the controller is the waiter who reads the menu and carries out the orders.
The Ingress is a signboard listing “Bakery: second floor, Cinema: fourth floor”. The Ingress controller is the receptionist at the entrance who reads the signboard and walks each visitor to the right floor. A signboard without a receptionist helps nobody, and a receptionist without a signboard has nothing to follow.
2The Problem: Getting Traffic Into a Cluster
To see why Ingress exists, look at what you would do without it.
Every Pod in a cluster has its own internal address that changes when the Pod is replaced. To give a stable address, Kubernetes offers a Service, a fixed internal front door for a group of Pods. By default, a Service is reachable only from inside the cluster. To let the outside world in, you have two simple options.
NodePort Service
Opens the same high-numbered port on every machine in the cluster. Simple, but the ports are awkward, machines are exposed directly, and there is no smart routing.
LoadBalancer Service
Asks your cloud provider for a real public load balancer for one Service. It works well, but every Service gets its own load balancer, its own public address and its own monthly bill.
Where these options fall short
- Cost. Fifty applications would mean fifty cloud load balancers.
- No host or path routing. A basic Service load balancer works at the connection level and cannot tell “shop.example.com” from “blog.example.com”.
- Repeated encryption setup. Every public door would need its own certificate for secure connections.
- Scattered controls. Rate limits, redirects, authentication and logging would have to be repeated everywhere.
Ingress solves these by putting one smart entrance in front of many Services. One public address, one set of certificates, and a single place to apply web-level rules.
3Foundations You Need First
A few basics about the web and about Kubernetes make everything that follows much clearer.
HTTP, HTTPS and the host name
HTTP is the language web browsers and servers use to ask for pages and reply. HTTPS is the same language wrapped in encryption so nobody in between can read or change it. Every request carries a host name, such as shop.example.com, and a path, such as /cart. Together these tell a server what the visitor wants.
DNS
DNS is the internet’s phone book. It turns a name like shop.example.com into a numeric address. For Ingress, you point your names at the public address of the Ingress controller, and then all of them arrive at the same entrance.
Reverse proxy
A reverse proxy is a server that receives requests from visitors and forwards them to servers behind it, returning the answers. Visitors never talk to the back servers directly. Well-known examples include NGINX, HAProxy, Envoy and Traefik.
Layer 4 versus Layer 7
Network traffic can be handled at different levels. Layer 4 deals with raw connections, like a postman who only looks at the street address on the envelope. Layer 7 deals with the actual web request, like a postman who opens the envelope and reads “please deliver to the bakery on the second floor”. Ingress works at Layer 7, so it can make decisions based on host names and paths.
Service, Endpoints and Pods
A Service selects Pods by label and keeps a list of their current addresses, called endpoints. An Ingress points at a Service, and the controller uses the Service’s endpoints to find live Pods.
| Layer | What it sees | Example tool | Can route by host or path? |
|---|---|---|---|
| Layer 4 | IP address and port | Cloud network load balancer | No |
| Layer 7 | Host name, path, headers, cookies | Ingress controller, application load balancer | Yes |
DNS is the phone book that tells callers the mall’s address. The reverse proxy is the front desk. Layer 4 is a guard checking that you arrived at the right building. Layer 7 is the receptionist who asks which shop you want and points the way.
4Core Concepts and Vocabulary
The words you will meet again and again.
Ingress
A Kubernetes object holding routing rules for incoming web traffic. It belongs to a namespace and points to Services in that namespace.
Ingress controller
The running program that watches Ingress objects and configures a proxy to follow them.
IngressClass
An object that names a type of controller. An Ingress says which class it wants, so the right controller picks it up when several controllers coexist.
Rule
A line in the Ingress: for this host and this path, send traffic to that Service and port.
Backend
The destination of a rule: a Service and its port. Some controllers can also send to other resource types.
Default backend
Where requests go when no rule matches. Often a simple “not found” page.
TLS termination
Decrypting HTTPS at the entrance, so that traffic inside the cluster can be plain or re-encrypted as you choose.
Annotation
A free-form note attached to an object. Controllers use annotations for extra features that the Ingress object itself does not define, such as timeouts or rewrites.
Gateway API
A newer, richer set of Kubernetes objects designed as the successor to Ingress, with clearer roles and more built-in features.
cert-manager
A popular add-on that requests, renews and stores security certificates automatically, often from Let’s Encrypt.
Path types
Each path rule has a type that decides how the text is compared.
- Exact: the path must match exactly. “/cart” matches “/cart” but not “/cart/items”.
- Prefix: the path matches if it starts with the given text, split on slashes. “/shop” matches “/shop” and “/shop/items”.
- ImplementationSpecific: the controller decides how to interpret it. Behavior can differ between controllers.
5Architecture and Components
Here is the full picture of how traffic gets from a visitor to your Pod.
flowchart TB
V["Visitor's browser"] --> DNS["DNS: name to public address"]
DNS --> LB["Cloud load balancer or node address"]
LB --> IC
subgraph IC["Ingress controller Pods"]
P1["Reverse proxy Pod 1"]
P2["Reverse proxy Pod 2"]
end
P1 --> S1["Service: shop"]
P1 --> S2["Service: blog"]
P2 --> S1
P2 --> S2
S1 --> A1["Shop Pods"]
S2 --> B1["Blog Pods"]
The parts
The public entry point
Usually a cloud load balancer created by a Service of type LoadBalancer in front of the controller. In your own data center, it might be a fixed address on a node or a tool that hands out addresses.
The controller Pods
One or more Pods running the reverse proxy. Running several copies gives both capacity and safety.
The controller’s watcher
A small program that talks to the Kubernetes API server, watching Ingress objects, Services, endpoints and secrets, and translating them into proxy settings.
The Ingress objects
Written by application teams, one per application or one per host, describing their own routes.
Services and Pods
The real destinations of traffic, chosen by the rules.
Certificates
Stored as Kubernetes secrets and used by the proxy to encrypt connections with visitors.
Most controllers run as a Deployment with a few replicas, or as a DaemonSet with one Pod per machine. Both are common. The important point is that the controller is a normal application running inside your cluster, using cluster resources and needing the same care as any production service.
6Anatomy of an Ingress
Let us take an Ingress apart, using field names only, and see what each part means.
An Ingress lives in the networking API group at version v1, which has been stable since Kubernetes version 1.19. Its important fields are these.
| Field | Meaning | Notes |
|---|---|---|
| ingressClassName | Which controller should handle this Ingress | Replaces the older class annotation. Without it, a default class may apply. |
| rules | A list of host and path routing rules | Each rule has an optional host and one or more paths. |
| host | The name the visitor typed | May begin with a wildcard for a set of names. If omitted, the rule applies to all hosts. |
| paths | The URL parts to match | Each has a path, a path type and a backend. |
| backend | Service name and port | Must be in the same namespace as the Ingress. |
| tls | Hosts and the secret holding their certificate | Enables HTTPS for the listed hosts. |
| defaultBackend | Fallback when nothing matches | Optional; controllers also have their own default. |
| annotations | Extra settings specific to a controller | Not portable between controllers. |
How matching works
When a request arrives, the controller first chooses the rule whose host matches the request’s host name. Then, among that rule’s paths, it picks the most specific match, typically the longest matching path. If nothing matches, the request goes to the default backend, which usually responds with a “not found” message.
Matching is like the mall directory. First you find the building wing (the host name), then you find the shop inside it (the path). If you ask for a shop that does not exist, the receptionist politely says “we have no such shop”, which is the default backend.
A standard Ingress can only point at Services in its own namespace. If two teams share one host name across namespaces, they must coordinate carefully, since separate Ingress objects with overlapping paths can conflict. Many organizations give each team its own host name to avoid this.
7Common Routing Patterns
Almost every real Ingress uses one of three shapes, or a mix of them.
Single Service
All traffic for one host goes to one Service. The simplest case, used for small sites and single-purpose apps.
Fan-out by path
One host, many paths. “/shop” goes to the shop, “/blog” goes to the blog, “/api” goes to the API. One name, many applications.
Name-based virtual hosting
Different host names go to different Services, all through the same public address. “shop.example.com” and “blog.example.com” share the entrance but reach different apps.
Trade-offs between the patterns
Path-based routing keeps everything under one name, which is simple for visitors and needs only one certificate. But applications must be told they live under a sub-path, and links inside pages may break unless the app is built for it.
Host-based routing keeps each application at the root of its own name, so no path tricks are needed. It needs more DNS names, and a wildcard certificate or several certificates.
Most teams prefer host-based routing for separate applications, and path-based routing for pieces of one product, such as a front end and its API.
Production example: a shop with an API
A retailer serves its storefront at the main site name and its API under a path on the same name. The storefront and the API are separate Deployments and Services. One Ingress with two path rules sends browser page requests to the storefront and data requests to the API, and one certificate covers both. The mobile app calls the same API path.
8Internal Working: How a Controller Learns the Rules
The controller is always listening. Here is what it does when you create or change an Ingress.
sequenceDiagram
participant U as You
participant A as API server
participant C as Controller watcher
participant P as Reverse proxy
U->>A: Create or update an Ingress
A-->>C: Watch event: Ingress changed
C->>A: Read Services, endpoints and secrets
A-->>C: Current data
C->>C: Build full proxy configuration
C->>P: Apply new configuration
P-->>C: Ready with new rules
Note over C,P: Traffic keeps flowing during the switch
The reconcile loop
Kubernetes controllers follow a simple habit called reconciliation: they compare “what is wanted” with “what exists”, and act to make them match. An Ingress controller repeats this loop for every change.
- It watches for changes to Ingress objects, Services, endpoints and the secrets that hold certificates.
- It filters the Ingress objects to those whose class belongs to this controller.
- It builds a picture of all hosts, paths, backends and certificates.
- It renders that picture into the proxy’s native configuration.
- It applies the configuration, either by reloading the proxy or by updating it live.
Reload versus live update
Different controllers apply changes differently. Some, built on NGINX, write a new configuration file and ask NGINX to reload, which starts new worker processes and lets old ones finish their current requests. Frequent changes in a large cluster can make reloads costly, so many controllers update only the list of backend Pod addresses live and reload only when routes change. Envoy-based controllers push changes to the proxy over a live control channel, which avoids reloads altogether.
Following Pods as they change
Pods come and go all the time. Many controllers do not send traffic to the Service’s virtual address. Instead, they read the list of Pod addresses (the endpoints) and send requests straight to Pods, which allows features like sticky sessions and smarter load balancing. When a Pod starts or stops, the endpoint list changes and the controller notices almost at once.
The controller is like a receptionist who keeps the mall directory up to date. Whenever a shop opens, moves or closes, the receptionist hears about it, rewrites the directory board and keeps guiding visitors, without ever closing the entrance.
9Data Flow: Life of a Request
Follow one visitor from the browser to your Pod and back.
Name lookup
The browser asks DNS for shop.example.com and gets the public address of your load balancer.
Connection and encryption
The browser connects and, for HTTPS, starts a secure handshake. It tells the server which name it wants, and the controller presents the matching certificate.
Load balancer forwards
The cloud load balancer passes the connection to one of the controller Pods, often the one on the least busy machine.
Decrypt and read
The controller decrypts the request, reads the host, path and headers, and applies global rules such as size limits and rate limits.
Match a rule
It finds the matching host and the longest matching path, and picks the backend Service.
Choose a Pod
From that Service’s live endpoints, the controller picks a Pod using its balancing method, such as round-robin or least connections.
Forward and return
The request goes to the Pod, the Pod answers, and the controller relays the answer to the visitor, possibly adding headers or compressing it.
Headers the backend needs to know
Because the controller sits between the visitor and the application, the application would otherwise only see the controller’s address. Controllers therefore add headers such as the original visitor address and the original protocol, commonly named forwarded-for headers. Your application must be configured to trust these headers only from the controller, or attackers could fake them.
If the cloud load balancer rewrites the visitor’s address before the controller sees it, your logs may show only internal addresses. Settings such as preserving the client address or using the proxy protocol solve this. Plan for it early if you need real visitor addresses for security or analytics.
10HTTPS and TLS Termination
Secure connections are the most common reason people adopt an Ingress controller.
flowchart LR
B["Browser"] -->|HTTPS encrypted| IC["Ingress controller: holds certificate"]
IC -->|Option A: plain HTTP inside cluster| POD1["Pod"]
IC -->|Option B: re-encrypted HTTPS| POD2["Pod with own certificate"]
CM["cert-manager"] -->|requests and renews| CA["Certificate authority"]
CM -->|stores certificate| SEC["Kubernetes secret"]
SEC --> IC
What is TLS?
TLS is the encryption technology behind HTTPS. A server proves who it is by showing a certificate, which is a digital identity card signed by a trusted organization called a certificate authority. The visitor’s browser checks the signature. If it is valid and the name matches, the browser shows a padlock and encrypts everything after that.
Termination at the Ingress
In TLS termination, the controller holds the certificate and its private key, ends the encrypted connection, and forwards the request inside the cluster. It removes the need for every application to manage certificates. The certificate and key are kept in a Kubernetes secret that the Ingress refers to.
Choices inside the cluster
- Plain inside: simplest and fastest. Acceptable only if you trust the internal network.
- Re-encrypt: the controller opens a new encrypted connection to the Pod. Safer, with a small cost in speed and effort.
- Passthrough: some controllers can forward the encrypted stream untouched to the Pod, which then holds the certificate. The controller cannot read or route by path in this mode, only by host name.
Automatic certificates
Certificates expire. Renewing them by hand is a famous cause of outages. The cert-manager add-on can request free certificates from Let’s Encrypt or from a private authority, prove that you own the name, store the result in a secret, and renew it before it expires. The Ingress simply names the secret, and the controller picks up new certificates automatically.
Production example: wildcard certificate
A company hosting many customer sites under one parent domain uses a wildcard certificate covering all sub-names, issued and renewed by cert-manager. New sites become available over HTTPS the moment their Ingress is created, with no manual certificate work.
Redirect plain HTTP to HTTPS at the Ingress, and consider adding a header that tells browsers to always use HTTPS for your site. Only turn on the strict header after you are sure every subdomain supports HTTPS.
11The Controller Landscape: Which One Should You Use?
There is no single official controller. Kubernetes lists many, each with its own strengths.
| Controller | Built on | Known for | Consider when |
|---|---|---|---|
| Community ingress-nginx | NGINX | Very widely used, huge set of annotations, large community knowledge | Check its current maintenance status before choosing it for new projects |
| NGINX Ingress Controller from F5 | NGINX or NGINX Plus | Commercial support option, custom resources for richer routing | You want vendor support with NGINX |
| Traefik | Traefik proxy | Dynamic configuration, friendly dashboard, automatic certificates | You want easy setup and a modern feel |
| HAProxy Ingress | HAProxy | High performance, fine tuning | You already run HAProxy and value speed |
| Contour | Envoy | Live updates, clear delegation between teams | You use Envoy and want multi-team safety |
| Emissary-ingress | Envoy | API gateway features and rich policy | You need API-gateway behavior |
| Istio ingress gateway | Envoy | Part of a service mesh | You already run Istio |
| Cloud-native options | Provider load balancers | Managed by the cloud: AWS Load Balancer Controller, Google Cloud’s load balancing for GKE, Azure Application Gateway | You want the cloud to run the data path and integrate with cloud security tools |
Two families
In-cluster proxies such as NGINX, Traefik, HAProxy and Envoy run as Pods, and you own their scaling, upgrades and tuning. They work the same in every cloud and in your own data center. Cloud-managed controllers instead configure a load balancer that lives outside your cluster and is run by the provider. This removes work and can integrate with cloud firewalls and identity, but it ties you to that provider and its limits.
The Kubernetes project announced that the community-maintained ingress-nginx controller would move toward retirement, with maintenance winding down in 2026. Project status can change quickly, so before choosing any controller for a new system, look at its official page for current maintenance and security-update commitments. I have not verified this live, so treat it as a prompt to check.
Choosing a controller is like choosing a receptionist service. You can hire and train your own staff, which gives full control but costs effort, or you can rent a managed front desk from the building, which is easier but less customizable. What matters is that someone competent will still be at the desk next year.
12Installing and Exposing a Controller
A controller is not useful until traffic can reach it. How you expose it depends on where the cluster runs.
LoadBalancer Service
The usual choice in a public cloud. The controller’s own Service asks the provider for a load balancer, which gets a public address. Point your DNS names at it.
Address-giving add-ons
In your own data center, tools such as MetalLB can hand out public-facing addresses to LoadBalancer Services, giving you the same experience as the cloud.
NodePort
The controller listens on a high port on every node, and an external load balancer or firewall forwards to it. Works anywhere but is more manual.
Host network
The controller uses the machine’s own network so it can listen directly on the standard web ports. Only one controller Pod fits per machine, and the isolation is weaker.
Installation basics
Most controllers are installed with a package manager for Kubernetes called Helm, or with a set of ready-made description files. The installation creates the controller’s Deployment or DaemonSet, its Service, the permissions it needs to read cluster objects, and an IngressClass. After that, you create Ingress objects that name that class.
Running several controllers
A cluster can host more than one controller, for example one for public traffic and one for internal tools. The IngressClass tells them apart. Each Ingress chooses one class, and only that controller handles it. If you install two controllers without classes, both may try to handle the same Ingress and fight, so always set classes explicitly.
Mark exactly one IngressClass as the default in a cluster where developers may forget the class name. Otherwise, an Ingress with no class may be ignored by every controller, and the symptom is simply that nothing happens.
13Beyond Simple Routing: Advanced Features
The Ingress object itself is small. Most of the useful extras come from controller-specific settings.
Rewrites and redirects
Change the path before passing it on, so an app built for the root can live under a sub-path. Or send visitors from an old address to a new one.
Timeouts and size limits
Decide how long to wait for a slow Pod and how large an upload may be. Too small a limit breaks file uploads; too large invites abuse.
Rate limiting
Cap how many requests one visitor can make per second, protecting your apps from floods and greedy scrapers.
Sticky sessions
Send the same visitor to the same Pod using a cookie. Helps apps that keep visitor data in memory, though stateless design is better.
Canary releases
Send a small share of traffic, say 5 percent, to a new version to test it with real users before a full rollout.
Authentication in front
Require login or a token at the entrance, using an external identity service, so unprotected apps are safe to expose.
Compression and caching
Shrink responses and store repeated answers to save bandwidth and speed up pages.
Custom error pages
Show a friendly maintenance or error page instead of a raw technical message.
Web application firewall
Inspect requests for known attack patterns such as injection attempts and block them at the door.
Client certificate checks
Require visitors, often other machines, to present their own certificate, giving strong two-way identity checks.
The portability problem
The Ingress object has no standard way to express most of these features. Each controller invented its own annotations or custom objects. An annotation that works on one controller means nothing on another. Moving controllers therefore means rewriting all these settings, which is the main source of lock-in with Ingress.
Some controllers allow annotations that insert raw proxy configuration. That gives great flexibility but also lets anyone who can edit an Ingress affect the shared entrance, or even attack it. Restrict or disable these raw-configuration annotations unless you truly need them.
Production example: safe releases with canaries
A streaming company releases a new version of its web front end to 5 percent of visitors first, using a canary rule at the Ingress. Engineers watch error rates and page speed for an hour. If all is well, they raise the share to 25, 50 and finally 100 percent. If not, they drop it back to zero, and nobody outside the test share ever saw the problem.
14Ingress, Services and the Gateway API
Kubernetes has several ways to expose applications. Here is how they relate, and where the future is heading.
flowchart TD
Q1{"Is the traffic web traffic, HTTP or HTTPS?"}
Q1 -->|No, raw TCP or UDP| L4["LoadBalancer Service or Gateway API TCP and UDP routes"]
Q1 -->|Yes| Q2{"Many apps behind one address?"}
Q2 -->|No, only one app| L4B["LoadBalancer Service may be enough"]
Q2 -->|Yes| Q3{"New project and cluster supports Gateway API?"}
Q3 -->|Yes| GW["Consider Gateway API"]
Q3 -->|No or existing setup| ING["Ingress with an Ingress controller"]
| Approach | Good for | Limits |
|---|---|---|
| ClusterIP Service | Internal traffic only | Not reachable from outside |
| NodePort Service | Quick tests, custom edge setups | Awkward ports, exposes nodes |
| LoadBalancer Service | One app, any protocol | One load balancer per Service |
| Ingress | Many web apps behind one address | Web traffic only, limited standard features, controller-specific extras |
| Gateway API | Rich, portable, multi-team traffic management, several protocols | Newer; check controller support and maturity for your needs |
What is the Gateway API?
The Gateway API is a newer family of Kubernetes objects built to overcome the limits of Ingress. It splits responsibilities among three roles. An infrastructure provider defines the kinds of gateways available. A cluster operator creates the actual gateways and decides who may attach to them. Application developers create routes that attach to a gateway. It supports features that Ingress needed annotations for, such as header-based matching and traffic splitting, in a portable way, and it can handle more protocols than HTTP.
The Kubernetes project treats Ingress as stable but frozen, meaning it is not receiving new features, and points new feature work to the Gateway API. The Gateway API reached its first stable release in 2023. Existing Ingress setups continue to work, and migration can be gradual, but new projects should evaluate the Gateway API seriously.
Ingress is a mall directory with one shared board that every shop owner scribbles on. The Gateway API is a modern building with separate roles: the landlord owns the doors, the building manager decides which shops may use which door, and each shop owner manages only their own sign.
15Scaling and High Availability of the Controller
The controller is the single entrance. If it fails, everything behind it becomes unreachable. Treat it as your most critical service.
Run at least two or three replicas
One controller Pod is a single point of failure. Several copies share the load and survive individual failures.
Spread them out
Use placement rules so that replicas land on different machines and different zones. Losing one machine or one building should not remove the whole entrance.
Set resource requests and limits
The controller uses processor time for encryption and memory for connections. Size it from measured traffic, and leave room for spikes.
Autoscale on load
A horizontal autoscaler can add controller Pods when processor use or request rate rises. Keep a floor so a quiet period never drops below your safe minimum.
Protect against voluntary disruption
A Pod disruption budget makes sure that maintenance never removes too many controller Pods at once.
Shut down gracefully
When a controller Pod is stopped, it should stop taking new connections but finish current ones. Give it a suitable grace period and a short delay so the load balancer stops sending it new traffic first.
Add health checks
Readiness and liveness checks make sure that broken controller Pods are removed from rotation or restarted.
Performance factors
- Connections: keep-alive between the proxy and Pods reduces the cost of opening new connections.
- Encryption: handshakes are costly. Session reuse and modern protocol versions reduce the load.
- Configuration size: thousands of Ingress objects produce a huge proxy configuration and slow updates. Consider splitting across several controllers.
- Reload frequency: constant churn in routes can cause frequent reloads and dropped long-lived connections.
- Extra hops: traffic that crosses machines twice, once to the controller and once to a Pod, adds delay. Some setups keep traffic on the same machine where possible.
A mall with a single security guard at the entrance is a mall that closes when the guard has lunch. Several guards, on different shifts, standing at different doors, with a plan for how to hand over gracefully, keep the mall open all day.
16Advantages, Disadvantages and Trade-offs
Ingress controllers are the standard way to expose web apps, but they have real costs and limits.
Advantages
- One public address and one set of certificates for many applications.
- Routing by host and path, giving clean, friendly addresses.
- Central place for security, limits, logging and redirects.
- Lower cost than one cloud load balancer per Service.
- Routes are described as Kubernetes objects, versioned with the app.
- Automatic certificate renewal with cert-manager.
- Teams can add their own routes without touching infrastructure.
Disadvantages
- A shared, critical component: a fault can affect every app.
- Standard Ingress supports only HTTP and HTTPS.
- Most advanced features are controller-specific, causing lock-in.
- Shared configuration makes noisy-neighbor and conflict problems possible.
- Requires expertise to secure, tune and upgrade.
- Ingress is frozen; new features are going to the Gateway API.
- Debugging needs an understanding of several layers at once.
The design trade-offs
One controller versus several. A single shared controller is cheap and simple, but one team’s mistake can affect all. Separate controllers for public traffic, internal tools and different teams reduce the blast radius, at the cost of more moving parts and more public addresses.
In-cluster proxy versus cloud-managed. In-cluster proxies are portable and highly configurable, but you operate them. Cloud-managed entrances are easier to run and integrate with the provider’s security, but they tie you to one vendor and their feature limits.
Terminate early versus end-to-end encryption. Ending encryption at the entrance is simple and lets the controller inspect traffic. Encrypting all the way to the Pod is safer against internal snooping but costs more processing and certificate management.
Ingress today versus Gateway API. Ingress is mature, widely understood and supported by every controller. The Gateway API is richer and more portable but newer, and support varies. The right answer depends on your timeline and your team’s appetite for change.
17Security
The Ingress controller faces the open internet. It is one of the most attacked parts of any cluster, so security here is not optional.
Keep it patched
A controller is exposed software with wide permissions. Track its security announcements and upgrade promptly. Serious flaws have been found in popular controllers, including one in 2025 that affected the admission component of a widely used NGINX-based controller, so assume that more will be found.
Protect the admission webhook
Many controllers install a validation hook that the API server calls when Ingress objects are created. Make sure only the API server can reach it, and never expose it to other networks.
Least privilege for the controller
The controller needs to read Services, endpoints and certificate secrets. Give it only what it needs, and where possible limit its secret access to specific namespaces.
Restrict raw-config annotations
Disable or tightly control annotations that inject raw proxy configuration. They let editors of one Ingress influence the shared entrance.
Control who writes Ingress
Use role-based access so only trusted teams can create or edit Ingress objects in each namespace, and use admission policies to limit which host names each team may claim, preventing one team from hijacking another’s name.
Strong TLS
Allow only modern protocol versions and strong cipher choices, redirect HTTP to HTTPS, enable strict transport headers when ready, and monitor certificate expiry.
Rate limits and a firewall
Apply request rate limits, connection limits and, for public sites, a web application firewall with a maintained rule set such as the OWASP Core Rule Set.
Network policies
Allow the controller to reach only the Services it must, and make backend Pods accept traffic only from the controller namespace where appropriate. This limits damage if the controller is compromised.
Hide what you can
Custom error pages and hidden version banners avoid handing attackers useful clues.
Separate internal and public entrances
Use different controllers, and different addresses, for admin tools and public websites. An admin panel should never sit behind the same open door as your public site.
Applications that trust visitor-address headers from anywhere can be tricked into believing a request came from a trusted address. Only trust these headers when they come from your controller, and make sure the controller overwrites any values sent by the visitor.
The main entrance of a mall has cameras, guards, bag checks and a plan for emergencies, because everyone passes through it. The back offices behind it are protected too, so that if someone slips past the front desk, they still cannot walk into the vault.
18Monitoring, Logging and Metrics
The controller sees every request. That makes it the best place to learn how healthy your whole platform is.
Access logs
One line per request: time, visitor address, host, path, status code, response time and backend. Ship them to a central system and keep them long enough for investigations.
Error logs
Messages about failed configuration reloads, rejected Ingress objects and backend connection failures. Read these first when something changes unexpectedly.
Request metrics
Most controllers publish numbers in a format that Prometheus can collect: requests per second, response codes, latency percentiles and bytes transferred, per host and per backend.
Controller health
Processor and memory use, open connections, configuration reload counts and failures, and the age of the last successful reload.
Certificate expiry
Track days remaining on every certificate. Alert well before expiry, even if automation is in place, because automation can fail silently.
Tracing
Add a request identifier at the entrance and pass it along, so a single request can be followed through every service it touches.
The golden signals at the entrance
| Signal | What to watch | Warning sign |
|---|---|---|
| Traffic | Requests per second by host | Sudden drop (outage) or spike (attack or campaign) |
| Errors | Share of 5xx responses, and 502, 503 and 504 in particular | Rising percentage for one backend |
| Latency | Median and 99th percentile response time | Slow tail while the median looks fine |
| Saturation | Controller processor, memory and connections | Nearing limits during peak hours |
Alert on the share of failed requests, not just the raw number. A hundred errors is huge for a small site and invisible for a giant one.
19Design Patterns and Anti-patterns
Ideas that hold up in production, and habits that cause outages.
Patterns that work
Pattern: Public and private entrances
One controller class for the internet and another for internal tools, with different addresses and stricter rules for the private one.
Pattern: One Ingress per application, owned by that team
Each application team owns its routes in its own namespace, while the platform team owns the controller. Clear ownership avoids conflicts.
Pattern: Automated certificates
Use cert-manager everywhere. No human ever renews a certificate, and expiry alarms are the safety net rather than the routine.
Pattern: Host-based routing per application
Give each application its own name, avoiding rewrites and sub-path headaches.
Pattern: Canary at the edge
Test new versions on a small share of real traffic, with an automated way back.
Pattern: Policy guardrails
Admission policies enforce allowed host names, required classes, HTTPS-only and forbidden raw-config annotations, catching mistakes before they reach the shared door.
Traps to avoid
What it looks like
A single controller replica with default resources.
Why it hurts
Any restart, node failure or traffic spike takes every application offline.
Better approach
At least two or three replicas, spread out, autoscaled and protected by a disruption budget.
What it looks like
Dozens of controller-specific annotations copied between projects without understanding them.
Why it hurts
Behavior becomes a mystery, upgrades break routes, and switching controllers becomes a rewrite.
Better approach
Keep annotations few and documented, and consider the Gateway API for features that annotations were covering.
What it looks like
Exposing admin dashboards through the same public entrance with no extra protection.
Why it hurts
Anyone on the internet can try to log in to sensitive tools.
Better approach
Use a private entrance, strong authentication at the edge, and network restrictions.
What it looks like
Installing two controllers without classes.
Why it hurts
Both may try to manage the same Ingress, or neither does, causing puzzling behavior.
Better approach
Always define IngressClass objects and name a class in every Ingress.
What it looks like
Long file uploads or streaming with default short timeouts.
Why it hurts
Requests are cut off midway, and users see random failures.
Better approach
Tune timeouts and body-size limits for the specific hosts that need them, not globally.
20Best Practices and Common Mistakes
Habits that keep the front door open, and errors that lock people out.
Habits that pay off
- Treat the controller as tier-zero infrastructure with its own owners, monitoring, alarms and on-call.
- Use readiness checks on backends so the controller only sends traffic to Pods that are ready.
- Set explicit classes on every Ingress.
- Automate certificates and alert on expiry anyway.
- Test changes in a staging cluster before applying to the shared production entrance.
- Upgrade on a schedule with a rollback plan, reading release notes for changed defaults.
- Document your annotations and keep an inventory of which teams use which features.
- Keep a default backend with a helpful, non-revealing error page.
- Plan the exit by learning the Gateway API now, so you are not forced to move in a hurry.
Mistakes beginners make
No controller installed
Creating Ingress objects and wondering why nothing happens. Without a controller, the Ingress is just a note.
Wrong or missing class
The Ingress names a class no controller owns, so nobody handles it.
Wrong Service port
The rule points at a port the Service does not expose, giving 503 or 502 errors.
Service in the wrong namespace
An Ingress can only use Services in its own namespace.
DNS not pointing to the controller
The rules are perfect, but the name still points to an old address.
Certificate secret missing or in the wrong namespace
The controller falls back to a default fake certificate, and browsers show warnings.
Path type confusion
Using Exact when Prefix was intended, so sub-paths return not found.
Health checks that fail behind the load balancer
The cloud load balancer marks the controller unhealthy because its check path is wrong, and traffic stops.
21Real-World and Industry Examples
The same idea shows up at every scale.
A small team on a managed cluster
A start-up runs a website, an API and an admin site on a managed Kubernetes service. One NGINX-based or Traefik controller sits behind a single cloud load balancer. Three Ingress objects route three host names, cert-manager handles certificates, and the monthly cost is one load balancer instead of three.
Cloud-provider integrated entrances
Teams on Amazon’s cloud often use the AWS Load Balancer Controller to turn Ingress objects into Application Load Balancers. Teams on Google Cloud and Azure use their own managed options. These integrate with cloud firewalls and identity but need the provider’s rules for limits such as the number of rules and certificates.
Envoy at the edge
Envoy, created at Lyft and later adopted widely, is the proxy behind Contour, Emissary and several service meshes. Companies that want live configuration updates without reloads and rich traffic controls often choose Envoy-based entrances.
Multi-tenant platforms
Platform companies hosting many customers give each customer a namespace and a host name. Policy engines make sure a customer can only claim their own names. A wildcard certificate and automation onboard a new customer in minutes.
Moving to the Gateway API
Larger organizations, and many vendors, have begun adopting the Gateway API for new work while keeping Ingress running for existing sites. They run both side by side and migrate service by service, reducing risk.
A typical online shop
The shop’s public entrance handles the storefront, the API and the image service under three names, all with automatic HTTPS. A private entrance serves the staff dashboard, reachable only through the company network. During a sale, the controller autoscales from three to twelve Pods, and a canary rule tests a new checkout page on a small share of visitors first.
22Troubleshooting Ingress
When the front door does not open, walk the path of the request from the outside in.
flowchart TD
T1["Visitor sees an error"] --> T2{"Does the name resolve to the controller address?"}
T2 -->|No| F1["Fix DNS"]
T2 -->|Yes| T3{"Does the controller answer at all?"}
T3 -->|No| F2["Check load balancer, firewall and controller Pods"]
T3 -->|Yes| T4{"What status code?"}
T4 -->|404| F3["No rule matched: check host, path, class and path type"]
T4 -->|502 or 503| F4["Backend problem: check Service, port, endpoints and readiness"]
T4 -->|504| F5["Backend too slow: check timeouts and Pod health"]
T4 -->|Certificate warning| F6["Check certificate secret, name and expiry"]
| Symptom | Most likely cause | First check |
|---|---|---|
| Nothing happens after creating Ingress | No controller, or class mismatch | Confirm a controller is running and the class name matches |
| 404 from the controller | Host or path does not match any rule | Compare the request’s host and path with the rules |
| 503 Service unavailable | Service has no ready Pods | Check the Service’s endpoints and Pod readiness |
| 502 Bad gateway | Pod refused the connection or sent a bad reply | Verify the port and that the app listens on all addresses |
| 504 Gateway timeout | Backend too slow for configured timeouts | Look at Pod load and the timeout settings |
| Browser warns about certificate | Default fake certificate, wrong name, or expired | Check the secret, its namespace, and cert-manager status |
| Works for some visitors only | Stale DNS, or a controller replica out of sync | Check each controller Pod’s logs and readiness |
| Configuration change ignored | Controller rejected it; validation error | Read the controller’s error log and the Ingress events |
Always test in two steps. First, call the backend Service from inside the cluster to prove the application works. Then call through the Ingress. If the first works and the second does not, the fault is in the Ingress, class, DNS or controller, not in your app.
23Frequently Asked Questions
Quick answers to the questions people ask most.
24Summary and Key Takeaways
You started with a mall that has one main entrance. Now you know how to build, guard and grow that entrance for a cluster.
Key Takeaways
- Two parts: An Ingress is a set of routing rules; an Ingress controller is the reverse proxy that reads them and moves the traffic. You need both.
- Why it exists: One public address and one set of certificates can serve many web applications, with routing by host name and path, at far lower cost than a load balancer per Service.
- How it works: The controller watches the cluster, builds a proxy configuration, sends requests to live Pod addresses and ends HTTPS at the entrance, often with certificates renewed by cert-manager.
- Choose carefully: Many controllers exist, in-cluster and cloud-managed. Check maintenance status, features and fit, and always set explicit ingress classes.
- Protect the door: Keep it patched, restrict raw-configuration annotations, guard the admission hook, limit who can claim host names, use strong TLS, rate limits, a firewall and network policies.
- Run it like tier-zero: Several spread-out replicas, autoscaling, disruption budgets, graceful shutdown, access logs, metrics on the four golden signals and certificate expiry alarms.
- Look ahead: Ingress is stable but frozen, and the Gateway API is the richer, more portable successor. Learn it now and migrate at your own pace.