Kubernetes Networking Deep Dive

Kubernetes Services

Demo Service Types

In this guide, you’ll learn about the four primary Kubernetes Service types—ClusterIP, NodePort, Headless, and ExternalName—using a sample NGINX deployment. Understanding these service types will help you expose applications both inside and outside your cluster.

Overview of Service Types

Service TypeScopeUse CaseExample Port
ClusterIPInternal cluster trafficInternal load-balancing80
NodePortNode’s IP + portExternal access via node IP and port30000
HeadlessPod IPs directlyDirect per-pod connectivity (no LB)80
ExternalNameDNS CNAME mappingMap service to external DNS (no proxy)N/A

Before diving in, we’ve deployed three NGINX pods with the label role=nginx in the default namespace:

kubectl get pods
# OUTPUT
# NAME                                  READY   STATUS    RESTARTS   AGE
# nginx-deployment-7ff69d756-8qdv8      1/1     Running   0          3m
# nginx-deployment-7ff69d756-hccjn      1/1     Running   0          3m
# nginx-deployment-7ff69d756-stpmz      1/1     Running   0          3m

1. ClusterIP (Default)

ClusterIP is the Kubernetes default service type. It allocates a virtual IP reachable only within the cluster.

1.1 Service Definition

apiVersion: v1
kind: Service
metadata:
  name: clusterip-svc
  namespace: default
spec:
  type: ClusterIP
  selector:
    role: nginx
  ports:
    - name: http
      port: 80
      targetPort: 80
kubectl apply -f clusterip-svc.yaml
kubectl get svc clusterip-svc
# OUTPUT
# NAME             TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)   AGE
# clusterip-svc    ClusterIP   10.102.157.139   <none>        80/TCP    5m

1.2 Testing Internal Access

Launch a temporary pod to test DNS and HTTP:

kubectl run -i --tty --rm debug --image=curlimages/curl --restart=Never -- sh

Inside the debug pod:

nslookup clusterip-svc.default.svc.cluster.local
curl http://clusterip-svc.default.svc.cluster.local
# Should return the NGINX welcome page

Note

ClusterIP services are only reachable from within the Kubernetes cluster. Use them for internal microservice communication.


2. NodePort

NodePort exposes a Service on each Node’s IP at a static port, allowing external traffic.

2.1 Service Definition

apiVersion: v1
kind: Service
metadata:
  name: nodeport-svc
  namespace: default
spec:
  type: NodePort
  selector:
    role: nginx
  ports:
    - name: http
      port: 80
      targetPort: 80
      nodePort: 30000
kubectl apply -f nodeport-svc.yaml
kubectl get svc nodeport-svc
# OUTPUT
# NAME             TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)         AGE
# nodeport-svc     NodePort    10.98.229.84     <none>        80:30000/TCP    5m

2.2 Access via Node IP

  1. Find a node’s IP address:
    kubectl get node node01 -o jsonpath='{.status.addresses[?(@.type=="InternalIP")].address}'
    # e.g., 192.168.121.156
    
  2. From outside the cluster:
    curl http://192.168.121.156:30000
    
    This should return the NGINX welcome page.

Warning

Ensure that your cloud provider’s firewall or on-premise network allows traffic to the nodePort range (default 30000–32767).

2.3 Internal DNS Resolution

Within the cluster, you can still resolve the service by DNS:

kubectl run -i --tty --rm debug --image=curlimages/curl --restart=Never -- sh
# Inside the pod:
nslookup nodeport-svc.default.svc.cluster.local
curl http://nodeport-svc.default.svc.cluster.local

3. Headless Service

A headless Service omits the cluster IP (clusterIP: None) and returns the IPs of individual pods directly.

3.1 Service Definition

apiVersion: v1
kind: Service
metadata:
  name: headless-svc
  namespace: default
spec:
  clusterIP: None
  selector:
    role: nginx
  ports:
    - name: http
      port: 80
      targetPort: 80
kubectl apply -f headless-svc.yaml
kubectl get svc headless-svc
# OUTPUT
# NAME            TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
# headless-svc    ClusterIP   None         <none>        80/TCP    5m

3.2 DNS and Direct Pod Access

kubectl run -i --tty --rm debug --image=curlimages/curl --restart=Never -- sh

Inside the debug pod:

nslookup headless-svc.default.svc.cluster.local
for ip in $(nslookup headless-svc.default.svc.cluster.local | grep Address | awk '{print $2}'); do
  curl http://$ip
done

Note

Headless Services are ideal for stateful applications (e.g., databases) where you need direct pod access for persistent storage or custom load balancing.


4. ExternalName

ExternalName maps a Service to an external DNS name by returning a CNAME record.

4.1 Service Definition

apiVersion: v1
kind: Service
metadata:
  name: externalname-svc
  namespace: default
spec:
  type: ExternalName
  externalName: httpbin.org
kubectl apply -f externalname-svc.yaml
kubectl get svc externalname-svc
# OUTPUT
# NAME                 TYPE           CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
# externalname-svc     ExternalName   <none>       <none>        <none>    5m

4.2 Testing ExternalName

kubectl run -i --tty --rm debug --image=curlimages/curl --restart=Never -- sh
# Inside the pod:
curl http://externalname-svc.default.svc.cluster.local/get
# This request is forwarded to httpbin.org/get

Note

ExternalName does not proxy traffic through the cluster—it simply performs a DNS CNAME lookup. Use this to reference external APIs or services.


Further Reading & References

Watch Video

Watch video content

Practice Lab

Practice lab

Previous
Service Types