Hello! Welcome to the next lesson in our journey through Kubernetes.
In our last session, we explored how to expose applications using Kubernetes Services. We saw that ClusterIP is perfect for internal communication, NodePort is useful for development, and LoadBalancer is the standard for exposing a single service to the internet in a cloud environment. However, we ended with a critical question for production systems: What if you have dozens of microservices? Creating a LoadBalancer for each one would be slow, complex to manage, and very expensive.
This lesson introduces the elegant solution to that problem: Kubernetes Ingress. Our goal is to implement HTTP routing to services using an Ingress controller and Ingress resources. Ingress acts as a smart traffic cop for your cluster, allowing you to manage access to all your services through a single entry point and a set of routing rules. This is a foundational concept for exposing microservices in production and a common topic in system design interviews.
The Two Halves of Ingress: Controller and Resource
To understand Ingress, it's crucial to know that it's not a single thing but a system of two components working together:
- Ingress Controller: This is the engine. It's an application (often a sophisticated proxy like NGINX, Traefik, or HAProxy) that runs in your cluster, listens for traffic, and routes it according to a set of rules. You typically install a controller once per cluster.
- Ingress Resource: This is the rulebook. It's a Kubernetes YAML object where you define how traffic should be routed. For example, you might define a rule that says "requests for
api.example.com/usersshould go to theuser-service."
The Ingress Controller constantly watches for Ingress Resources and automatically reconfigures itself to implement the rules you've defined.
Let's look at the big picture.
.webp)
The Ingress Controller: The Brain of the Operation
Before you can define any routing rules, a controller must be running in your cluster. It's the component that actually does the work of routing traffic. Let's get a clearer definition of its role.
Ingress Configuration in Kubernetes: Complete Production Guide
The article 'Ingress Configuration in Kubernetes' provides a great introduction to the core concepts. Let's start there to solidify our understanding of what Ingress is and why it's different from a simple LoadBalancer.
Please read the sections 'Introduction' and 'Ingress Concepts'. Focus on the 'Ingress vs LoadBalancer vs NodePort' table and the 'Ingress Architecture' diagram to understand its role as a Layer 7 router.
As you've read, the key benefit is managing multiple services behind a single IP address with intelligent, application-layer (HTTP/S) routing.
Installing an Ingress controller is typically a one-time setup task for a cluster administrator. While there are several popular options, we'll focus on the NGINX Ingress Controller, which is one of the most widely used.
Ingress Configuration in Kubernetes: Complete Production Guide
To make this more concrete, let's look at how you would install an Ingress controller. You don't need to run these commands, but seeing them helps demystify the process.
Quickly scan the section 'Installing Ingress Controllers', particularly the part on the 'NGINX Ingress Controller'. Notice that it can be installed with a single Helm command or a kubectl apply command. This component, once installed, will typically create a LoadBalancer Service to become the cluster's entry point.
With the controller in place, we can now start defining our routing rules using Ingress resources.
The Ingress Resource: Defining the Rules of the Road
The Ingress resource is where you, as a developer, will spend most of your time. This YAML file tells the Ingress controller how to route traffic. The two primary methods for routing are by the request's path and its hostname.
1. Path-Based Routing
This is the most common pattern for a microservices backend, where a single API domain is split into different services. For example:
GET /api/orders->order-serviceGET /api/products->product-service
Let's examine the YAML for path-based routing.
High Availability and Scalability deployment Microservices ...
Let's turn to a practical example that uses path-based routing to expose two different Spring Boot microservices: order-service and item-service.
Read the section 'Routing request to microservices in the Ingress Resource'. Focus on the YAML under the spec.rules section. See how it maps the /order-service path to the mes-order-service Kubernetes Service and /item-service to mes-item-service.
Here is a breakdown of that Ingress resource:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: emc-app-ingress
namespace: microservices
annotations:
# This tells the NGINX controller to strip the routing prefix before forwarding
# e.g., /order-service/orders becomes /orders when it hits the service
nginx.ingress.kubernetes.io/rewrite-target: /$2
spec:
# This specifies which installed Ingress controller should handle this Ingress
ingressClassName: nginx
rules:
# Rules for requests to the host 'mes.app.com'
- host: mes.app.com
http:
paths:
# Rule for the order service
- path: /order-service(/|$)(.*)
pathType: ImplementationSpecific # Allows regex in the path
backend:
service:
name: mes-order-service # The name of the Kubernetes Service
port:
number: 8080 # The port on the Service
# Rule for the item service
- path: /item-service(/|$)(.*)
pathType: ImplementationSpecific
backend:
service:
name: mes-item-service
port:
number: 8080
Notice the backend.service.name field. The Ingress doesn't route to Pods directly. It routes to a Service (which would typically be a ClusterIP type), which then handles load balancing across the actual Pods. This decoupling is a core principle of Kubernetes networking.
2. Host-Based Routing
You can also route traffic based on the hostname (or domain name) in the request. This is useful for hosting completely different applications or tenants in the same cluster.
api.mydomain.com->api-serviceblog.mydomain.com->blog-service
Ingress Configuration in Kubernetes: Complete Production Guide
For a clear example of host-based and even wildcard host routing, let's go back to the 'Ingress Configuration' guide.
Read the section 'Host-Based Routing'. Pay attention to the 'Multiple Hosts Ingress' example, as it clearly shows how different hostnames can be directed to different backend services within the same Ingress resource.
You can, of course, combine both host and path-based routing in the same Ingress resource for very fine-grained control.
Test your understanding!
You are deploying an application with three services:
user-service: Manages user profiles.auth-service: Handles login and authentication.admin-portal: A separate web app for administrators.
You want to configure the following routing:
- Requests to
api.production.com/users/*should go touser-serviceon port 8080. - Requests to
api.production.com/auth/*should go toauth-serviceon port 9000. - Requests to
admin.production.com/*should go toadmin-portal-serviceon port 80.
Write a single Ingress resource YAML to implement this. Assume the ingressClassName is nginx.
Show answer
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: production-routing
spec:
ingressClassName: nginx
rules:
# Rules for the main API
- host: api.production.com
http:
paths:
- path: /users
pathType: Prefix
backend:
service:
name: user-service
port:
number: 8080
- path: /auth
pathType: Prefix
backend:
service:
name: auth-service
port:
number: 9000
# Rule for the admin portal
- host: admin.production.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: admin-portal-service
port:
number: 80
This single resource cleanly separates traffic based on both hostname and path, directing requests to the correct backend services.
Ingress vs. API Gateway: An Important Distinction
In a microservices interview, you might be asked to compare an Ingress with an API Gateway (like Spring Cloud Gateway, which we'll cover later). They seem similar, but they operate at different levels of abstraction.
- Ingress is an infrastructure concern. Its primary job is L7 routing: getting HTTP/S traffic from outside the cluster to the correct service inside the cluster.
- API Gateway is an application concern. It sits between clients and your microservices to handle cross-cutting concerns like authentication/authorization, rate limiting, request/response transformation, and aggregating calls to multiple services.

While you can add some API Gateway-like features to an NGINX Ingress using annotations (as seen in resource LINK, section idx=7), a dedicated API Gateway provides much more powerful and flexible capabilities. A common production pattern is to have an Ingress route all traffic for api.example.com to a single API Gateway service, which then handles the finer-grained routing and policy enforcement for the downstream microservices.
Conclusion
Today we've seen how Kubernetes Ingress provides a powerful and scalable way to manage external access to services. By decoupling the routing rules from the underlying proxy implementation, it gives developers a simple, declarative way to expose their applications.
Key Takeaways:
- Ingress solves the cost and complexity problem of creating a
LoadBalancerfor every service. - It consists of an Ingress Controller (the engine) and Ingress Resources (the declarative rules).
- It enables intelligent L7 routing based on hostname and URL path.
- Ingress is an infrastructure-level router, distinct from an application-level API Gateway, though their functionalities can sometimes overlap.
Now that we can reliably deploy our application (using Deployments), expose it internally (using Services), and route external traffic to it (using Ingress), the next logical step is to manage its configuration. Hardcoding database URLs or feature flags into your container images is a bad practice. In our next lesson, we will learn how to externalize application configuration using ConfigMaps and inject sensitive data using Secrets.
Can't find a good explanation? Sign up and we'll make it for you
Sign up