Ingress in Kubernetes

Ingress in Kubernetes

A friendly, step-by-step guide to how visitors from the internet find the right application inside a Kubernetes cluster: what Ingress is, how it works, how to secure it, and how to avoid the classic mistakes.

Imagine you have built an online shop. Behind the scenes it is not one big program. It is many small programs: one shows product pages, one handles payments, one powers search, one sends order emails. All of them run inside a Kubernetes cluster, which is a group of computers managed together as if they were one.

Now a customer opens a browser and types your website address. That single request arrives at the edge of your cluster and must find the right small program among dozens. Who looks at the address? Who decides that /pay goes to the payment program and /search goes to the search program? Who also unlocks the secure padlock (HTTPS) so that the customer’s card details stay private?

In Kubernetes, the answer to all of these questions is Ingress. In this guide we will build the idea from zero, one small step at a time. Every new word is explained the first time it appears, and every big idea comes with an everyday comparison so it sticks.

1What Is Ingress?

Before we talk about Ingress, we need four simple words: cluster, pod, service, and ingress. Let us meet them one by one.

Word 1

Cluster

A cluster is a group of computers that work together as one big computer. Kubernetes is the software that manages this group. Google, Spotify and Airbnb have all shared publicly how they run services on Kubernetes.

Word 2

Pod

A pod is a running copy of your application, the smallest thing Kubernetes runs. Pods are temporary. They can be created, destroyed and replaced at any moment, and each new pod gets a brand-new internal address.

Word 3

Service

A service gives a group of pods one stable name and one stable address. Even when pods come and go, the service address stays the same. Think of it as the phone number of a department, not of one employee.

Word 4

Ingress

Ingress is a set of rules at the edge of the cluster. The rules say which outside web requests should be sent to which service. It is the rule book for incoming web traffic.

So what exactly is Ingress?

Ingress is a Kubernetes object that describes how outside HTTP and HTTPS traffic should reach services inside the cluster. HTTP is the language browsers use to talk to websites. HTTPS is the same language, wrapped in encryption so nobody can read it on the way.

The word “ingress” simply means “the way in”. Its opposite, “egress”, means “the way out”. Ingress is therefore the official way in for web visitors.

An important detail: an Ingress object is only a written set of rules. It does not move a single byte of traffic by itself. Another piece, called the Ingress controller, reads those rules and does the real work. We will study both pieces in detail, because mixing them up is the number one beginner mistake.

Everyday analogy

Picture a big office tower with one front door and a reception desk. Visitors do not wander the corridors looking for the right room. They tell the receptionist who they want to see, and the receptionist points them to the correct floor. The list of “who sits where” on the receptionist’s desk is the Ingress. The receptionist who reads the list and guides people is the Ingress controller.

A short history

Google released Kubernetes as open source in 2014. In the early days, exposing an application to the internet was awkward, and every team invented its own tricks. The Ingress idea arrived as an early (beta) feature in late 2015, and it became a stable, officially supported feature in Kubernetes version 1.19 in 2020.

Today there is a newer and more powerful family of objects called the Gateway API. We will meet it later. Even so, Ingress is still used in a huge number of production clusters, and understanding it makes Gateway API much easier to learn.

i
Remember this

Ingress always comes as a pair: the rules (the Ingress object) and the worker (the Ingress controller). A cluster with rules but no controller behaves like a reception desk with a list and nobody sitting behind it.

2The Problem Ingress Solves

Kubernetes already has ways to open a door to the outside world. To see why Ingress was invented, we first need to see why those doors are not enough for web applications.

The three older doors

Kubernetes offers three main kinds of service. Each one answers the question “who is allowed to talk to my pods?” in a different way.

ClusterIP is the default. It gives the service an address that works only inside the cluster. It is perfect for private conversations between your own programs, but a visitor on the internet can never reach it.

NodePort opens the same high-numbered port on every computer in the cluster. By default the port is somewhere between 30000 and 32767. A visitor could type the computer’s address followed by that odd number. It works for quick experiments, but nobody wants a shop at an address ending in :31874.

LoadBalancer asks your cloud provider (AWS, Google Cloud, Azure) to create a real load balancer just for that one service. A load balancer is a machine or managed service that spreads incoming traffic across many servers. It gives you a clean public address, but there is a catch: one service means one load balancer.

MethodWhat it doesGood forWeakness
ClusterIPInternal-only addressService-to-service talk inside the clusterInvisible to the outside world
NodePortOpens one high port on every machineLearning and quick testsUgly ports, wide attack surface, no smart routing
LoadBalancerOne dedicated cloud load balancer per serviceExposing a single service, including non-web onesCost and address sprawl grow with every service
IngressOne shared entry point that routes by host name and pathMany web applications behind one front doorWeb traffic only, needs a controller installed

The pain of many front doors

Imagine our shop has ten services that must be reachable from the internet. With plain LoadBalancer services you would create ten cloud load balancers. That means ten public addresses to manage, ten separate bills, and ten places where you must install and renew your HTTPS certificate.

There is also a smarter problem. A plain load balancer at the network level does not understand web addresses. It cannot say “requests for shop.example.com go here and requests for api.example.com go there”. It just forwards bytes. Web applications need a helper that can read the request and make decisions based on what it says.

