SaveMyCert
Log in
5 of 5 free questions left today·for unlimited practice
Container Orchestration

Kubernetes Networking: Services, kube-proxy, CNI, DNS, and Ingress

12 min readKCNA · Container OrchestrationUpdated

Kubernetes networking follows one flat model: every Pod receives its own IP address, and any Pod can reach any other Pod in the cluster without network address translation (NAT). On top of that foundation, Services give groups of Pods a stable virtual IP and DNS name, kube-proxy programs the rules that make those virtual IPs work, CoreDNS resolves service names, and Ingress routes external HTTP traffic to the right Service. The layer below the model, assigning Pod IPs and wiring nodes together, is delegated to a Container Network Interface (CNI) plugin such as Calico, Cilium, or Flannel. For the KCNA exam you need recognition-level command of this stack: what each component does, which Service type fits a given situation, and how a NetworkPolicy flips a Pod from accepting all traffic to denying everything not explicitly allowed. This lesson walks the path traffic takes so each component has an obvious place.

What you’ll learn
  • Explain the Kubernetes flat network model and the no-NAT rule for Pod-to-Pod traffic
  • Distinguish ClusterIP, NodePort, LoadBalancer, headless, and ExternalName Services
  • Describe how kube-proxy and CoreDNS together make a Service reachable by name
  • Identify the role of the CNI and recognize plugins such as Calico, Cilium, and Flannel
  • Contrast Ingress with Services and explain why an Ingress needs an Ingress controller
  • State how NetworkPolicies change a Pod from default-allow to default-deny

The Kubernetes network model: one flat network

Kubernetes imposes a small set of networking rules and leaves the implementation to plugins. The rules: every Pod gets its own cluster-wide IP address; every Pod can communicate with every other Pod, on any node, without NAT; and agents on a node, such as the kubelet, can reach all Pods on that node. The result is one flat network in which Pods behave like small hosts with real addresses.

This is deliberately different from the classic single-host Docker model, where containers hide behind the host IP and you publish ports with flags like -p 8080:80. In Kubernetes there is no port mapping between Pods: a container listening on port 8080 is reachable at its Pod IP on port 8080 from anywhere in the cluster. Containers in the same Pod share one network namespace, so they share the Pod IP and talk to each other over localhost, which also means two containers in one Pod cannot bind the same port.

The flat model keeps application configuration simple, but Pod IPs are ephemeral. When a Pod is evicted, rescheduled, or replaced during a Deployment rollout, its replacement comes up with a new IP. Nothing in the cluster should hard-code a Pod IP. That instability is the problem Services exist to solve, and it is the thread that connects everything else in this lesson: Services give the flat network stable names, and Ingress and NetworkPolicies shape what is allowed to flow across it.

CNI: the plugin that actually wires Pod networking

Kubernetes defines the network model but does not implement it. That job belongs to a Container Network Interface (CNI) plugin. CNI is a CNCF specification: when the kubelet asks the container runtime to create a Pod, the configured CNI plugin is invoked to attach the Pod to the network, assign it an IP address from the cluster's Pod address range, and set up the routes or tunnels that let Pods on different nodes reach each other without NAT.

For KCNA you need recognition-level knowledge of the common plugins, not their internals:

  • Flannel: a simple overlay network focused on basic Pod-to-Pod connectivity. It does not enforce NetworkPolicies on its own.
  • Calico: a widely used plugin that provides routed networking and full NetworkPolicy enforcement, and can extend policy features beyond the built-in API.
  • Cilium: built on eBPF in the Linux kernel, offering networking, NetworkPolicy enforcement, and deep observability of traffic flows.

Two exam-relevant consequences follow. First, a cluster without a working CNI plugin cannot run normal workloads: nodes stay not ready and new Pods never receive IP addresses. Second, NetworkPolicy is enforced by the CNI plugin, not by Kubernetes itself, so creating a NetworkPolicy object in a cluster whose plugin ignores policies changes nothing. If a question asks which component assigns Pod IPs or implements the network model, the answer is the CNI plugin, not kube-proxy and not the kube-apiserver.

