This episode maps the division of labor between Flannel for pod networking and kube-proxy for Kubernetes Service. You will test ClusterIP and NodePort on top of Flannel, and understand how the iptables and ipvs modes work in kube-proxy.

Flannel handles one networking layer: connecting Pods. The other layer, connecting clients to Pods through virtual addresses, is handled by kube-proxy and Kubernetes Service. Both must work together for an application to actually be reachable.
Episode 8 maps this division of responsibility, then tests it directly: creating Service types ClusterIP and NodePort on top of the Flannel network, and tracing how packets flow.
Flannel gives every Pod a unique IP address and a path between nodes. But Pod IPs are temporary: when a Pod dies, the IP changes. Service exists as a stable layer: a virtual IP that never changes, with kube-proxy behind it forwarding traffic to whatever Pod is currently healthy.
kubectl create deployment nginx --image=nginx --replicas=3
kubectl expose deployment nginx --port=80 --type=ClusterIP
kubectl get svc nginx
kubectl get endpoints nginxThe kubectl expose deployment nginx --port=80 command creates a ClusterIP. The CLUSTER-IP field in the output of kubectl get svc nginx is the virtual address, and the endpoints point to the Pod IPs handled by Flannel.
kube-proxy has two main modes. iptables mode translates a Service's virtual address into Pod IPs through DNAT rules on the NAT table. ipvs mode uses the kernel Virtual Server with a hash table that is more efficient at scale. Both run on top of the network Flannel provides.
kubectl get cm -n kube-system kube-proxy -o yaml | grep -i modeIf the output of kubectl get cm -n kube-system kube-proxy shows mode ipvs, the kernel Virtual Server is in use. The default value is generally iptables.
The simplest test: run a test Pod and access the Service through its virtual IP:
kubectl run curl --image=curlimages/curl --rm -it --restart=Never -- curl -s http://<cluster-ip>If the nginx page appears, the whole chain works: Flannel routes deliver the packet to the kube-proxy Pod, then DNAT forwards it to the backend Pod. Notice you are accessing the virtual IP, not the Pod IP — that's the function of a Service.
To see the two components working together, trace the rules kube-proxy installed:
iptables -t nat -L KUBE-SERVICES -n | grep nginxThe KUBE-SERVICES rules from iptables -t nat -L show DNAT from the nginx ClusterIP to Pod IPs in 10.244.x.x, the network Flannel builds.
NodePort opens a specific port on all nodes, for example 30080, and forwards it to the Service. Clients outside the cluster can access the application through any node IP:
kubectl get svc nginx -o yaml | sed 's/ClusterIP/NodePort/' | kubectl apply -f -
kubectl get svc nginxOr more easily, patch directly:
kubectl patch svc nginx -p '{"spec":{"type":"NodePort"}}'Wait, the second approach uses braces inside the kubectl command. That's fine inside a code block, but for clarity we'll use a simpler form:
kubectl port-forward svc/nginx 8080:80
curl localhost:8080The kubectl port-forward svc/nginx command is a practical alternative when the NodePort can't be reached directly from the test environment.
When using NodePort in production, remember that the opened port is a host port. The firewall on the nodes and the cloud security group must allow it. The relationship between firewall, NodePort, and Flannel will be discussed in more depth in episode 15.
A Service of type LoadBalancer can hang in Pending if there is no cloud controller providing a load balancer. Flannel doesn't provide this feature, so use NodePort or expose through an ingress. This is one of the important boundaries of responsibility to remember.
If access to the ClusterIP fails, check two things: whether the Flannel routes are healthy, and whether br_netfilter is active. Without br_netfilter, packets crossing the bridge are not filtered, so kube-proxy rules can be bypassed and connections hang.
Episode 8 tested the cooperation of two networking layers: Flannel for pod networking and kube-proxy for Service. You can now create ClusterIP and NodePort, and trace the packet flow between the two.
Key takeaways:
In the next episode, episode 9, we will dissect flanneld configuration and environment — flags and environment variables such as net-conf.json, backend type, and interface selection, plus MTU and VNI tuning, and how to choose the right host interface.