flowchart TB
  subgraph WITHOUT["Without Ingress: one load balancer per service"]
    direction LR
    U1["Internet visitor"] --> LB1["Cloud Load Balancer 1"] --> S1["Shop Service"]
    U1 --> LB2["Cloud Load Balancer 2"] --> S2["Payments Service"]
    U1 --> LB3["Cloud Load Balancer 3"] --> S3["Search Service"]
  end
  subgraph WITH["With Ingress: one shared front door"]
    direction LR
    U2["Internet visitor"] --> LB4["One Cloud Load Balancer"] --> IC["Ingress Controller"]
    IC --> S4["Shop Service"]
    IC --> S5["Payments Service"]
    IC --> S6["Search Service"]
  end
    
Figure 1. Three cloud load balancers collapse into one shared entry point.
Everyday analogy

Building a separate front door, a separate doorbell and a separate security guard for each of ten shops in a shopping mall would be silly. A mall has one main entrance and a directory board that says which shop is on which floor. Ingress turns your cluster into a mall: one main entrance, one directory, one security checkpoint.

1
shared front door for many web applications
L7
works at the HTTP and HTTPS level, reading host names and paths
443
the standard HTTPS port where encryption is usually unlocked
!
Watch out

NodePort is fine for a classroom demo, but exposing production traffic through it means every machine in the cluster becomes a public doorway. Prefer a proper load balancer or Ingress in front of real users.

3Core Concepts

Ingress has only a handful of building blocks. Learn these eight and everything else in this guide will feel familiar.

Rules

Ingress resource

The written rule book. It lists host names, paths and the service that should receive each kind of request. You save it in the cluster like any other Kubernetes object.

Worker

Ingress controller

The program that reads the rule book and actually moves traffic. It runs as ordinary pods inside the cluster and is built on a proxy such as NGINX, HAProxy, Envoy or a cloud load balancer.

Choice

IngressClass

A label that says which controller should handle which Ingress. If a cluster has two controllers, the class stops them from fighting over the same rules.

Match

Host

The website name in the request, such as shop.example.com. Browsers send it along with every request, so one entry point can serve many different websites.

Match

Path

The part of the address after the website name, like /cart or /images. Rules can send different paths to different services.

Target

Backend

The place a matched request is sent to. In most cases this is a Kubernetes service and a port number. The service then picks a healthy pod.

Safety net

Default backend

Where requests go when no rule matches. It usually shows a friendly “page not found” message instead of an ugly error or, worse, the wrong application.

Security

TLS section

Tells the controller which host names should use HTTPS and which stored certificate to present. TLS is the encryption technology behind the padlock in your browser.

Everyday analogy

Think of a recipe card and a chef. The card says “add salt, bake for twenty minutes”, yet a card alone never made a cake. The Ingress resource is the recipe card. The Ingress controller is the chef who reads it and cooks. You can swap the chef for a different one and keep the same card, which is exactly why IngressClass exists.

Understanding path types

When you write a path rule, you must also say how strictly to compare it. Kubernetes offers three path types.

Path typeHow it comparesExample with /shop
ExactThe request path must be identical, letter for letterMatches /shop only. Does not match /shop/ or /shop/items
PrefixCompares whole path pieces separated by slashesMatches /shop, /shop/ and /shop/items. Does not match /shopping
ImplementationSpecificLeaves the decision to the chosen controllerDepends on the controller, so behaviour can differ between products

When several rules could match one request, the most specific one wins. A long exact path beats a short prefix path. This is like a postal sorter who prefers a full street address over just a city name.

i
Good to know

Ingress speaks HTTP and HTTPS only. If you need to expose a database port, a game server or any other raw TCP or UDP service, you will use a LoadBalancer service, controller-specific extras, or the newer Gateway API instead.

4Architecture and Components

Let us zoom out and see every piece that sits between a visitor’s browser and your application, in the order a request meets them.

flowchart LR
  User["Browser or Mobile App"] --> DNS["DNS Record"]
  DNS --> LB["Cloud Load Balancer"]
  LB --> IC["Ingress Controller Pods"]
  ING["Ingress Resource with Rules"] --> API["Kubernetes API Server"]
  API -. "controller watches for changes" .-> IC
  IC -->|"shop.example.com"| SVC1["Shop Service"]
  IC -->|"api.example.com"| SVC2["API Service"]
  SVC1 --> P1["Shop Pods"]
  SVC2 --> P2["API Pods"]
    
Figure 2. The full path of a request, plus the control path that teaches the controller its rules.

Piece by piece

DNS is the internet’s phone book. It turns a friendly name like shop.example.com into a numeric address. For Ingress, that name points at the public address of your entry point, so DNS is the very first thing every visitor touches.

The cloud load balancer is the outermost door. It has a public address, accepts the connection from the visitor, and forwards it to one of the computers running the Ingress controller. In AWS this is usually a Network Load Balancer or an Application Load Balancer.

The Ingress controller pods are the reception desk. Usually you run at least two or three copies, spread over different machines, so that losing one machine does not close the front door. Each copy contains a proxy, which is a program that receives a request, decides where it should go, and passes it on.

The Kubernetes API server is the cluster’s central notice board. Every object, including your Ingress rules, is stored there. The controller keeps an eye on this notice board and reacts the moment something changes.

Services and pods are the destination. The controller either hands the request to the service, or looks up the healthy pods behind it and talks to them directly. We will see why this difference matters in the next chapter.

Everyday analogy

A concert works the same way. DNS is the ticket that tells you which stadium to go to. The load balancer is the stadium gate. The Ingress controller is the usher who reads your ticket and walks you to the correct block. The service is the block itself, and the pod is your actual seat.

Where the controller lives

There are two common designs. In the first, the controller runs inside the cluster as normal pods, and a single LoadBalancer service exposes those pods to the internet. Community NGINX, Traefik and HAProxy controllers usually work this way.

In the second, the controller is only a thin translator. It reads your Ingress rules and configures a load balancer that lives outside the cluster, run by the cloud provider. The AWS Load Balancer Controller works this way: it creates an Application Load Balancer and keeps its rules in sync with your Ingress objects. In this design the actual traffic does not pass through pods you manage at all.

2 to 3+
controller replicas is a common minimum for a production cluster
1
API server acts as the single source of truth for all rules
0
controllers installed by default, you must add one yourself
!
Common surprise

Kubernetes does not ship with an Ingress controller. If you create Ingress rules in a fresh cluster and nothing happens, the missing controller is almost always the reason.

5How Ingress Works Internally

Here is what really happens inside the controller from the moment you save a rule to the moment a visitor is served.

The watch-and-reconcile loop

Kubernetes is built around a simple habit called the control loop. A controller compares “what the world should look like” (the desired state) with “what it looks like right now” (the actual state), and then takes small actions to close the gap. It repeats this forever.

An Ingress controller applies this habit to web routing. It subscribes to change notifications from the API server for four kinds of objects: Ingresses, Services, endpoint lists, and certificate secrets. Whenever any of them changes, it wakes up and works out what its proxy should now look like.

flowchart TD
  A["Admin saves new Ingress rules"] --> B["API Server stores the object"]
  B --> C["Controller is notified of the change"]
  C --> D["Controller builds a new proxy configuration"]
  D --> E{"Is the configuration valid?"}
  E -->|"Yes"| F["Proxy is updated without dropping connections"]
  E -->|"No"| G["Old configuration is kept and an error event is recorded"]
  F --> H["New traffic follows the new rules"]
    
Figure 3. The controller’s loop: watch, translate, validate, apply.
1

Watch

The controller keeps an open line to the API server and hears about every relevant change within moments.

2

Translate

It turns the Kubernetes rules into the native language of its proxy. For an NGINX-based controller, that means writing NGINX configuration.

3

Validate

Before switching, it tests the new configuration. A typo in one team’s rules must never take the whole front door down for everyone.

4

Apply

It loads the new configuration gracefully. Requests already in progress finish on the old settings while new ones use the new settings.

5

Report

It writes the public address into the Ingress status and records events, so that humans can see what happened.

Why controllers often skip the Service

A Service normally works like a small random selector: it receives a request and picks a pod. But the Service is only a pointer. The real list of healthy pod addresses lives in an object called an endpoint list (modern clusters call it EndpointSlices).

Many controllers read that list directly and send traffic straight to the pod addresses. This skips one extra hop, allows smarter balancing such as “least busy pod”, and lets the controller keep a user’s session on the same pod when that is needed. The Service is still important, because it is the name you write in your rules and the thing that keeps the pod list up to date.

Everyday analogy

Suppose you ask a taxi company’s call centre for a driver. The Service is the call centre’s phone number. The endpoint list is the live board showing which drivers are free right now. A clever dispatcher looks at the board and calls the nearest free driver directly instead of waiting for the call centre to guess.

Reloads without pain

In the early days, every change forced a proxy restart, and a busy cluster with constantly changing pods caused a storm of restarts. Modern controllers avoid this. When only the list of pod addresses changes, which happens all the time, many controllers update it in memory without any reload. A full reload is kept for real rule changes, such as a new host name or a new certificate.

i
Tip

If a change to your rules seems ignored, check the events on the Ingress object first. A rejected configuration leaves the old one running, so the controller looks alive even though your update never took effect.

6Data Flow and Lifecycle

Now let us follow one single visitor from the first click to the finished page, and then follow one Ingress object from birth to deletion.

The journey of one request

sequenceDiagram
  participant U as Visitor Browser
  participant D as DNS
  participant L as Cloud Load Balancer
  participant I as Ingress Controller
  participant S as Service
  participant P as Pod
  U->>D: Where is shop.example.com?
  D-->>U: Address of the load balancer
  U->>L: Secure request arrives
  L->>I: Traffic forwarded to a controller pod
  I->>I: Unlock TLS then match host and path
  I->>S: Send to the chosen backend
  S->>P: A healthy pod is selected
  P-->>U: Response returns along the same path
    
Figure 4. One request, from a typed address to a finished web page.
1

Name lookup

The browser asks DNS where the website lives and receives the public address of the entry point.

2

Connection

The browser connects to the load balancer, which picks one of the controller pods.

3

Unlocking the padlock

The controller presents a certificate, agrees on encryption keys with the browser and reads the request. This is called TLS termination.

4

Matching

It looks at the host name and path and finds the rule that fits best.

5

Forwarding

It passes the request to a healthy pod, often adding helpful headers such as the visitor’s original address.

6

Response

The pod answers, the answer travels back through the controller and the load balancer, and the page appears.

The whole trip usually takes a few dozen milliseconds. The controller’s share of that time is tiny, often a millisecond or less on a healthy setup. If pages feel slow, the cause is nearly always the application or the network distance, not the Ingress.

The lifecycle of an Ingress object

An Ingress object also has a life story. Knowing it helps you understand what you see when you inspect it.

Stage 1

Created

You save the rules. The API server accepts them and stores them, and some clusters run a safety check first.

Stage 2

Claimed

The controller whose class matches the Ingress picks it up. Rules with no matching controller stay ignored.

Stage 3

Address assigned

Once traffic can flow, the public address appears in the status of the object. Until then, it stays empty.

Stage 4

Active

Live traffic follows the rules. Pods scale up and down underneath while the rules stay untouched.

Stage 5

Updated

You change a path or a certificate. The controller validates and applies the change without dropping visitors.

Stage 6

Deleted

The rules are removed. Requests for those hosts now fall to the default backend, and cloud resources created for the rules are cleaned up.

i
Health matters

A controller only sends traffic to pods that report themselves ready. Give every application a readiness check, which is a small “am I ready for visitors?” test, or the controller may send early visitors to a pod that is still warming up.

Keeping connections fast

Opening a brand-new connection is slow, because the two sides must greet each other and, for HTTPS, agree on secret keys. To avoid repeating this work, the controller keeps connections open and reuses them for many requests. This is called keep-alive. It is like keeping a phone line open during a long chat instead of hanging up and redialling after every sentence.

Modern controllers also speak HTTP/2, a newer version of the web language that lets many requests share one connection at the same time. The controller can talk HTTP/2 to the visitor and a simpler version to your pods, so your applications get the speed benefit without any change.

Finally, remember that the controller is patient only up to a point. It has timeouts: how long to wait for a connection to a pod, how long to wait for the pod’s answer, and how long an idle line may stay open. If an application sometimes needs sixty seconds to generate a report, but the timeout is thirty, visitors will see an error even though the application worked. Always match timeouts to the real behaviour of each route.

7Routing Patterns You Will Use

Most real-world Ingress setups are built from a small set of routing patterns. Learn to recognise them and you can read almost any configuration.

Host-based routing

Different website names go to different services. Requests for shop.example.com reach the shop service, and requests for blog.example.com reach the blog service. Companies use this to give every product or team its own address while sharing one entry point.

Path-based routing

One website name, different paths. The address example.com/cart goes to the cart service, while example.com/search goes to the search service. Visitors think they are on one website, but behind the curtain many small teams own the pieces.

Fan-out

A single host name with many paths, each pointing to a different backend. This is the pattern our online shop uses. It is a natural fit for microservices, which are small independent programs that each do one job.

Default backend

Anything that matches no rule lands on a friendly fallback service. A good fallback returns a clear “not found” page and quietly logs the strange request, which also helps you notice scanners probing your site.

Wildcard hosts

A single rule for every sub-address under a domain, such as anything ending in .example.com. Software-as-a-service companies use this so each customer can have a personal address without a new rule per customer.

Canary and gradual releases

Send a small share of visitors, say five percent, to the new version of an application while the rest still use the old one. Many controllers support this through extra settings. If errors rise, you switch it off and only a few visitors were affected.

Everyday analogy

Host-based routing is like a postal sorting centre that first looks at the city on the envelope. Path-based routing then looks at the street. A fan-out is a sorting centre with one belt that splits into many smaller belts, one for each street.

Rewrites and redirects

Sometimes the address the visitor uses is not the address your application expects. Your cart program might live at the root of its own service, but the visitor types /cart. A rewrite quietly changes /cart/items into /items before the request reaches the application. A redirect is different: it tells the browser to go to another address, and the browser makes a new request.

These features are not part of the basic Ingress definition. Each controller offers them through its own settings, usually called annotations, which are small notes attached to the Ingress. That is powerful, but it also means your configuration may not move easily between controllers.

!
Watch out

Two Ingress objects that claim the same host and path can conflict. Which one wins depends on the controller, and it may change silently after an update. Give every host and path exactly one owner.

8TLS and Security

The Ingress controller is the first program to touch every request from the internet. That makes it the best place to add security, and also the most attractive place for attackers to aim.

TLS termination: unlocking the padlock in one place

TLS is the encryption used by HTTPS. A certificate is a digital passport that proves a website is really who it claims to be. It is issued by a trusted organisation called a certificate authority.

With TLS termination, the controller holds the certificate and does all the encryption work at the front door. Your applications behind it can stay simple and never handle certificates. The certificate is stored in the cluster as a special secret, and the TLS section of your Ingress names it.

There are three ways to handle encryption on the last stretch inside the cluster. Terminate and forward plain is the simplest and fastest. Terminate and re-encrypt unlocks the traffic at the door for inspection and then locks it again before sending it to the pod, which suits strict security rules. Passthrough never opens the traffic at all and lets the application handle its own encryption, but then the controller cannot read paths or add headers.