Services: a stable front door for ephemeral Pods

A Service gives a set of Pods a single stable virtual IP (the ClusterIP) and a DNS name that outlive any individual Pod. The Service finds its Pods with a label selector: every ready Pod whose labels match becomes an endpoint, and Kubernetes tracks those Pod IPs in EndpointSlice objects that update automatically as Pods come and go. Clients talk to the Service address; they never need to know which Pods are behind it right now.

apiVersion: v1
kind: Service
metadata:
  name: api
spec:
  selector:
    app: api
  ports:
    - port: 80
      targetPort: 8080

Here anything in the cluster can call the api Service on port 80, and the traffic is delivered to port 8080 on one of the matching Pods. Traffic is spread across the ready endpoints roughly evenly.

kube-proxy is the component that makes the virtual IP work. It runs on every node, watches the API server for Services and EndpointSlices, and programs the node's packet-handling rules, using iptables by default or IPVS, so that a connection to the ClusterIP is rewritten to go to a real Pod IP. Despite its name, kube-proxy does not sit in the data path passing packets along in userspace in modern clusters; it programs the kernel rules and the kernel forwards the traffic. On the exam, kube-proxy is the answer to which node component implements Services.

Service types compared: ClusterIP, NodePort, LoadBalancer, and friends

Every Service has a type, and the first three types build on each other. Choosing among them is a classic KCNA question, so learn them as a ladder of exposure:

TypeReachable fromHow it worksTypical use
ClusterIP (default)Inside the cluster onlyVirtual IP programmed by kube-proxyInternal service-to-service traffic
NodePortOutside, via any node IPOpens the same port (default range 30000-32767) on every node, on top of a ClusterIPSimple external access, dev and test
LoadBalancerOutside, via one external IPAsks the cloud provider to provision a load balancer that forwards to the ServiceProduction external exposure on a cloud

Two more variants appear at recognition depth. A headless Service sets clusterIP: None: no virtual IP is allocated and no load balancing happens; instead, DNS returns the individual Pod IPs directly. StatefulSets use headless Services so each Pod gets its own stable DNS name, which matters for databases where clients must address a specific replica. An ExternalName Service has no selector and no Pod endpoints at all; it simply returns a DNS CNAME record pointing at an external hostname, letting in-cluster clients use a consistent internal name for something outside the cluster.

Remember the dependency direction: LoadBalancer includes NodePort behavior, and NodePort includes ClusterIP behavior. A LoadBalancer Service on a bare-metal cluster with no provider integration stays pending, because there is no cloud to provision the load balancer.

Cluster DNS: CoreDNS and service discovery

Stable virtual IPs are only half of service discovery; the other half is names. Every conformant cluster runs a DNS server, and CoreDNS is the standard choice. It runs as a Deployment in the kube-system namespace, is exposed through a Service (traditionally named kube-dns), and every Pod's DNS configuration is pointed at it automatically. When you create a Service, CoreDNS starts answering for it immediately.

The naming pattern is fixed and worth memorizing: a Service named api in namespace shop resolves at the fully qualified name api.shop.svc.cluster.local. Pods in the same namespace can use the short name api; Pods in other namespaces must include the namespace, such as api.shop. This is why application configuration in Kubernetes references service names rather than IP addresses: the name survives every Pod restart and even deletion and re-creation of the Service.

DNS behavior also changes with the Service type. A normal ClusterIP lookup returns the single virtual IP. A headless Service lookup returns the set of Pod IPs, one record per ready Pod. An ExternalName lookup returns a CNAME to the configured external hostname. For the exam, associate CoreDNS with one job: resolving service names inside the cluster. It is not a load balancer, it does not program packet rules, and it is not the component that assigns Pod IPs.

Ingress: HTTP routing into the cluster

