--- title: 'CKA Practice: Configure Network Policies To Restrict Traffic Between Pods' description: | This exercise tests your ability to configure kubernetes network policies to make sure only pods with specific labels can communicate with each other. kind: challenge playground: k3s playgroundOptions: tabs: - machine: dev-machine - machine: cplane-01 - machine: node-01 machines: - name: dev-machine users: - name: root default: true welcome: | Welcome to the CKA networking exercise. Follow the instructions to configure secure pod communication. - name: cplane-01 - name: node-01 cover: __static__/pod-networking-with-labels.png createdAt: 2024-11-03 updatedAt: 2024-12-18 difficulty: easy categories: - kubernetes - networking tagz: - cka - network-policies tasks: verify_namespace: run: | if [ $(kubectl get namespace | grep app | wc -l) -gt 0 ]; then echo "Namespace created!" exit 0 else exit 1 fi verify_deployment_frontend: needs: - verify_namespace run: | if [ $(kubectl get deployment -n app frontend -o jsonpath='{.status.replicas}') -eq 2 ]; then echo "Frontend deployment created successfully!" exit 0 else exit 1 fi verify_deployment_backend: needs: - verify_namespace run: | if [ $(kubectl get deployment -n app backend -o jsonpath='{.status.replicas}') -eq 2 ]; then echo "Backend deploymenet created successfully!" exit 0 else exit 1 fi verify_labels_all_frontend: needs: - verify_deployment_frontend - verify_deployment_backend run: | if [ $(kubectl get pods -n app -l role=frontend --no-headers | wc -l) -eq 2 ]; then echo "Frontend pod labels configured correctly!" exit 0 else exit 1 fi verify_labels_all_backend: needs: - verify_deployment_frontend - verify_deployment_backend run: | if [ $(kubectl get pods -n app -l tier=api --no-headers | wc -l) -eq 2 ]; then echo "Backend pod labels configured correctly!" exit 0 else exit 1 fi verify_labels_one_backend: needs: - verify_deployment_frontend - verify_deployment_backend run: | if [ $(kubectl get pods -n app -l "tier=api,!role" --no-headers | wc -l) -eq 1 ]; then echo "Single backend pod label configured correctly!" exit 0 else exit 1 fi verify_network_policies: # we don't want this to start firing too soon needs: - verify_labels_all_frontend - verify_labels_all_backend - verify_labels_one_backend # default timeout is 10-15 seconds, and we want the checking loop to run faster than that timeout_seconds: 7 run: | # Get a frontend pod and one backend pod with role=backend and one backend pod without a role FRONTEND_POD=$(kubectl get pod -n app -l role=frontend -o jsonpath='{.items[0].metadata.name}') FRONTEND_POD_IP=$(kubectl get pod -n app -l role=frontend -o jsonpath='{.items[0].status.podIP}') BACKEND_POD_WITH_ROLE=$(kubectl get pod -n app -l role=backend -o jsonpath='{.items[0].metadata.name}') BACKEND_POD_WITH_ROLE_IP=$(kubectl get pod -n app -l role=backend -o jsonpath='{.items[0].status.podIP}') BACKEND_POD_WITHOUT_ROLE=$(kubectl get pod -n app -l "tier=api,role!=backend" -o jsonpath='{.items[0].metadata.name}') BACKEND_POD_WITHOUT_ROLE_IP=$(kubectl get pod -n app -l "tier=api,role!=backend" -o jsonpath='{.items[0].status.podIP}') # Test connectivity from frontend to both backend pods FRONTEND_TO_BACKEND=$(kubectl -n app exec $FRONTEND_POD -- curl -s -o /dev/null -w "%{http_code}" --connect-timeout 5 $BACKEND_POD_WITH_ROLE_IP:8000) FRONTEND_TO_BACKEND_WITHOUT_ROLE=$(kubectl -n app exec $FRONTEND_POD -- curl -s -o /dev/null -w "%{http_code}" --connect-timeout 5 $BACKEND_POD_WITHOUT_ROLE_IP:8000) # Test connectivity from both types of backend pods to frontend pod BACKEND_WITH_ROLE_TO_FRONTEND=$(kubectl -n app exec $BACKEND_POD_WITH_ROLE -- curl -s -o /dev/null -w "%{http_code}" --connect-timeout 5 $FRONTEND_POD_IP:80) BACKEND_WITHOUT_ROLE_TO_FRONTEND=$(kubectl exec -n app $BACKEND_POD_WITHOUT_ROLE -- curl -s --connect-timeout 5 $FRONTEND_POD_IP:80 2>&1 || true) if [ "$FRONTEND_TO_BACKEND" -eq 200 ] && \ [ "$FRONTEND_TO_BACKEND_WITHOUT_ROLE" -eq 200 ] && \ [ "$BACKEND_WITH_ROLE_TO_FRONTEND" -eq 200 ] && \ [[ "$BACKEND_WITHOUT_ROLE_TO_FRONTEND" == *"command terminated"* ]]; then echo "Network policies configured correctly!" exit 0 else exit 1 fi --- In this exercise, you will configure network policies to control traffic flow between two deployments in a Kubernetes cluster. You'll need to ensure specific pods can communicate based on their labels while blocking unauthorized traffic. Have fun! <img src="__static__/pod-networking-with-labels.png" style="margin: 0px auto; max-width: 600px; width: 100%" alt="Diagram showing desired network policy configuration between frontend and backend pods"> First, create a namespace called "app": ::simple-task --- :tasks: tasks :name: verify_namespace --- #active Waiting for namespace to be created... #completed Good, the namespace is ready to go. :: ::hint-box --- :summary: Hint 1 --- Check the [documentation for creating namespaces](https://kubernetes.io/docs/reference/generated/kubectl/kubectl-commands#-em-namespace-em-) :: Now, create two deployments in that namespace. 1. Frontend: - Deployment "frontend" with 2 replicas running `ghcr.io/iximiuz/labs/nginx:alpine` - Accessible on port 80 2. Backend: - Deployment "backend" with 2 replicas running `ghcr.io/lpmi-13/default-go` - Accessible on port 8000 ::simple-task --- :tasks: tasks :name: verify_deployment_frontend --- #active Waiting for frontend deployment to be created... #completed Great! Frontend deployment is running correctly. :: ::simple-task --- :tasks: tasks :name: verify_deployment_backend --- #active Waiting for backend deployment to be created... #completed Alright! Backend deployment is running correctly. :: ::hint-box --- :summary: Hint 2 --- Check the [documentation for creating deployments](https://kubernetes.io/docs/reference/generated/kubectl/kubectl-commands#-em-deployment-em-) :: Now, label the pods: 1. All frontend pods should have: `role=frontend` 2. All backend pods should have: `tier=api` 3. Only one backend pod should have the additional label: `role=backend` ::simple-task --- :tasks: tasks :name: verify_labels_all_frontend --- #active Checking for correct frontend pod labels... #completed Nice! Both frontend pods are properly labeled with `role=frontend`. :: ::simple-task --- :tasks: tasks :name: verify_labels_all_backend --- #active Checking for correct backend pod labels... #completed Fantastic! Both backend pods are properly labeled with `tier=api`. :: ::simple-task --- :tasks: tasks :name: verify_labels_one_backend --- #active Checking for correct backend pod label... #completed Good! Only one backend pod is properly labeled with `role=backend`. :: ::hint-box --- :summary: Hint 3 --- Check the [documentation for adding labels](https://kubernetes.io/docs/reference/generated/kubectl/kubectl-commands#label) :: ::hint-box --- :summary: Hint 4 --- ```bash # Get the name of one backend pod BACKEND_POD=$(kubectl get pods -n app -l app=backend -o jsonpath='{.items[0].metadata.name}') ``` :: Finally, create network policies to make sure: 1. All frontend pods can send traffic to any backend pod with label `tier=api` on port 8000 2. Only the backend pod with label `role=backend` can send traffic to frontend pods with label `role=frontend` on port 80 3. All other traffic should be denied by default ::simple-task --- :tasks: tasks :name: verify_network_policies --- #active Verifying network policies and testing connectivity... #completed Excellent! The network policies are correctly configured and enforcing the desired traffic patterns. :: ::hint-box --- :summary: Hint 5 --- Create two network policies, one for the frontend => backend, and another from the backend => frontend. Here's the first one: ```yaml apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: frontend-to-backend namespace: app spec: podSelector: matchLabels: tier: api ingress: - from: - podSelector: matchLabels: role: frontend ports: - port: 8000 protocol: TCP ``` ::