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
+---------------+--------------------------------------------------+| 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
+---------------------+ +----------------------+| 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
1# service.yaml — internal service for the payments API2apiVersion: v13kind: Service4metadata:5 name: payments-service6 namespace: production7spec:8 type: ClusterIP # Default — no need to specify explicitly9 selector:10 app: payments-api # Routes to pods with this label11 ports:12 - protocol: TCP13 port: 4000 # Port the service listens on14 targetPort: 4000 # Port the container actually runs onHow to Inspect a ClusterIP Service
1# Get service details including the assigned ClusterIP2kubectl get service payments-service -n production3 4# Output:5# NAME TYPE CLUSTER-IP PORT(S) AGE6# payments-service ClusterIP 10.96.45.200 4000/TCP 5d7 8# See which pods are backing this service via endpoints9kubectl get endpoints payments-service -n production10 11# Full describe for troubleshooting12kubectl 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 |
1# Debug ClusterIP connectivity from inside a pod2kubectl exec -it debug-pod -n production -- curl http://payments-service.production:4000/health3 4# Temporarily expose ClusterIP to local machine for debugging5kubectl port-forward service/payments-service 4000:4000 -n production📌 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.
💡 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: Changing theportvalue in a service spec without updating all internal consumers. Every other service or pod that callspayments-service:4000will break immediately. Always treat ClusterIP port values as a contract between services in production at Razorpay or PhonePe scale.