Exercise 3: Pod Security Standards
In this exercise, you’ll learn about Pod Security Standards in Kubernetes and how to implement them to enhance the security posture of your AKS cluster. You’ll also explore how to create and manage namespaces with specific security policies.
Task 1: Using Pod Security Standards
Pod Security Standards in Kubernetes help enforce security best practices for your pods. Let’s explore how to use them:
Create a namespace with enforced Pod Security Standards:
kubectl create namespace restricted-ns kubectl label namespace restricted-ns pod-security.kubernetes.io/enforce=restricted
kubectl create namespace restricted-ns kubectl label namespace restricted-ns pod-security.kubernetes.io/enforce=restricted
Try to create a privileged pod in this namespace:
$privilegedPodYaml = @" apiVersion: v1 kind: Pod metadata: name: privileged-pod spec: containers: - name: nginx image: k8sonazureworkshoppublic.azurecr.io/nginx securityContext: privileged: true "@ $privilegedPodYaml | kubectl apply -f - -n restricted-ns
cat << EOF | kubectl apply -f - -n restricted-ns apiVersion: v1 kind: Pod metadata: name: privileged-pod spec: containers: - name: nginx image: k8sonazureworkshoppublic.azurecr.io/nginx securityContext: privileged: true EOF
This should fail because the Pod Security Standard doesn’t allow privileged containers.
Create a pod that complies with the restricted policy. This uses the nginx-unprivilaged image to remove the need for privilage escalation, binds to a non-privilaged port and does not try and write to root-owned directories.
$compliantPodYaml = @" apiVersion: v1 kind: Pod metadata: name: compliant-nginx namespace: restricted-ns spec: securityContext: runAsNonRoot: true seccompProfile: type: RuntimeDefault containers: - name: nginx image: k8sonazureworkshoppublic.azurecr.io/nginx ports: - containerPort: 8080 securityContext: allowPrivilegeEscalation: false capabilities: drop: ["ALL"] runAsNonRoot: true "@ $compliantPodYaml | kubectl apply -f - -n restricted-ns
cat << EOF | kubectl apply -f - -n restricted-ns apiVersion: v1 kind: Pod metadata: name: compliant-nginx namespace: restricted-ns spec: securityContext: runAsNonRoot: true seccompProfile: type: RuntimeDefault containers: - name: nginx image: k8sonazureworkshoppublic.azurecr.io/nginx ports: - containerPort: 8080 securityContext: allowPrivilegeEscalation: false capabilities: drop: ["ALL"] runAsNonRoot: true EOF
Verify that the compliant pod is running:
kubectl get pods -n restricted-ns
kubectl get pods -n restricted-ns
Alternatively, if we did have a requirement to run the privileged version of Nginx, we can remove the restricted policy from the namespace. By default AKS applies the restricted policy to all namespaces, you can see this by running:
kubectl describe namespace restricted-ns
kubectl describe namespace restricted-ns
You should see the pod security labels in the output.
Remove the restricted policy from the namespace:
kubectl label namespace restricted-ns pod-security.kubernetes.io/enforce-
kubectl label namespace restricted-ns pod-security.kubernetes.io/enforce-
Now try to create the privileged pod again:
$privilegedPodYaml = @" apiVersion: v1 kind: Pod metadata: name: privileged-pod spec: containers: - name: nginx image: k8sonazureworkshoppublic.azurecr.io/nginx securityContext: privileged: true "@ $privilegedPodYaml | kubectl apply -f - -n restricted-ns
cat << EOF | kubectl apply -f - -n restricted-ns apiVersion: v1 kind: Pod metadata: name: privileged-pod spec: containers: - name: nginx image: k8sonazureworkshoppublic.azurecr.io/nginx securityContext: privileged: true EOF
Verify that both pods are now running:
kubectl get pods -n restricted-ns
kubectl get pods -n restricted-ns
You should see both the compliant-nginx and privileged-pod running.
Clean up the namespace:
kubectl delete namespace restricted-ns
kubectl delete namespace restricted-ns