Exposing one Service externally is what NodePort and LoadBalancer do. But a real platform hosts many HTTP applications, and paying for one cloud load balancer per Service scales badly. Ingress solves this at layer 7: it is an API object holding HTTP routing rules that map hostnames and URL paths to Services, and it can terminate TLS. One external entry point can serve shop.example.com and blog.example.com, or route /api and /static to different Services.

The critical exam fact: an Ingress object does nothing by itself. It is only configuration. A cluster must run an Ingress controller, such as ingress-nginx, Traefik, HAProxy, or a cloud provider's controller, which watches Ingress objects and configures an actual proxy to implement the rules. Create an Ingress in a cluster with no controller and traffic goes nowhere.

AspectServiceIngress
LayerLayer 4, TCP and UDPLayer 7, HTTP and HTTPS
Routing based onPortsHostnames and URL paths
TLS terminationNoYes
Needs extra componentNo, kube-proxy is built inYes, an Ingress controller

Concrete scenario: a user requests https://shop.example.com/api/cart. DNS points at a cloud load balancer created for the Ingress controller's own Service. The controller terminates TLS, matches the host and the /api path prefix against Ingress rules, and forwards the request to the api ClusterIP Service, whose kube-proxy rules deliver it to a ready Pod. Kubernetes is also evolving the Gateway API as the more expressive successor to Ingress; for KCNA, recognizing that direction is enough.

NetworkPolicies: from default-allow to default-deny

The flat network model is maximally open: by default, every Pod accepts traffic from every other Pod in the cluster. NetworkPolicy is the namespaced API object that restricts this. A policy selects Pods with a podSelector and then lists the ingress sources or egress destinations that remain allowed, expressed as Pod selectors, namespace selectors, or IP blocks.

The behavior switch is the single most tested fact here. A Pod selected by no NetworkPolicy accepts everything: default-allow. The moment any policy selects a Pod, that Pod becomes default-deny for the traffic directions the policy covers, and only what some policy explicitly allows gets through. Policies are additive; multiple policies selecting the same Pod combine into the union of their allow rules, and there is no deny rule to write. An empty podSelector selects every Pod in the namespace, which is how the common default-deny baseline is written:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default-deny-ingress
  namespace: shop
spec:
  podSelector: {}
  policyTypes:
    - Ingress

Scenario: the shop namespace runs a frontend, an api, and a database. After applying the default-deny policy above, nothing in the namespace accepts inbound traffic. You then add one policy allowing Pods labeled app: frontend to reach app: api, and another allowing app: api to reach app: db on port 5432. A compromised frontend Pod can no longer talk to the database directly, because no policy allows that path. Remember also that enforcement depends on the CNI plugin: Calico and Cilium enforce policies, plain Flannel does not.

Putting it together: which component owns which job

KCNA networking questions are almost always about ownership: which piece of the stack is responsible for a given behavior. Fix the following mapping and most questions become elimination exercises.

  • CNI plugin (Calico, Cilium, Flannel): implements the flat network model, assigns Pod IPs, connects nodes, and enforces NetworkPolicies where supported.
  • Service: a stable virtual IP and name for a labeled set of Pods; the object you create.
  • kube-proxy: the per-node agent that programs iptables or IPVS rules so Service IPs actually deliver traffic to Pod endpoints.
  • CoreDNS: resolves service.namespace.svc.cluster.local names to Service or Pod IPs.
  • Ingress controller: the layer 7 proxy that implements Ingress host and path routing and TLS termination.
  • NetworkPolicy: the API object that restricts Pod traffic; inert until a CNI plugin enforces it.

Trace one full journey to cement it. A Pod calls api.shop: CoreDNS resolves the name to a ClusterIP; kernel rules programmed by kube-proxy rewrite the connection to a healthy Pod endpoint from the EndpointSlice; the packet crosses nodes over routes the CNI plugin set up, without NAT between Pods; and if a NetworkPolicy selects the destination Pod, the CNI plugin permits the connection only if some rule allows this source. External HTTP traffic simply adds the Ingress controller in front of the same chain. Every exam option that assigns one component another component's job is wrong by definition.

