A first look at Network Policies in Tanzu Mission Control
Some time back, I wrote a blog post about how to use the network policies available with the Antrea CNI (Container Network Interface). In that post we looked at how to create a simple network policy to prevent communication between pods in a Tanzu Kubernetes cluster, based on pod selectors / labels. We stood up a simply web server and a standalone pod, and showed how the pod could access the web server when no network policies were in place. We then proceeded to create a network policy that only allowed pods to communicate to each other if the pod selector / label matched the rule defined in the policy. In this post, I am going to look at how to do the same operation in Tanzu Mission Control. Again, the Kubernetes cluster will be TKG v1.3.1 (K8s 1.20.5). I will create a namespace, then create a Nginx deployment + service along with a standalone busybox pod. To begin, the busybox will have a different label to Nginx. We will show how, without a network policy, the busybox pod can communicate with the Nginx service. We will then implement a network policy that only allows pods with a certain label to communicate, so in this case, the busybox pod will no longer be able to communicate with the web server. Finally, we will change the pod selector / label rule in the network policy to match that of the busybox pod and we should see successful communication once again.
Step 1 – Create namespace and apps
I created a namespace called network-testing on my TKG cluster. I deployed the Nginx application, and my standalone busybox pod. Note how they have different labels as shown by the APP column. Also note the Cluster-IP address for the Nginx service, highlighted in blue below. We will be using this to test communication between the pods.
$ kubectl get all -n network-testing -L app NAME READY STATUS RESTARTS AGE APP busybox 1/1 Running 0 9m1s busybox nginx-deployment-585449566-8p27j 1/1 Running 0 9m9s nginx nginx-deployment-585449566-nsd7k 1/1 Running 0 9m9s nginx nginx-deployment-585449566-rqfp5 1/1 Running 0 9m9s nginx NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE APP service/nginx-svc LoadBalancer 100.67.183.176 10.35.14.224 443:31991/TCP,80:30903/TCP 21m nginx NAME READY UP-TO-DATE AVAILABLE AGE APP deployment.apps/nginx-deployment 3/3 3 3 21m NAME DESIRED CURRENT READY AGE APP replicaset.apps/nginx-deployment-585449566 3 3 3 21m nginx
Step 2 – Verify pod communication without network policy
To make sure we have pod to pod communication in place without any network policy created, we can use the following test. After opening a shell to the busybox pod, we should be able to run a wget against the Cluster-IP of the Nginx service and retrieve the web server landing page, as shown below. This demonstrates that there is communication between the different pods.
$ kubectl exec -it busybox -n network-testing -- sh / # wget -q -O - 100.67.183.176 <!DOCTYPE html> <html> <head> <title>Welcome to nginx!</title> <style> html { color-scheme: light dark; } body { width: 35em; margin: 0 auto; font-family: Tahoma, Verdana, Arial, sans-serif; } </style> </head> <body> <h1>Welcome to nginx!</h1> <p>If you see this page, the nginx web server is successfully installed and working. Further configuration is required.</p> <p>For online documentation and support please refer to <a href="http://nginx.org/">nginx.org</a>.<br/> Commercial support is available at <a href="http://nginx.com/">nginx.com</a>.</p> <p><em>Thank you for using nginx.</em></p> </body> </html> / #
We can now try to control this communication with a network policy.
Step 3 – Create a Workspace in Tanzu Mission Control
In order to be able to create a network policy in Tanzu Mission Control (TMC), it must be created at the workspace level. A workspace is an organizational tool that helps you monitor and manage your Kubernetes namespaces within and across clusters. Creating the workspace is very simple. From the main TMC landing page, there is a Workspace link on the left-hand navigation bar. Click on this, and then click on the button to Create Workspace. Give it a name, and optional description and optional labels, and that is it. For this example, I created a workspace called network-testing-ws.
Step 4 – Attach the namespace to the Workspace in TMC
Once the workspace is created, add your namespace to it. As previously mentioned, I created a namespace called network-testing for this post. To add this namespace to the workspace, select Namespaces from the navigation bar on the left-hand side, select the namespace that you want to attach, and then click the Attach button. With the namespace now attached to the workspace, we can proceed with the creation of the network policy. In this screenshot, I have attached my network-testing namespace to the network-testing-ws workspace.
Step 5 – Navigate to ‘create a network policy’
Network policies can only be created at the workspace level. They cannot be created at cluster level or at a namespace level. Thus, to get to the point where you can create a network policy, you must first expand the Policies section in the left-hand navigation bar. This will show a sub-menu item called Assignments. Click on this and it will take you to the Policies section. Across the top, there will be a number of menu items. Select Network. Now you have the option of selecting Cluster or Workspace. If Cluster is selected, it will tell you that you cannot set network policies at the cluster level, only at the workspace level. Select Workspace, and then select the workspace you want to create a policy on. In our case, the workspace is network-testing-ws. Now you should see the option to create a network policy on the right hand side of the window.
Step 6 – Create a Network Policy
Click on the Create Network Policy link shown above. For the purposes of this demonstration, I am going to create a custom-ingress policy. I will give the policy a name, called nginx-allow. The pod selector, to identify which pods this rule applies, will be the pod selector / label app:nginx. Click on the Add Label button to save it.
Now we need to add the rule regarding who can have ingress access to Nginx. I changed the From: field to be Selector rather than IP Block, and stated that only pods with the app:nginx label (Pod Selector) can have ingress access. This should mean that our busybox pod no longer have access to the web-server.
Save the policy by click on the Create Policy button at the bottom. The new rule should now be associated with the namespace.
Step 7 – Test that the network policy is working
To test that the policy is working, try to access the web server from the busybox pod as before.
$ kubectl exec -it busybox -n network-testing -- sh / # wget -q -O - 100.67.183.176 wget: can't connect to remote host (100.67.183.176): Connection timed out
It would seem that the policy has successfully taken effect, and we are no longer able to access the web server because our busybox pod does not have the correct pod identifier / label.
Step 8 – Verifying with a different Pod Selector
There are two ways that you could allow the busybox pod to communicate to the web server. The first is to change the label on the busybox pod so that it has a label of app:nginx, or the alternate method is to change the rule in the policy, and modiy the pod selector from app:nginx to app:busybox. If we do the latter, the rule would look similar to the following:
After saving the rule, our wget command from the busybox pod to the web server service should start working again.
/ # wget -q -O - 100.67.183.176 | grep title <title>Welcome to nginx!</title>
Success! Finally, we can examine the network policy object that was created in our TKG cluster namespace by using the following kubectl commands.
$ kubectl get networkpolicy -A NAMESPACE NAME POD-SELECTOR AGE network-testing tmc.wsp.network-testing.nginx-allow <none> 12m $ kubectl describe networkpolicy -n network-testing Name: tmc.wsp.network-testing.nginx-allow Namespace: network-testing Created on: 2021-11-04 11:57:38 +0000 GMT Labels: tmc.cloud.vmware.com/managed=true Annotations: <none> Spec: PodSelector: app=nginx Allowing ingress traffic: To Port: <any> (traffic allowed to all ports) From: PodSelector: app=busybox Not affecting egress traffic Policy Types: Ingress
You can find our more information around rules that can be used in network policies in the official documentation.