Everyday analogy

Terminating TLS is like a bank branch where a guard at the entrance checks your identity and opens the armoured van door. Re-encrypting is like moving the cash from the van into a second sealed bag before carrying it down the inner corridor. Passthrough is like the guard letting the sealed van drive straight to the vault without looking inside.

Certificates that renew themselves

Certificates expire. An expired certificate makes browsers show a scary warning page, and visitors leave. The classic story is a company whose website went down on a Sunday because someone forgot to renew a certificate.

The community solved this with a tool called cert-manager, which runs in the cluster, requests certificates from an authority such as Let’s Encrypt (a free, automated authority whose certificates traditionally last 90 days), and renews them long before they expire. On AWS, another popular choice is to keep certificates in AWS Certificate Manager and let the load balancer use them directly.

Encrypt

Force HTTPS

Redirect all plain HTTP visitors to HTTPS, and send a header that tells browsers to always use HTTPS for your site in the future.

Limit

Rate limiting

Cap how many requests one visitor can make per second. This blunts password-guessing bots and accidental floods.

Filter

Web application firewall

A firewall that understands web attacks such as injected commands. Many controllers support one, and the AWS load balancer can be paired with AWS WAF.

Identify

Authentication at the edge

Ask visitors to log in before their request ever reaches the application. This protects internal dashboards without changing their code.

Allow

IP allow lists

Permit an admin panel only from your office or VPN addresses. Everyone else is turned away at the door.

Verify

Mutual TLS

Both sides show a certificate. The server proves who it is, and the client proves who it is too. It is common for machine-to-machine traffic.

Protecting the controller itself

Because the controller can read every request and holds your certificate secrets, it is a high-value target. In March 2025 security researchers disclosed a group of serious flaws, nicknamed IngressNightmare, in the popular community NGINX controller. They showed that a weakness in the controller’s safety-check component could let an attacker take over the controller and reach secrets across the cluster. The lesson is not “avoid Ingress”. The lesson is to treat the controller like the critical building it is.

Habits that keep the front door safe

Keep the controller updated and subscribe to its security announcements. Never expose its safety-check component to the network. Switch off free-form configuration snippets unless you truly need them. Give only trusted people permission to create or edit Ingress objects. Run the controller pods with the fewest privileges possible, and add network policies so that only the controller can reach your application pods.

!
Who can write rules?

Anyone who can create an Ingress can decide where some traffic goes. In a shared cluster, restrict permissions and consider policies that stop one team from claiming another team’s host name.

9Choosing an Ingress Controller

The Ingress rules are the same everywhere, but the worker you hire changes the speed, the features and the operating cost.

ControllerBuilt onWhere traffic flowsNotable strength
Community NGINX (ingress-nginx)NGINXPods in your clusterHuge number of tutorials and examples
NGINX Ingress Controller from F5NGINX or NGINX PlusPods in your clusterCommercial support and advanced features
TraefikTraefik proxyPods in your clusterAutomatic discovery and a friendly dashboard
HAProxy IngressHAProxyPods in your clusterStrong performance and stability record
Contour, EmissaryEnvoyPods in your clusterModern proxy features and good live updates
Istio ingress gatewayEnvoyPods in your clusterTight fit if you already use a service mesh
AWS Load Balancer ControllerAWS Application Load BalancerManaged load balancer outside the clusterNative AWS integration with WAF, ACM certificates and IAM

The AWS way

On Amazon EKS, many teams choose the AWS Load Balancer Controller. For each Ingress it creates an Application Load Balancer, which is a managed layer-7 load balancer, and keeps its listeners and rules in step with your Ingress. Amazon looks after scaling and patching of that load balancer, which removes a chunk of work from your team.

It can send traffic directly to pod addresses (“IP mode”) when the cluster uses the Amazon VPC network plugin, which removes an extra hop. It can also let several Ingress objects share one load balancer through a grouping setting, which prevents the “one load balancer per service” bill explosion we discussed in Chapter 2.

The trade-off is portability. Many of its features are configured through AWS-specific notes on the Ingress, so moving the same rules to another cloud needs some rework.

Everyday analogy

Running an in-cluster controller is like hiring your own receptionist: you choose them, train them and cover their sick days. Using a cloud-managed controller is like renting a front desk from the building’s management company: less work, less control over the small details.

How to decide

Question 1

Where do you run?

On one cloud, the cloud’s own controller is often the least effort. On several clouds or on your own servers, choose an in-cluster proxy that behaves the same everywhere.

Question 2

What features do you need?

Simple host and path routing is available everywhere. Advanced needs such as authentication, canary releases or fine-grained rate limits vary a lot between products.

Question 3

Who supports it?

Check that the project is actively maintained and gets timely security fixes. Also check whether your company needs a vendor to call at 3 a.m.

Question 4

What does your team know?

A tool your engineers already understand deeply is usually safer than a fancier tool nobody has debugged at midnight.

!
Check the project’s status

The Kubernetes community has announced that the widely used community NGINX controller is being retired, with maintenance winding down. Before choosing any controller for a new project, look at its current release activity and support status on its official page.

