Services and Ingress
In a Kubernetes ecosystem, Pods are the fundamental unit of deployment, but they are inherently ephemeral. They are frequently created, destroyed, and rescheduled, meaning their IP addresses are constantly changing. To build a reliable distributed system, you cannot rely on direct Pod-to-Pod communication via IP addresses. This is where Service and Ingress come into play.
While both concepts are used to expose applications and route traffic, they operate at different layers of the networking stack and serve distinct purposes. Understanding the nuances between them is essential for designing scalable and cost-effective cluster architectures.
A Service is a Kubernetes abstraction that defines a logical set of Pods and a policy by which to access them. Instead of tracking individual Pod IPs, other components in the cluster communicate with the Service's stable IP address or DNS name. The Service uses Label Selectors to identify the group of Pods it should direct traffic toward, ensuring that even if Pods are replaced, the connection remains seamless.
Kubernetes provides several Service types to handle different networking requirements:
- ClusterIP (Default): This type exposes the Service on a cluster-internal IP. It is only reachable from within the cluster, making it the standard choice for internal microservices communication.
- NodePort: This exposes the Service on a specific port across every Node in the cluster. External traffic can reach the service by hitting
<NodeIP>:<NodePort>. While useful for testing, it is often difficult to manage at scale due to port conflicts and security concerns. - LoadBalancer: Designed for cloud environments, this type integrates with cloud provider load balancers (such as AWS ELB, Azure LB, or GCP LB). It automatically provisions a public-facing load balancer that routes traffic to your Service, making it the most common way to expose services to the internet in production.
- ExternalName: Instead of selecting Pods via labels, this type maps a Service to a DNS name (e.g., an external database endpoint), allowing internal Pods to access external resources using a local Kubernetes DNS name.
Example: ClusterIP Configuration
The following YAML demonstrates a standard ClusterIP Service that routes traffic to Pods labeled with app: my-app.
apiVersion: v1
kind: Service
metadata:
name: my-app-service
spec:
selector:
app: my-app
ports:
- protocol: TCP
port: 80
targetPort: 8080
type: ClusterIP
The Role of Ingress
While NodePort and LoadBalancer can expose services to the outside world, they have significant drawbacks in complex environments. Using a LoadBalancer service for every single microservice is prohibitantly expensive and operationally heavy, as each one consumes a unique cloud IP and load balancer instance.
Ingress solves this problem by acting as a smart entry point for the cluster. Unlike a Service, Ingress is not a standalone networking object that manages traffic itself; rather, it is a collection of routing rules for HTTP and HTTPS traffic.
To function, Ingress requires two distinct components:
- Ingress Controller: This is the "engine" of the operation. It is a specialized Pod (often running Nginx, Traefik, or HAProxy) that constantly monitors the Kubernetes API for Ingress resources and implements the routing logic.
- Ingress Resource: This is the configuration object where you define your routing rules, such as which domain name or URL path should point to which backend Service.
By using Ingress, you can consolidate multiple services under a single IP address and a single entry point, using Host-based routing (e.g., api.example.com vs web.example.com) or Path-based routing (e.g., /shop vs /blog).
Example: Ingress Resource Configuration
The following example shows how an Ingress resource can route traffic to two different services based on the URL path.
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: example-ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
rules:
- host: myapp.example.com
http:
paths:
- path: /shop
pathType: Prefix
backend:
service:
name: shop-service
port:
number: 80
- path: /blog
pathType: Prefix
backend:
service:
name: blog-service
port:
number: 80
In this setup, a single Ingress Controller manages all incoming traffic for myapp.example.com. It intelligently directs /shop requests to the shop-service and /blog requests to the blog-service.
Service vs. Ingress: How They Work Together
It is a mistake to view Service and Ingress as competing technologies. In a well-architected cluster, they work in tandem to create a multi-layered networking stack.
The Layered Approach
The fundamental difference lies in the OSI Model layers they operate on:
- Service (Layer 4): Operates primarily at the Transport Layer (TCP/UDP). It handles connection-level load balancing and ensures that traffic reaches the correct set of Pods based on IP and port.
- Ingress (Layer 7): Operates at the Application Layer (HTTP/HTTPS). It provides advanced features like SSL/TLS termination, header manipulation, cookie-based affinity, and sophisticated URL routing.
The Traffic Flow
When an external user makes a request to your application, the journey typically looks like this:
- External Request: The user hits the public IP of the Ingress Controller.
- L7 Routing: The Ingress Controller inspects the HTTP request (the Host header or the URL path) and matches it against the Ingress Resource rules.
- L4 Forwarding: Once the rule is matched, the Ingress Controller forwards the traffic to the designated Service (usually via its
ClusterIP). - Pod Delivery: The Service then routes the traffic to one of the healthy Pods associated with its selector.
Summary
Choosing between Service and Ingress depends on your specific requirements:
- Use Service (ClusterIP) for internal communication between microservices.
- Use Service (LoadBalancer) when you need a simple, direct way to expose a single service to the internet via a cloud provider.
- Use Ingress when you are managing multiple services, require advanced HTTP routing, need to manage SSL certificates centrally, or want to optimize costs by using a single entry point for your entire application suite.
Mastering the synergy between these two components is the key to building a robust, production-ready Kubernetes network.