Skip to content

Service

A Kubernetes Service is an API abstraction that defines a logical set of Pods and a policy to access them, functioning as a stable network gateway for your dynamic workloads. Because Pods are ephemeral and assigned new IP addresses whenever they are recreated, a Service provides a consistent Virtual IP (VIP) and DNS name that persists regardless of changes to the underlying containers. This mechanism decouples frontend clients from backend implementations, automatically load-balancing traffic to healthy Pods that match the Service's selector.

Lets expand on the Service concept. While the above correctly identifies the Service as a stable gateway, understanding the internal mechanics—specifically how it identifies backends and routes traffic—is what allows you to architect resilient systems.

A Service is essentially a continuous reconciliation loop that maps a stable Virtual IP (VIP) to a constantly changing set of Pod IP addresses.

1. The Mechanism: Selectors and EndpointSlices

To understand how a Service finds its backing Pods, you must look at Label Selectors and EndpointSlices.

  • The Label Selector: When you define a Service, you typically define a .spec.selector. This is a query that looks for Pods with specific labels (e.g., app: nginx). The Service controller continuously scans for Pods matching this selector.
  • The Abstraction Layer: The Service does not route traffic directly to the Pods itself. Instead, it maintains a list of valid IP addresses for those Pods.
    • Legacy: In older versions, this list was stored in an object called Endpoints.
    • Modern (EndpointSlices): In current Kubernetes versions, this data is stored in EndpointSlices. EndpointSlices are scalable objects that track the IP addresses, ports, and readiness status of the Pods matching the selector.
  • The Decoupling: If a Pod dies and is replaced, the new Pod gets a new IP. The Service controller detects this, updates the EndpointSlice, and the stable Service IP remains unchanged. Your frontend application continues talking to the Service IP, unaware that the backend Pods have been swapped.

2. Service Discovery: How Clients Find the Service

Once a Service is created, workloads inside the cluster need to know its VIP. Kubernetes provides two primary mechanisms:

  1. DNS (Recommended): Kubernetes runs an internal DNS server (usually CoreDNS). It watches the API for new Services and creates DNS records for them.
    • A Service named my-service in the prod namespace gets a fully qualified domain name (FQDN) of my-service.prod.svc.cluster.local.
    • Pods in the same namespace can simply reach it using the hostname my-service.
  2. Environment Variables: When a Pod starts, the kubelet populates environment variables for all currently active Services. For example, a service named redis-primary would generate variables like REDIS_PRIMARY_SERVICE_HOST inside the container.
    • Constraint: This only works if the Service is created before the Pod starts. Due to this ordering limitation, DNS is the standard for production systems.

3. Service Types: Publishing the Service

The type field in the Service spec dictates how the Service is exposed to the network.

TypeDescriptionUse Case
ClusterIP (Default)Assigns a VIP accessible only from within the cluster. This is the default behavior if no type is specified.Internal communication (e.g., backend API talking to a database).
NodePortExposes the Service on a static port (default range 30000-32767) on every Node's IP address. Traffic sent to <NodeIP>:<NodePort> is routed to the Service.Direct access during development or when an external load balancer is not available.
LoadBalancerProvisions a cloud provider's external load balancer (e.g., AWS ELB, Google Cloud LB). It directs external traffic to the Service.Exposing a public-facing application (e.g., a web server) to the internet.
ExternalNameMaps the Service to a DNS name (CNAME) rather than a VIP. It returns the CNAME record of an external service (e.g., my.database.example.com).Allowing Pods to use a local Kubernetes Service name to reach an external resource seamlessly.

4. Headless Services

Sometimes you do not want load balancing or a single VIP. You might want to communicate directly with specific Pods (e.g., for database replication where you need to reach "Primary" vs. "Replica").

  • Configuration: You define a Service with .spec.clusterIP: "None".
  • Behavior: Kubernetes does not allocate a VIP. Instead, the DNS query for the Service returns a list of A records containing the IP addresses of all the backing Pods directly.
  • Use Case: This is heavily used by StatefulSets to provide stable network identities for individual Pods.

5. Traffic Policies (Advanced Traffic Engineering)

You can fine-tune how traffic is routed to nodes and Pods using traffic policies.

  • External Traffic Policy (externalTrafficPolicy):
    • Cluster (Default): Traffic arriving at a NodePort or LoadBalancer is distributed to any Pod in the cluster. This may involve an extra network hop to a different node, hiding the client's original source IP (Source NAT).
    • Local: Traffic is only sent to Pods running on the same node that received the traffic. This preserves the client's source IP but risks imbalanced traffic if some nodes have no Pods for that Service.
  • Internal Traffic Policy (internalTrafficPolicy):
    • Cluster (Default): Internal traffic is routed to all endpoints evenly.
    • Local: Traffic from a Pod is routed only to endpoints on the same node. This reduces latency and cost (e.g., cross-zone data transfer) but requires a Pod to exist on the local node.