10Advantages, Disadvantages and Trade-offs

No tool is perfect. A good engineer knows both what Ingress gives and what it costs.

Advantages

  • One shared entry point instead of many load balancers, which cuts cost and address sprawl
  • Routing by host name and path, which suits microservices
  • Certificates managed in one place
  • Security features such as rate limits and firewalls added once at the edge
  • Rules stored as Kubernetes objects, so they can live in version control and be reviewed like code
  • A stable, widely understood standard with many controller choices

Disadvantages

  • Handles HTTP and HTTPS only, not raw TCP or UDP
  • Advanced features depend on controller-specific annotations, which hurts portability
  • One shared door can become a shared point of failure if under-sized
  • The basic definition has no clear split between platform and application roles
  • The controller is a high-value security target and needs careful updating
  • Extra piece to install, operate and monitor

The trade-offs behind the lists

Shared versus separate. Sharing one controller across all teams saves money, but one team’s heavy traffic or bad configuration can affect others. Many larger companies run separate controllers for public traffic and internal traffic, or one per team, and accept the extra cost in return for isolation.

Simple versus powerful. The standard Ingress fields are easy to learn but limited. To get more, you reach for annotations, and each annotation is a private agreement between you and one controller. Too many of them make the setup hard to read and hard to move.

In-cluster versus managed. An in-cluster proxy gives you fine control and works everywhere, but you must patch and scale it. A managed cloud load balancer removes that burden but ties you to one provider.

Where Gateway API fits

The Kubernetes community created the Gateway API to fix the limits above. It reached its first stable release in 2023. Instead of one object doing everything, it splits the work: a GatewayClass describes the type of gateway, a Gateway describes the actual entry point and who may attach to it, and route objects such as HTTPRoute describe the routing rules. This lets a platform team own the door while application teams own their own routes, and it supports more traffic types and standard ways to do things that Ingress needs annotations for.

Ingress keeps simple things simple. Gateway API keeps complicated things organised.

The Ingress object is not going away suddenly. It is a stable, frozen feature, meaning it receives fixes but few new capabilities. Sensible advice for a new large platform is to learn both, use Ingress where it is already in place, and consider Gateway API for new designs.

Scaling the front door

The controller must grow with your traffic. The usual method is horizontal scaling: add more identical controller pods and let the load balancer spread visitors across them. Each pod can handle a certain number of requests and open connections per second, which depends on its processor, its memory and how much work it does per request. Encrypting traffic and running a firewall both cost extra processor time, so a controller doing more work needs more pods.

Autoscaling adds and removes pods automatically based on a measurement such as processor use or requests per second. It reacts in minutes, though, and a sudden rush can arrive in seconds. For known big events, such as a festival sale or a live sports match, experienced teams scale up in advance and ask their cloud provider to prepare the load balancer for the surge, instead of trusting autoscaling to catch up.

Also watch the pieces around the controller. A managed load balancer has its own limits, the network has its own limits, and the applications behind the door have theirs. A very fast front door is useless if all its traffic squeezes into one slow database. Capacity planning means checking every link in the chain, not only the first one.

Everyday analogy

Opening more entry gates at a stadium helps only if the corridors and seats behind them can handle the crowd. Ingress scaling is the gates. The rest of the stadium must grow with them.

11Monitoring, Logging and Metrics

Because every request passes through the Ingress controller, it is the best place to learn how healthy your whole system is. Watching it is like checking the pulse at the wrist: one spot tells you a lot about the entire body.

The four golden signals at the front door

Site reliability engineers at Google popularised four simple signals: latency, traffic, errors and saturation. Ingress gives you all four almost for free.

Traffic

Request rate

How many requests arrive each second, split by host and path. A sudden jump may be a marketing success or an attack.

Errors

Error rate

The share of answers that are failures. Codes starting with 4 usually mean a visitor mistake. Codes starting with 5 mean your side is failing and deserve alerts.

Latency

Response time

How long answers take. Track percentiles: the 99th percentile is the time that only the slowest one percent of visitors exceed. Averages hide unhappy customers.

Saturation

Controller load

Processor and memory use of the controller pods, and the number of open connections. Full pods mean it is time to add copies.

Health

Reloads and errors

How often the configuration reloads and whether any reload failed. Frequent failures mean someone is pushing broken rules.

Trust

Certificate expiry

Days left before each certificate expires. This one number prevents the classic Sunday outage.

p99
latency percentile that reveals the slowest one percent of visits
5xx
error codes that mean your side failed and should page someone
14 days
a sensible warning window before a certificate expires

Logs and traces

An access log is a diary with one line per request: who asked, for what, how long it took and what answer was returned. Store these logs in a central place such as Amazon CloudWatch Logs, Grafana Loki or Elasticsearch, so you can search them even after a pod disappears. Structured logs, where each line has labelled fields, are far easier to search than free text.

Add a unique request identifier at the front door and pass it to every service behind it. When a customer says “my payment failed at 10:42”, you can follow that one identifier through all the small programs. Combine it with distributed tracing tools, which draw a timeline of one request across services, and the mystery of “where did the time go?” becomes a picture.