Tip. KCNA tests networking as component-to-job matching: expect questions like which component implements Services (kube-proxy), which assigns Pod IPs (the CNI plugin), which resolves service names (CoreDNS), and which object routes HTTP by host and path (Ingress, which needs a controller). Trigger words include flat network, without NAT, ClusterIP, NodePort range, headless, CNAME, and default-allow versus default-deny. Scenario stems often ask you to pick the right Service type for a described exposure need, or to predict what happens once a NetworkPolicy selects a Pod.

Key takeaways
  • Every Pod gets its own IP address, and Pods communicate across nodes without NAT; that flat model is implemented by the CNI plugin, not by Kubernetes itself.
  • A Service provides a stable virtual IP and DNS name in front of ephemeral Pods, selected by labels and tracked through EndpointSlices.
  • kube-proxy runs on every node and programs iptables or IPVS rules that make Service IPs deliver traffic to real Pod endpoints.
  • ClusterIP is internal-only and the default; NodePort opens a high port (30000-32767) on every node; LoadBalancer provisions a cloud load balancer on top of NodePort.
  • A headless Service (clusterIP: None) returns Pod IPs directly in DNS; ExternalName returns a CNAME to an outside hostname.
  • CoreDNS resolves names like api.shop.svc.cluster.local; short names work within the same namespace.
  • Ingress defines layer 7 host and path routing but does nothing without an Ingress controller; the Gateway API is its emerging successor.
  • Pods are default-allow until a NetworkPolicy selects them; then everything not explicitly allowed in the covered direction is denied, and enforcement requires a CNI plugin that supports policies.

Frequently asked questions

What is the difference between a Service and an Ingress in Kubernetes?

A Service works at layer 4: it gives a set of Pods one stable IP and DNS name and spreads TCP or UDP traffic across them. An Ingress works at layer 7: it holds HTTP routing rules that map hostnames and URL paths to Services and can terminate TLS. A Service functions on its own through kube-proxy, while an Ingress is only configuration and requires an Ingress controller such as ingress-nginx or Traefik to take effect. In practice they combine: an Ingress routes external HTTP requests to ClusterIP Services.

What does kube-proxy actually do?

kube-proxy is an agent that runs on every node and implements Services. It watches the API server for Services and EndpointSlices and programs the node's packet-handling rules, using iptables by default or IPVS, so that connections to a Service's virtual IP are redirected to one of the ready Pod endpoints. In modern clusters it does not forward packets itself in userspace; the kernel rules it programs do the forwarding. It does not assign Pod IPs and it does not resolve DNS names.

Why does Kubernetes need a CNI plugin?

Kubernetes defines a network model, in which every Pod has its own IP and Pods communicate without NAT, but deliberately does not implement it. A Container Network Interface (CNI) plugin such as Calico, Cilium, or Flannel does the actual work: assigning each Pod an IP address, connecting Pods across nodes, and, where supported, enforcing NetworkPolicies. Without a working CNI plugin, nodes remain not ready and new Pods never receive IP addresses, so ordinary workloads cannot run.

Are NetworkPolicies enabled by default in Kubernetes?

No policy exists by default, so all Pod-to-Pod traffic is allowed: Kubernetes clusters start default-allow. A Pod only becomes restricted once at least one NetworkPolicy selects it; from then on, traffic in the directions that policy covers is denied unless some policy explicitly allows it. Enforcement also depends on the CNI plugin: Calico and Cilium enforce NetworkPolicies, while plain Flannel does not, in which case created policies have no effect.

What is a headless Service used for?

A headless Service is created by setting clusterIP: None. Kubernetes allocates no virtual IP and does no load balancing; instead, a DNS lookup of the Service name returns the IP addresses of the individual ready Pods. This is used when clients need to reach specific Pods rather than any interchangeable replica, most notably with StatefulSets, where each Pod gets its own stable DNS name, as required by databases and other clustered stateful systems.

Test yourself on this topic
Practice questions with full explanations.
Practice now

Sign up free to mark lessons complete, bookmark topics and track your exam readiness.