What is a Kubernetes Service?
How does this object help us reach pods?
A service is a Kubernetes object that provides a stable network endpoint for a set of Pods. Pods are ephemeral and can be rescheduled at any time, so their individual IP addresses are unreliable. A service gives us reliability by providing a consistent IP address and DNS name which we can use to reach those pods, regardless of where they’re running.
We can see Kubernetes services as a load balancer that sits in front of our pods. Traffic sent to the service is distributed across the healthy pods that match its label selector.
Kubernetes offers four types of services, and each of them is best suited for a specific use case:
- ClusterIP (default): exposes the service on an internal IP, reachable only from within the cluster (this is what we’d use for internal service-to-service communication);
- NodePort: exposes the service on a static port on each node’s IP, so external traffic can reach it via
<NodeIP>:<NodePort>(useful for development, but not ideal for production since we’d rely on node addresses); - LoadBalancer: provisions an external load balancer (only when running on cloud providers) that routes traffic to the service and is the standard way of exposing a service to the internet on AWS, GCP, or Azure;
- ExternalName: maps a service to a DNS name (e.g.
api.example.com), acting as a CNAME record (useful for referencing external resources as if they were cluster services).
apiVersion: v1kind: Servicemetadata: name: nginx-servicespec: selector: app: nginx ports: - protocol: TCP port: 80 targetPort: 80 type: ClusterIPLet’s have a closer look:
- selector tells the service which pods to target. Here it matches all pods with the label
app: nginx. - port is the port the service itself listens on.
- targetPort is the port on the pod’s container that traffic is forwarded to.
- type defines how the service is exposed (ClusterIP in this case).
The connection between a service and its pods is entirely based on labels. A pod declares labels in its metadata, and the service uses a selector to find pods with matching labels. This allows us to add or remove pods from a service’s pool of pods by simply modifying their labels and never actually modifying the service itself.