Everyday analogy

The access log is the visitor book at the reception desk. The metrics are the counter clicking on each visitor. The request identifier is the sticker placed on each visitor’s shirt, so any floor can say “yes, this person came through here at 10:42”.

i
Alert on symptoms

Raise alerts for things visitors feel: a rising share of 5xx answers, slow 99th percentile times, no healthy controller pods, and certificates close to expiry. Avoid noisy alerts about small internal details that nobody can act on at night.

Failure scenarios worth rehearsing

Good teams practise failure before it happens. Three scenarios are worth a rehearsal. First, a controller pod dies: the load balancer should notice within seconds and stop sending it traffic, and users should see nothing. Second, a bad rule is pushed: the controller should reject it and keep the old rules, and your alerts should tell you. Third, a whole availability zone disappears: the remaining zones must have enough spare controller and application pods to carry the extra load.

Write down what should happen in each case, test it in a staging cluster, and time how long recovery takes. A runbook, which is a short step-by-step guide for an emergency, saves precious minutes when someone is tired at night. The first few lines should always say how to check DNS, the load balancer, the controller pods and the rule status, in that order.

12Design Patterns and Anti-patterns

A pattern is a proven way of solving a common problem. An anti-pattern is a habit that looks sensible at first and causes pain later.

Patterns that work

Pattern

Public and private doors

Run one controller for internet traffic and a separate one for internal tools. A mistake on the private side can then never leak onto the public side.

Pattern

One Ingress per team

Each team owns the rules for its own services in its own namespace, which is a private workspace inside the cluster. Changes stay small and reviews stay simple.

Pattern

CDN in front

Place a content delivery network, such as Amazon CloudFront or Cloudflare, before the load balancer. Images and static files are served from nearby locations, and the cluster sees far less traffic.

Pattern

Gradual migration

Move a large old application to small services piece by piece. Route one path at a time to the new service until the old program has nothing left to do. This is often called the strangler pattern.

Pattern

Multi-zone spread

Spread controller pods over several availability zones, which are separate data centres in one region, so one building failing does not stop traffic.

Pattern

Global routing with DNS

For several regions, use a DNS service such as Amazon Route 53 to send visitors to the nearest healthy cluster, each with its own Ingress.

Anti-patterns to avoid

ANTI-PATTERN 01 · One lonely controller pod Avoid
The habit

Installing the controller with a single copy because “it works in testing”.

What goes wrong

When that pod restarts for an update or its machine fails, the whole front door closes. Every application behind it goes offline together, even though each application is perfectly healthy.

Better approach

Run at least two or three copies on different machines and zones, add a disruption budget so updates never remove them all at once, and let an autoscaler add more under load.

ANTI-PATTERN 02 · Business logic in annotations Avoid
The habit

Piling long custom snippets and dozens of special notes onto an Ingress until it behaves like a small program.

What goes wrong

Nobody can read it, tests are hard to write, and a typo can break routing for everyone. Free-form snippets are also a well-known security risk.

Better approach

Keep the Ingress for routing and TLS. Put real logic, such as authentication rules or data transformation, in the application or a proper API gateway.

ANTI-PATTERN 03 · Wildcard catch-all with no ownership Avoid
The habit

Letting any team claim any host and path in a shared cluster.

What goes wrong

Two teams claim the same address, traffic silently goes to the wrong place, and a malicious or careless user can steal another team’s traffic.

Better approach

Give each namespace a fixed set of host names it may use, enforce this with admission policies, and review rule changes like code.

13Best Practices and Common Mistakes

These habits come from many teams running Ingress in production. Follow them and you will avoid most of the midnight phone calls.

1

Always set the class

Name the IngressClass explicitly so the right controller, and only that controller, picks up each rule.

2

Automate certificates

Use a tool that renews them for you and alert when any certificate has fewer than two weeks left.

3

Add readiness checks

Every application should tell Kubernetes when it is truly ready, so traffic never reaches a half-started pod.

4

Size and spread the controller

Several replicas, several zones, sensible resource limits and an autoscaler.

5

Set timeouts and body limits

Decide how long a request may take and how large an upload may be. Defaults are rarely right for your application.

6

Keep rules in version control

Treat routing changes like code: review them, test them in a staging cluster, and roll them back easily.

7

Patch the controller promptly

Follow its security notices and rehearse upgrades regularly so they never feel scary.

Common mistakes and their cures

MistakeWhat you seeCure
No controller installedThe Ingress exists but its address stays empty foreverInstall a controller and set the matching class
Wrong class nameRules are ignored, or two controllers fightMatch the class on the Ingress to the controller’s class
Wrong service portVisitors get a gateway error such as 502 or 503Point the rule at the port the service actually exposes
Prefix path confusionSome paths land on the wrong serviceRemember matching works on whole path pieces, and test edge cases
Missing DNS recordThe rules are perfect but the website name does not resolvePoint the name at the load balancer’s address
Upload failsLarge files return an error after a short waitRaise the request body size limit and timeouts on that route only
Redirect loopThe browser complains the page redirected too many timesMake sure the controller and any load balancer in front agree on which side handles HTTPS
i
A debugging order that works

