Earlier this week my girlfriend (who is a networking ninja) asked a great question, how do you secure traffic between pods in Azure Kubenetes Service (AKS).

This simple sounding question started a two-day hack to allow us to experiment with deploying AKS and configuring network policies. As it turns out, this functionality is currently in preview, so it wasn’t as simple as it might have first appeared.

In this post, I’m going to outline the basics of a demo that demonstrates the process. If you’re interested in following this tutorial then you’ll be pleased to hear you don’t have to install any tools locally!

Cloud Shell

The Cloud Shell is a browser-based shell experience available anywhere, providing you can log into the Azure portal. With the Cloud Shell, you are able to pick between either Bash or Powershell, which is great for me as a long time macOS user now sporting a Dell.

Cloud Shell Scripts

When I first saw the Cloud Shell, I assumed it was only good for executing individual commands but its just as powerful as PowerShell on my Dell or Bash on my Mac. This is because it’s backed by Azure File Storage, which allows us to upload and execute existing shell scripts.

Using the Cloud Shell with scripts makes it super easy to quickly deploy services in a reproducible way, without having to install and configure any tools on your local development machine, which is a HUGE win!

Preview Features

This feature is in preview, so before we start, we need to enable it. In the Cloud Shell, enter the following:

az feature register --name EnableNetworkPolicy --namespace Microsoft.ContainerService

This can take a few minutes but only ever needs to be done just the once! Once It’s completed, you can query its status using the following:

az feature list -o table --query "[?contains(name, 'Microsoft.ContainerService/EnableNetworkPolicy')].{Name:name,State:properties.state}

Once registered is success, you’ll need to run the following to finish up:

az provider register -n Microsoft.ContainerService

Creating an AKS Instance

Now for the interesting bits! We’re going to deploy a new AKS cluster! Because we’ll be using the same names throughout the process, we’ll go ahead and define these as variables.

export RESOURCE_GROUP_NAME=my-aks-demo
export CLUSTER_NAME=my-AKS1

Create a resource group

az group create --name $RESOURCE_GROUP_NAME --location eastus

Create a Virtual Network & Subnet

az network vnet create --resource-group $RESOURCE_GROUP_NAME --name myVnet --address-prefixes 10.0.0.0/8 --subnet-name myAKSSubnet --subnet-prefix 10.240.0.0/16

We get the Virtual Network Subnet Resource ID

SUBNET_ID=$(az network vnet subnet show --resource-group $RESOURCE_GROUP_NAME --vnet-name myVnet --name myAKSSubnet --query id -o tsv) 

az aks create --resource-group $RESOURCE_GROUP_NAME --name $CLUSTER_NAME --kubernetes-version 1.12.4 --network-plugin azure --service-cidr 10.0.0.0/16 --dns-service-ip 10.0.0.10 --docker-bridge-address 172.17.0.1/16 --vnet-subnet-id $SUBNET_ID --network-policy calico --generate-ssh-keys

Nows the time to pop your feet up and relax as this is going to take a while. On average it takes about 10 minutes to finish. Once it has though, it’ll have spun up a new AKS cluser which means we can grab a copy of the Kubernetes Context using Kubectl:

az aks get-credentials --resource-group $RESOURCE_GROUP_NAME --name $CLUSTER_NAME

Deploying something!

We need to deploy something to AKS in order to confirm that the network policies are working. We don’t need anything too complex so a NGINX Container it is! We’ll give it a label of “app=api” and expose the pod.

kubectl run api --image=nginx --labels app=api --expose --port 80

By default, any other containers should be able to communicate with the API we just deployed, so lets confirm! To do that,we’ll go ahead and deploy another container.
kubectl run --rm -it --image=alpine test-np

Testing, Testing, 123

200.gif

Lets test if it works! To do this, we can use the prompt and enter the following:
wget http://api -qO-

We should then get some HTML passed back as text.

Deny Policy

gandalfmeme

So we know we can communicate, which is default behavior, lets deploy a network policy which will deny the communication. The policies are super simple, in fact the sample here is only 9 LOC!

kind: NetworkPolicy
apiVersion: networking.k8s.io/v1
metadata:
name: api-policy
spec:
podSelector:
matchLabels:
app: api
ingress: []

With this saved to disk (or uploaded to the Cloud Shell), we can call the following:
kubectl create -f [RootDirectory]/deny.yaml

Testing

To retest we’re going to need to reattach to the pod. To do this, enter the following:
kubectl attach [test-np name] -i -t

We can then repeat the process above but adding a timeout to ensure we don’t wait until boredom or death occurs before being told it failed. (its default is 30 seconds…)

wget -qO- --timeout=2 http://api

Wrap Up

You’re now a cutting edge, AKS networking ninja!

Well, perhaps not exactly but you’ve at least learn the basic of this new feature to AKS. To learn more about this new feature then check out the offical documentation on the Microsoft site.

Huge thanks and credit goes to Simona Tarantola & Justin Davies. This post wouldn’t have been possible without them!


1 Comment

Azure.Source – Volume 76 – Cloud News Magazine · April 1, 2019 at 3:17 pm

[…] AKS Networking Policies […]

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.