Kubernetes CKS sample exam question 3 with answer - Network Policies

Question:

Create a namespace named g04 with labels app=orion
Set up three Pods to demonstrate the unrestricted Pod-to-Pod network communication. Define the Pods named backend which will use image gcr.io/kuar-demo/kuard-amd64:blue with container port 8080 and frontend with image alpine with command sleep 1d in the namespace g04. Define the other Pod with busybox image with command sleep 1d that lives in the default namespace.
Determine the virtual IP addresses assigned to the Pods.
Try to communicate between The frontend and the backend using wget
Try to communicate from other Pod residing in the default namespace with the backend Pod using wget
Apply deny-all ingress network policy from Kubernetes documentation.
Try again procedure with wget.
Allow ingress traffic to the backend Pod only from the frontend Pod that lives in the same namespace. Ingress traffic from all other Pods should be denied independently of the namespace they are running in.
Adjust network policy that allows the frontend Pod to talk to the backend Pod only on port 8080. No other communication should be allowed.
Test again with wget

Answer:

Create the namespace. First - generate a manifest:

k create ns g04 --dry-run=client -o yaml > ns.yaml
Edit the ns.yaml to match like this:
apiVersion: v1
kind: Namespace
metadata:
  name: g04
  labels:
    app: orion
Apply to create the namespace:
k apply -f ns.yaml
Create backend Pod in the g04 namespace:
k -n g04 run backend --image=gcr.io/kuar-demo/kuard-amd64:blue --port=8080
Create frontend Pod in the g04 namespace:
k -n g04 run frontend --image=alpine --command -- /bin/sh -c "sleep 1d"
Create other Pod in the default namespace:
k run other --image=busybox --command -- /bin/sh -c "sleep 1d"
Determine the IPs of new-created Pods:
k -n g04 get po -o wide
k get po -o wide
The output should be something like:
$ k -n g04 get po -o wide
NAME       READY   STATUS    RESTARTS   AGE     IP            NODE     NOMINATED NODE   READINESS GATES
backend    1/1     Running   0          19s     192.168.1.3   node01   <none>           <none>
frontend   1/1     Running   0          3m58s   192.168.1.5   node01   <none>           <none>
$ k get po -o wide
NAME    READY   STATUS    RESTARTS   AGE     IP            NODE     NOMINATED NODE   READINESS GATES
other   1/1     Running   0          3m34s   192.168.1.6   node01   <none>           <none>
Try to communicate between frontend and backend:
k -n g04 exec frontend -it  -- wget --spider --timeout=1 192.168.1.3:8080
Output will be:
Connecting to 192.168.1.3:8080 (192.168.1.3:8080)
remote file exists
Try the same communication from other Pod to backend:
k exec other -it  -- wget --spider --timeout=1 192.168.1.3:8080
Response is the same:
Connecting to 192.168.1.3:8080 (192.168.1.3:8080)
remote file exists
So, the frontend Pod can talk to the backend Pod and the other Pod residing in the default namespace can communicate with the backend Pod without problems.

Next, apply deny-all ingress network policy. The Kubernetes Documentation:
https://kubernetes.io/docs/concepts/services-networking/network-policies/#default-policies
provides a couple of helpful YAML manifest examples. The below one shows a network policy deny-all-ingress-network-policy.yaml that denies ingress traffic to all Pods in the namespace g04:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default-deny-ingress
  namespace: g04
spec:
  podSelector: {}
  policyTypes:
  - Ingress
Apply deny-all-ingress-network-policy.yaml above NetPol:
kubectl apply -f deny-all-ingress-network-policy.yaml
Let’s see how this changed the runtime behavior for Pod-to-Pod network communication. Try again the communication between frontend and backend:
k -n g04 exec frontend -it  -- wget --spider --timeout=1 192.168.1.3:8080
The frontend Pod cannot talk to the backend Pod anymore:
Connecting to 192.168.1.3:8080 (192.168.1.3:8080)
wget: download timed out
command terminated with exit code 1
Try to make a call from the other Pod running in the default namespace to the IP address of the backend Pod:
k exec other -it  -- wget --spider --timeout=1 192.168.1.3:8080
Furthermore, Pods running in a different namespace cannot connect to the backend Pod anymore either:
Connecting to 192.168.1.3:8080 (192.168.1.3:8080)
wget: download timed out
command terminated with exit code 1
Network policies are additive. To grant more permissions for network communication, simply create another network policy with more fine-grained rules.

So, per requirements - allow ingress traffic to the backend Pod only from the frontend Pod that lives in the same namespace. Ingress traffic from all other Pods should be denied independently of the namespace they are running in.
Note from above instructions that we have created a namespace with labels:
kubectl get ns g04 --show-labels
We will need those when creating a Network Policy. Output:
NAME   STATUS   AGE   LABELS
g04    Active   17m   app=orion,kubernetes.io/metadata.name=g0
Get the pod labels in the g04 namespace:
k -n g04 get po --show-labels
Output:
NAME       READY   STATUS    RESTARTS   AGE   LABELS
backend    1/1     Running   0          20m   run=backend
frontend   1/1     Running   0          20m   run=frontend
Create a new network policy backend-ingress-network-policy.yaml that allows the frontend Pod to talk to the backend Pod only on port 8080. No other communication should be allowed:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: backend-ingress
  namespace: g04
spec:
  podSelector:
    matchLabels:
      run: backend
  policyTypes:
  - Ingress
  ingress:
  - from:
    - namespaceSelector:
        matchLabels:
          app: orion
      podSelector:
        matchLabels:
          run: frontend
    ports:
    - protocol: TCP
      port: 8080
Apply backend-ingress-network-policy.yaml:
k apply -f backend-ingress-network-policy.yaml
Test again with wget from frontend Pod:
k -n g04 exec frontend -it  -- wget --spider --timeout=1 192.168.1.3:8080
And it works:
Connecting to 192.168.1.3:8080 (192.168.1.3:8080)
remote file exists
Test from other pod in default namespace:
k exec other -it  -- wget --spider --timeout=1 192.168.1.3:8080
Pods running outside of the g04 namespace still can’t connect to the backend Pod:
Connecting to 192.168.1.3:8080 (192.168.1.3:8080)
wget: download timed out
command terminated with exit code 1