Skip to content

Configure a Pod to run with a limited SecurityContext

As Subkube is a shared platform, containers are only allowed to run in so-called 'restricted' PodSecurityPolicies. This guide walks through the steps of creating a deployment, seeing it fail, updating it to use a SecurityContext, and seeing it run successfully.

Prerequisites

  • A Namespace in a Subkube Project
  • Kubectl

Steps

Setting up a basic Deployment

For this example, we will use the echoserver image, which sets up a simple HTTP server which replies everything sent to it.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
apiVersion: apps/v1
kind: Deployment
metadata:
  creationTimestamp: null
  labels:
    app: hello-subkube
  name: hello-subkube
spec:
  replicas: 1
  selector:
    matchLabels:
      app: hello-subkube
  strategy: {}
  template:
    metadata:
      creationTimestamp: null
      labels:
        app: hello-subkube
    spec:
      containers:
      - image: ealen/echo-server:latest
        name: echoserver
        resources: {}
status: {}

Let's apply the supplied, unmodified deployment, to a namespace, called demo in our example:

1
kubectl apply -n demo -f deployment-before.yaml

Initial testing

Because we don't want to set up any Services or an Ingress, we'll use a PortForward to connect to the Deployment:

1
2
> kubectl port-forward -n demo deployment/hello-subkube 8080:8080
error: unable to forward port because pod is not running. Current status=Pending

😕

Figuring out why our Pod fails

Let's check the logs and see what is going wrong

1
2
> kubectl logs deployment/hello-subkube -n demo
Error from server (BadRequest): container "echoserver" in pod "hello-subkube-758bc95559-bgg29" is waiting to start: CreateContainerConfigError

We are shown a CreateContainerConfigError while trying to fetch the Pod's logs. Let's look in to that:

1
2
3
4
5
6
> kubectl describe pods -n demo
...
Normal   Pulled     47s (x8 over 2m18s)  kubelet, minikube-local-local  Successfully pulled image "ealen/echo-server:latest"
Warning  Failed     47s (x8 over 2m18s)  kubelet, minikube-local-local  Error: container has runAsNonRoot and image will run as root
Normal   Pulling    33s (x9 over 2m27s)  kubelet, minikube-local-local  Pulling image "ealen/echo-server:latest"
...

Because we haven't configured our Deployment to run with an appopriate SecurityContext, the Kubernets control plane isn't allowing Pods in our Deployment to run.

Setting a SecurityContext

We can easily fix this by setting a SecurityContext. For many containers this is as easy as setting the runAsUser property to the value 65534, which translates to the nobody user account.

By default, the echo-server image runs on port 80, but because our container won't be running as root, the container will be unable to allocate the port, and the Pod will fail. Instead, we want to run the echo-server on a different port, say 8080.

Let's update our Deployment manifest accordingly:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
apiVersion: apps/v1
kind: Deployment
metadata:
  creationTimestamp: null
  labels:
    app: hello-subkube
  name: hello-subkube
spec:
  replicas: 1
  selector:
    matchLabels:
      app: hello-subkube
  strategy: {}
  template:
    metadata:
      creationTimestamp: null
      labels:
        app: hello-subkube
    spec:
      containers:
      - image: ealen/echo-server:latest
        name: echoserver
        env:
          - name: PORT
            value: "8080"
        securityContext:
          runAsUser: 65534
status: {}

Now we should apply the modified deployment:

1
kubectl apply -n demo -f deployment-after.yaml

Testing our revised Deployment

Let's again try to start our PortForward:

1
kubectl port-forward -n demo deployment/hello-subkube 8080:8080

That should've worked. Now we can use curl to test our Deployment:

1
2
> curl 'localhost:8080/?echo_body=All_Good'
All_Good

More Resources & Further Reading