RSS

Kubernetes supports running kube-proxy in an unprivileged container

This post describes how the --init-only flag to kube-proxy can be used to run the main kube-proxy container in a stricter securityContext, by performing the configuration that requires privileged mode in a separate init container. Since Windows doesn’t have the equivalent of capabilities, this only works on Linux.

The kube-proxy Pod still only meets the privileged Pod Security Standard, but there is still an improvement because the running container doesn’t need to run privileged.

Please note that kube-proxy can be installed in different ways. The examples below assume that kube-proxy is run from a pod, but similar changes could be made in clusters where it is run as a system service.

Background

It is undesirable to run a server container like kube-proxy in privileged mode. Security aware users wants to use capabilities instead.

If kube-proxy is installed as a POD, the initialization requires “privileged” mode, mostly for setting sysctl’s. However, kube-proxy only tries to set the sysctl’s if they don’t already have the right values. In theory, then, if a privileged init container set the sysctls to the right values, then kube-proxy could run unprivileged.

The problem is to know what to setup. Until now the only option has been to read the source to see what changes kube-proxy would have made, but with --init-only you can have kube-proxy itself do the setup exactly as on a normal start, and then exit.

Initializing kube-proxy in an init container

The example manifests below are not complete, but narrowed down to what is essential to illustrate the function.

Usually, cluster operators run kube-proxy in a privileged security context.

apiVersion: apps/v1
kind: DaemonSet
metadata:
  labels:
    k8s-app: kube-proxy
spec:
  template:
    spec:
      containers:
      - name: kube-proxy
        command:
        - /usr/local/bin/kube-proxy
        - --config=/var/lib/kube-proxy/config.conf
        - --hostname-override=$(NODE_NAME)
        securityContext:
          privileged: true
   # (lots of stuff omitted here...)

But now it is possible to use:

apiVersion: apps/v1
kind: DaemonSet
metadata:
  labels:
    k8s-app: kube-proxy
spec:
  template:
    spec:
      initContainers:
      - name: kube-proxy-init
        command:
        - /usr/local/bin/kube-proxy
        - --config=/var/lib/kube-proxy/config.conf
        - --hostname-override=$(NODE_NAME)
        - --init-only
        securityContext:
          privileged: true
   # (lots of stuff omitted here...)
      containers:
      - name: kube-proxy
        command:
        - /usr/local/bin/kube-proxy
        - --config=/var/lib/kube-proxy/config.conf
        - --hostname-override=$(NODE_NAME)
        securityContext:
          capabilities:
            add: ["NET_ADMIN"]
   # (lots of stuff omitted here...)

Summary

The --init-only flag can be used to perform privileged initialization in an init container and run the main container with NET_ADMIN capabilities only. Installers like kubeadm will likely be altered to use this feature in the future.