ClusterIP — The Internal Backbone of Kubernetes Service Discovery
What is ClusterIP in Simple Terms?
Pods are temporary — they get new IP addresses every time they restart. ClusterIP gives your service a permanent internal address that never changes. Other pods always connect to this stable ClusterIP and Kubernetes handles routing to the actual pods behind it.
Service Types Comparison
◈ DIAGRAM
+---------------+--------------------------------------------------+| Type | Accessibility |+---------------+--------------------------------------------------+| ClusterIP | Internal only — accessible only inside cluster || NodePort | Opens a port on every node — external access || LoadBalancer | Creates a cloud load balancer — full external || ExternalName | Maps to an external DNS name |+---------------+--------------------------------------------------+How ClusterIP Routes Traffic
◈ DIAGRAM
+---------------------+ +----------------------+| payments-api pod | | ClusterIP Service || (10.244.1.20) | | (10.96.45.200:4000)|+---------------------+ +----------------------+ | +---------------------------+---------------------------+ | | | v v v+---------------------+ +---------------------+ +---------------------+| payments pod | | payments pod | | payments pod || 10.244.1.21:4000 | | 10.244.2.15:4000 | | 10.244.3.8:4000 |+---------------------+ +---------------------+ +---------------------+kube-proxy manages iptables rules on every node to distribute traffic across the pods behind the ClusterIP.
Example ClusterIP Service
YAML
# service.yaml — internal service for the payments APIapiVersion: v1kind: Servicemetadata: name: payments-service namespace: productionspec: type: ClusterIP # Default — no need to specify explicitly selector: app: payments-api # Routes to pods with this label ports: - protocol: TCP port: 4000 # Port the service listens on targetPort: 4000 # Port the container actually runs onHow to Inspect a ClusterIP Service
Bash
# Get service details including the assigned ClusterIPkubectl get service payments-service -n production # Output:# NAME TYPE CLUSTER-IP PORT(S) AGE# payments-service ClusterIP 10.96.45.200 4000/TCP 5d # See which pods are backing this service via endpointskubectl get endpoints payments-service -n production # Full describe for troubleshootingkubectl describe service payments-service -n productionTroubleshooting ClusterIP
| Symptom | Likely Cause | Fix |
|---|---|---|
| Connection refused on ClusterIP | No pods match the selector | Check kubectl get endpoints — empty means label mismatch |
| ClusterIP unreachable from outside | Expected — it is internal only | Use kubectl port-forward for local debugging |
| Intermittent failures | Some pods are unhealthy | Check pod readiness probes |
| DNS name not resolving | CoreDNS issue | Run kubectl exec -it <pod> -- nslookup payments-service.production |
Bash
# Debug ClusterIP connectivity from inside a podkubectl exec -it debug-pod -n production -- curl http://payments-service.production:4000/health # Temporarily expose ClusterIP to local machine for debuggingkubectl port-forward service/payments-service 4000:4000 -n productionREMEMBER THIS**Remember:** ClusterIP addresses are virtual — they exist only in iptables rules managed by kube-proxy. You cannot ping a ClusterIP directly from outside the cluster.
PLACEMENT PRO TIP**Tip:** Use `kubectl port-forward service/payments-service 4000:4000 -n production` to temporarily expose a ClusterIP service to your local machine for debugging without changing the service type.
COMMON MISTAKE / WARNING**Common Mistake:** Changing the `port` value in a service spec without updating all internal consumers. Every other service or pod that calls `payments-service:4000` will break immediately. Always treat ClusterIP port values as a contract between services in production at Razorpay or PhonePe scale.