Skip to main content
ContainersAdvanced

Understanding Kubernetes Networking: Services, Ingress, and DNS

Deep dive into Kubernetes networking — ClusterIP, NodePort, LoadBalancer, Ingress controllers, CoreDNS, and Network Policies explained with examples.

N
Neeraj Jha
·Updated September 11, 2026·5 min read
Understanding Kubernetes Networking: Services, Ingress, and DNS

Kubernetes networking can feel overwhelming. Every Pod gets its own IP, Services provide stable endpoints, and Ingress routes external HTTP traffic. This guide breaks down how all the pieces fit together.

The Kubernetes Network Model

Kubernetes enforces three fundamental rules:

  1. Every Pod gets a unique IP address
  2. Pods on any node can communicate with Pods on any other node without NAT
  3. Agents on a node can communicate with all Pods on that node

This flat network model simplifies application design but requires a CNI (Container Network Interface) plugin to implement — Calico, Cilium, Flannel, and Weave are popular choices.

Service Types

Services abstract a set of Pods behind a stable IP and DNS name.

ClusterIP (default)

yaml
apiVersion: v1
kind: Service
metadata:
  name: api-service
spec:
  type: ClusterIP
  selector:
    app: api
  ports:
    - port: 80
      targetPort: 3000

Only reachable from inside the cluster. Other Pods access it at api-service.default.svc.cluster.local or just api-service within the same namespace.

NodePort

yaml
spec:
  type: NodePort
  ports:
    - port: 80
      targetPort: 3000
      nodePort: 30080

Exposes the service on every node's IP at port 30080. Useful for development or when you manage your own load balancer.

LoadBalancer

yaml
spec:
  type: LoadBalancer
  ports:
    - port: 80
      targetPort: 3000

Provisions a cloud load balancer (AWS ELB, GCP LB, etc.) that routes external traffic to the service. Each LoadBalancer service gets its own external IP, which can be expensive at scale.

Ingress Controllers

Instead of one LoadBalancer per service, use an Ingress controller to route HTTP traffic based on hostname and path.

Installing nginx-ingress

bash
helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
helm install ingress-nginx ingress-nginx/ingress-nginx

Defining Ingress Rules

yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: app-ingress
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  ingressClassName: nginx
  tls:
    - hosts:
        - app.example.com
      secretName: app-tls
  rules:
    - host: app.example.com
      http:
        paths:
          - path: /api
            pathType: Prefix
            backend:
              service:
                name: api-service
                port:
                  number: 80
          - path: /
            pathType: Prefix
            backend:
              service:
                name: frontend-service
                port:
                  number: 80

One LoadBalancer, multiple services, TLS termination — all managed declaratively.

CoreDNS

CoreDNS is the default DNS server in Kubernetes. It provides service discovery:

RecordResolves To
my-svc.my-ns.svc.cluster.localClusterIP of the service
pod-ip.my-ns.pod.cluster.localIndividual Pod IP
my-svc.my-ns.svc.cluster.local SRVPort and hostname of backing Pods

You can customize CoreDNS with a ConfigMap:

yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: coredns
  namespace: kube-system
data:
  Corefile: |
    .:53 {
        errors
        health
        kubernetes cluster.local in-addr.arpa ip6.arpa {
           pods insecure
           fallthrough in-addr.arpa ip6.arpa
        }
        forward . /etc/resolv.conf
        cache 30
        reload
    }

Network Policies

By default, all Pods can talk to all other Pods. Network Policies restrict traffic:

yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: api-netpol
spec:
  podSelector:
    matchLabels:
      app: api
  policyTypes:
    - Ingress
    - Egress
  ingress:
    - from:
        - podSelector:
            matchLabels:
              app: frontend
      ports:
        - port: 3000
  egress:
    - to:
        - podSelector:
            matchLabels:
              app: database
      ports:
        - port: 5432

This policy allows the API Pod to receive traffic only from the frontend and send traffic only to the database.

Debugging Networking Issues

bash
# Check service endpoints
kubectl get endpoints api-service

# DNS lookup from inside a Pod
kubectl exec -it debug-pod -- nslookup api-service.default.svc.cluster.local

# Test connectivity
kubectl exec -it debug-pod -- curl -v http://api-service:80/health

# View Ingress controller logs
kubectl logs -n ingress-nginx deployment/ingress-nginx-controller

Summary

ComponentPurpose
ClusterIPInternal service discovery
NodePortDevelopment / bare-metal exposure
LoadBalancerCloud external access (one per service)
IngressHTTP routing, TLS, path-based (shared LB)
CoreDNSService name resolution
NetworkPolicyPod-to-pod traffic control

Master these building blocks and Kubernetes networking becomes predictable instead of magical.

Enjoyed this article?

Get more DevOps insights delivered to your inbox.

Get new posts by email

Subscribe to get an email when a new blog post is published. Skip anytime.

No spam, unsubscribe anytime.

N

Written by

Neeraj Jha

Platform administrator and lead writer.

View all posts

Discussion

0 comments

Sign in to join the conversation.

Be the first to comment

Start a conversation about this post

Share: