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:

  1. 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.
  2. 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:

  1. External Request: The user hits the public IP of the Ingress Controller.
  2. L7 Routing: The Ingress Controller inspects the HTTP request (the Host header or the URL path) and matches it against the Ingress Resource rules.
  3. L4 Forwarding: Once the rule is matched, the Ingress Controller forwards the traffic to the designated Service (usually via its ClusterIP).
  4. 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.