Understanding Pod Connectivity
Introduction
This tutorial will guide you through understanding and verifying pod-to-pod connectivity within a Kubernetes cluster. You’ll learn how to deploy test pods, use kubectl commands to inspect network policies and services, and utilize nslookup and curl to test connectivity. This tutorial assumes you have a running Kubernetes cluster and kubectl configured to connect to it.
Prerequisites
- A running Kubernetes cluster (Minikube, Kind, or a cloud provider).
kubectlinstalled and configured.- Basic understanding of Kubernetes concepts like Pods, Services, and Namespaces.
Task 1: Creating Test Namespaces
To isolate our test deployments, we’ll create two namespaces: test-ns-a and test-ns-b.
-
Create the
test-ns-anamespace:NODE_TYPE // yamlapiVersion: v1 kind: Namespace metadata: name: test-ns-a -
Apply the manifest:
NODE_TYPE // bashkubectl apply -f - <<EOF apiVersion: v1 kind: Namespace metadata: name: test-ns-a EOFNODE_TYPE // outputnamespace/test-ns-a created -
Create the
test-ns-bnamespace:NODE_TYPE // yamlapiVersion: v1 kind: Namespace metadata: name: test-ns-b -
Apply the manifest:
NODE_TYPE // bashkubectl apply -f - <<EOF apiVersion: v1 kind: Namespace metadata: name: test-ns-b EOFNODE_TYPE // outputnamespace/test-ns-b created
Task 2: Deploying Test Pods
We’ll deploy simple nginx pods in each namespace. These pods will act as our connectivity endpoints.
-
Create a deployment file named
nginx-deployment-a.yamlfortest-ns-a:NODE_TYPE // yamlapiVersion: apps/v1 kind: Deployment metadata: name: nginx-a namespace: test-ns-a labels: app: nginx-a spec: replicas: 1 selector: matchLabels: app: nginx-a template: metadata: labels: app: nginx-a spec: containers: - name: nginx image: nginx:latest ports: - containerPort: 80 -
Apply the deployment:
NODE_TYPE // bashkubectl apply -f nginx-deployment-a.yamlNODE_TYPE // outputdeployment.apps/nginx-a created -
Create a deployment file named
nginx-deployment-b.yamlfortest-ns-b:NODE_TYPE // yamlapiVersion: apps/v1 kind: Deployment metadata: name: nginx-b namespace: test-ns-b labels: app: nginx-b spec: replicas: 1 selector: matchLabels: app: nginx-b template: metadata: labels: app: nginx-b spec: containers: - name: nginx image: nginx:latest ports: - containerPort: 80 -
Apply the deployment:
NODE_TYPE // bashkubectl apply -f nginx-deployment-b.yamlNODE_TYPE // outputdeployment.apps/nginx-b created -
Verify the pods are running:
NODE_TYPE // bashkubectl get pods -n test-ns-a kubectl get pods -n test-ns-bNODE_TYPE // outputNAME READY STATUS RESTARTS AGE nginx-a-xxxxxxxxxx-xxxxx 1/1 Running 0 XXs NAME READY STATUS RESTARTS AGE nginx-b-yyyyyyyyyy-yyyyy 1/1 Running 0 YYsReplacexxxxxxxxxx-xxxxxandyyyyyyyyyy-yyyyywith the actual pod names generated by your cluster.
Task 3: Testing Connectivity Without a Service
By default, pods within the same cluster can communicate with each other directly using their IP addresses. Let’s test this.
-
Get the IP address of
nginx-apod:NODE_TYPE // bashkubectl get pod -n test-ns-a -o wideNODE_TYPE // outputNAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES nginx-a-xxxxxxxxxx-xxxxx 1/1 Running 0 XXs 10.244.0.10 node-1 <none> <none>Replace10.244.0.10with the actual IP address of yournginx-apod. -
Exec into the
nginx-bpod and usecurlto access thenginx-apod’s IP address. Ifcurlis not present, install it withapt update && apt install -y curl:NODE_TYPE // bashkubectl exec -it -n test-ns-b nginx-b-yyyyyyyyyy-yyyyy -- bashNODE_TYPE // bashapt update && apt install -y curl curl 10.244.0.10NODE_TYPE // output<!DOCTYPE html> <html> <head> <title>Welcome to nginx!</title> ... </html>A successful response indicates that the
nginx-bpod can reach thenginx-apod directly via its IP address.
Task 4: Creating Services for Stable Endpoints
Direct pod IP addresses are ephemeral. Services provide a stable endpoint for accessing pods. Let’s create services for our nginx deployments.
-
Create a service file named
nginx-service-a.yamlfornginx-a:NODE_TYPE // yamlapiVersion: v1 kind: Service metadata: name: nginx-service-a namespace: test-ns-a spec: selector: app: nginx-a ports: - protocol: TCP port: 80 targetPort: 80 -
Apply the service:
NODE_TYPE // bashkubectl apply -f nginx-service-a.yamlNODE_TYPE // outputservice/nginx-service-a created -
Create a service file named
nginx-service-b.yamlfornginx-b:NODE_TYPE // yamlapiVersion: v1 kind: Service metadata: name: nginx-service-b namespace: test-ns-b spec: selector: app: nginx-b ports: - protocol: TCP port: 80 targetPort: 80 -
Apply the service:
NODE_TYPE // bashkubectl apply -f nginx-service-b.yamlNODE_TYPE // outputservice/nginx-service-b created -
Get the service details:
NODE_TYPE // bashkubectl get svc -n test-ns-a nginx-service-a kubectl get svc -n test-ns-b nginx-service-bNODE_TYPE // outputNAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE nginx-service-a ClusterIP 10.96.147.126 <none> 80/TCP XXs NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE nginx-service-b ClusterIP 10.96.228.110 <none> 80/TCP YYsNote theCLUSTER-IPfor each service. These are the stable endpoints we’ll use for communication.
Task 5: Testing Connectivity Using Service Names
Kubernetes provides DNS resolution for services within the cluster. Pods can use service names to access other services.
-
Exec into the
nginx-bpod:NODE_TYPE // bashkubectl exec -it -n test-ns-b nginx-b-yyyyyyyyyy-yyyyy -- bash -
Use
curlto access thenginx-service-ausing its service name within thetest-ns-anamespace:NODE_TYPE // bashcurl nginx-service-a.test-ns-a.svc.cluster.localNODE_TYPE // output<!DOCTYPE html> <html> <head> <title>Welcome to nginx!</title> ... </html>This command uses the fully qualified domain name (FQDN) of the service.
nginx-service-ais the service name,test-ns-ais the namespace,svcindicates it’s a service, andcluster.localis the default cluster domain. -
You can also use
nslookupto resolve the service name to its Cluster IP:NODE_TYPE // bashnslookup nginx-service-a.test-ns-a.svc.cluster.localNODE_TYPE // outputServer: 10.96.0.10 Address: 10.96.0.10#53 Name: nginx-service-a.test-ns-a.svc.cluster.local Address: 10.96.147.126This confirms that DNS resolution is working correctly within the cluster.
Task 6: (Optional) Introducing Network Policies
Network policies control traffic flow between pods. Let’s demonstrate how to restrict connectivity.
-
Create a network policy file named
deny-all-egress.yamlintest-ns-bto block all outgoing traffic:NODE_TYPE // yamlapiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: deny-all-egress namespace: test-ns-b spec: podSelector: {} egress: [] policyTypes: - Egress -
Apply the network policy:
NODE_TYPE // bashkubectl apply -f deny-all-egress.yamlNODE_TYPE // outputnetworkpolicy.networking.k8s.io/deny-all-egress created -
Repeat the
curlcommand from Task 5:NODE_TYPE // bashkubectl exec -it -n test-ns-b nginx-b-yyyyyyyyyy-yyyyy -- bash curl nginx-service-a.test-ns-a.svc.cluster.localThis time, the
curlcommand will likely timeout. Thedeny-all-egresspolicy prevents thenginx-bpod from initiating connections to any other pod, including thenginx-apod.Network Policy behavior depends on your CNI (Container Network Interface) provider. Some CNIs may not fully support Network Policies. -
To remove the network policy:
NODE_TYPE // bashkubectl delete networkpolicy deny-all-egress -n test-ns-b
Conclusion
In this tutorial, you learned how to verify connectivity between pods in Kubernetes. You created test deployments, used kubectl to inspect pod IP addresses and create services, and tested connectivity using curl and service names. You also explored the impact of network policies on pod-to-pod communication. Understanding these concepts is crucial for troubleshooting network issues and building secure, well-connected applications in Kubernetes.