Check from the outside in: does DNS resolve, does the load balancer answer, does the controller pod run, does the rule show an address, does the service have ready pods? Following the request’s own path finds the broken link quickly.

14Real-World Usage Stories

Organisations from small start-ups to global enterprises use Ingress. The stories below are simplified illustrations of common situations, not descriptions of any one company’s private setup.

A large online marketplace

Think of a marketplace with the scale of Amazon or Flipkart. Product pages, cart, checkout, reviews and seller tools are owned by different teams. One shared domain with path-based routing lets each team ship its own service on its own schedule, while a CDN absorbs image traffic and the Ingress spreads the remaining requests across hundreds of pods. During a big sale, the controller pods and the application pods are scaled up before the rush.

A software-as-a-service company

A company that sells project-management software gives each customer an address such as acme.company.com. A wildcard host rule and a wildcard certificate serve every customer with one setup. When a new customer signs up, no new load balancer and no new rule is needed, which keeps onboarding instant and cheap.

A bank or healthcare provider

Regulated companies often need encryption everywhere, even inside the cluster. They terminate TLS at the Ingress to apply firewall rules, then re-encrypt to the pods. Internal tools sit behind a private controller and require client certificates. Access logs are kept for auditors.

A streaming or media start-up

A video service keeps the heavy video files on a CDN and uses Ingress only for the website, sign-in and recommendation services. This split keeps the cluster front door light, so the controller pods can be small and cheap even when the audience grows.

An old application being modernised

A ten-year-old application is slowly replaced. At first, all paths go to the old program. Every month, one more path, such as /invoices, is switched to a new small service. Visitors notice nothing, and the old program shrinks until it can be switched off. Ingress makes this quiet migration possible.

i
Big picture

Across all these stories the same principle repeats: keep the door simple, put shared concerns such as HTTPS and rate limits at the door, and let the applications behind it focus on their own jobs.

15Frequently Asked Questions

Q1Is Ingress the same thing as a load balancer?
Not exactly. A load balancer spreads traffic across servers. Ingress is a set of routing rules, and the Ingress controller behind it often acts as a smart load balancer that understands web addresses. In the cloud, a network-level load balancer usually sits in front of the controller as well.
Q2What is the difference between Ingress and a LoadBalancer service?
A LoadBalancer service creates one dedicated external load balancer for one service and does not read web addresses. Ingress shares one entry point among many services and routes by host name and path. Use LoadBalancer for a single non-web service, and Ingress for many web applications.
Q3Can I run more than one Ingress controller in a cluster?
Yes. Give each controller its own IngressClass and mark each Ingress with the class it wants. Many teams run one controller for public traffic and another for private traffic.
Q4Does Ingress support TCP and UDP traffic?
The standard Ingress object does not. It is built for HTTP and HTTPS. Some controllers add extras for raw TCP or UDP, and the Gateway API includes standard route types for them. Otherwise, use a LoadBalancer service.
Q5How is Ingress different from an API gateway?
Ingress focuses on getting outside traffic to the right service. An API gateway adds business-level features such as API keys, usage plans, request transformation and developer portals. Some controllers, such as Kong, blur the line by offering both.
Q6Should I move from Ingress to Gateway API?
Not in a hurry. If your Ingress setup is stable, it will keep working. For new platforms, or when many teams need to share one entry point safely, Gateway API offers a cleaner design. Check that your chosen controller supports it well.
Q7Do I still need a cloud load balancer in front of the controller?
In a cloud, yes, in nearly all cases, because it provides the public address and spreads traffic across controller pods. On your own servers without a cloud, teams use tools such as MetalLB or an external hardware or software load balancer for the same job.
Q8Why is the address of my Ingress empty?
Common reasons: no controller is installed, the class does not match any controller, or the cloud is still creating the load balancer. Look at the events on the Ingress object and at the controller pod’s logs for the exact reason.
Q9How many controller replicas should I run?
A good starting point is two or three, on different machines and zones, then add an autoscaler based on processor use or request rate. Watch the saturation metrics from Chapter 11 and adjust with real numbers.
Q10Do WebSockets and long-lived connections work through Ingress?
Most controllers support them, but default timeouts are often short. Raise the timeout on the specific route that carries chat, live dashboards or streaming so idle connections are not cut off.

16Summary and Key Takeaways

Key Takeaways

  • Ingress is a rule book, not a program. The rules live in the Ingress object, and an Ingress controller reads them and moves the traffic.
  • It replaces many front doors with one. One shared entry point routes by host name and path, cutting cost and address sprawl compared with a load balancer per service.
  • Web traffic only. Ingress handles HTTP and HTTPS. Raw TCP and UDP need a LoadBalancer service, controller extras or Gateway API.
  • TLS belongs at the door. Terminate encryption at the controller, automate certificate renewal, and watch expiry dates.
  • Protect the controller. It sees every request, so patch it quickly, avoid free-form snippets and control who may write rules.
  • Run it like production infrastructure. Several replicas across zones, readiness checks, metrics on rate, errors, latency and saturation, and centralised logs.
  • Know the road ahead. Ingress is stable and widely used, while Gateway API is the more expressive successor. Choose a well-maintained controller and check its support status before building on it.