Controlling Network Access in AKS using Network Policies

One of the very first problems when starting to deploy workloads in Azure Kubernetes Service is the segregation of the network. By default, all pods are part of the same network and can communicate with each other.

In the majority of the cases, however, we want to restrict network access between pods, namespaces, applications, etc. Fortunately, K8s provide a way to easily control network traffic, called Network Policies.

There are two types of policies that can be applied to a pod, Ingress and Egress. Ingress-type policies control the traffic inbound to the pod, whilst egress control the traffic outbound from a pod. In this post, we're going to work only with ingress-type policies since the configuration and principles are pretty much the same, it's just the direction that changes.

To demonstrate the use of policies, we are going to be using three namespaces and each namespace will contain a deployment with containers that respond to ping requests and also contain the ping utility.

As with all posts related to K8s and AKS, I've created a set of Bicep files that create a network and an AKS cluster on Azure. All you have to do is to execute the script from the 101-Bicep-Templates/900-IaC-FullDeployment-001 folder.

When the deployment is completed, use the script from the 201-K8s-Deployments/401-Scripts/101-Azure folder to get the credentials for the cluster.

Now we're ready to deploy! The first three folders (*Application*) in 201-K8s-Deployments contain the necessary files to create the three namespaces and the applications within them. Apply the files using kubectl and verify the status of the pods that are created:

To test the connectivity from one pod to another, we're going to be connecting to the pods using the kubectl exec command. You'll find the exact definition of the command including all parameters in the script of the 201-K8s-Deployments/401-Scripts/102-K8s folder. My suggestion at this time is to open up multiple terminals in VS Code and connect to all pods.

The below diagram shows the namespaces and pods that are created as part of this demo:

Let's say that we apply the policies in the repository to the above AKS environment. The communications shown in green should be allowed and in red denied.

Keeping in mind that we only apply ingress-type policies and each policy has been applied to one of the namespaces, the result would be:

  • 3,6 and 9: Not allowed since no ingress communication is allowed
  • 1,8: Allowed due to the fact that all communication from production-tagged namespaces is allowed
  • 4: Blocked since the App-3 namespace is not tagged as production
  • 2,5: Blocked because ingress traffic is only allowed from within the same namespace
  • 7: Allowed since the connection is initiated from the same namespace
Let's dive into each policy and its settings!

This policy denies all ingress traffic to the pods in the specified namespace. This policy is applied to the namespace app-3 and this is the reason that even the pods in the same namespace cannot communicate with each other! Usually used on pods that should be locked down.

Applying this policy will deny all ingress network traffic to the pods in the specified namespace unless the source pod is part of a namespace that is tagged as production. Especially useful when separating multiple environments in the same cluster, like test and dev. As part of this lab, this policy is applied to the app-2 namespace.

The last example is a policy that allows ingress traffic only when the source pod is part of the same namespace as the destination pod. Applied to the namespace app-1 above, it allows pods in that namespace to communicate freely.

The Bicep and K8s files used in this demo are available here. More examples of Network Policies are available in Ahmet Alp Balkan's Github over here.

For more complex environments you should consider using a Service Mesh technology!

Happy coding!

Popular posts from this blog

Domain Controller Machine Password Reset

Configuring a Certificate on Exchange Receive Connector

Verbose Parameter Passing to cmdlet inside Function