在使用 K8S 过程中,偶尔会遇到如下所示的一段配置:

1securityContext:
2  capabilities:
3    drop:
4      - ALL
5    add:
6      - NET_BIND_SERVICE

实际上这是配置对应的容器的 Capabilities,在我们使用 docker run 的时候可以通过 --cap-add 和 --cap-drop 命令来给容器添加 Linux Capabilities

Linux Capabilities

Linux 使用 Capabilities 机制来对 root 权限进行了更加细粒度的控制,实现按需进行授权,减小了系统的安全隐患。Linux 将传统上与超级用户 root 关联的特权划分为不同的、可以独立启用禁用的单元,称为 Capabilities。

这样当系统在作权限检查的时候就变成了:在执行特权操作时,如果进程的有效身份不是 root,就去检查是否具有该特权操作所对应的 Capabilities,并以此决定是否可以进行该特权操作。比如,如果要设置系统时间,就得具有 CAP_SYS_TIME 这个 Capabilities。

Capabilities 详细描述可参考 capabilities man page

使用 Capabilities

通过 getcap 和 setcap 两条命令来分别查看和设置程序文件的 capabilities 属性。

 1# 查看 cap
 2root@iZwz9c8vxak6iz0pol8de3Z:~# getcap /bin/ping
 3/bin/ping cap_net_raw=ep
 4
 5# 删除 ping 的 cap
 6setcap cap_net_admin,cap_net_raw-p /bin/ping
 7
 8getcap /bin/ping
 9/bin/ping =
10
11# 恢复 ping 的 cap
12setcap cap_net_admin,cap_net_raw+p /bin/ping
13
14getcap /bin/ping
15/bin/ping cap_net_admin,cap_net_raw=p

Docker 配置 Capabilities

在 Docker 中,可以通过 --cap-add 和 --cap-drop 这两个参数来动态调整权限, 最大限度地保证容器的使用安全。下面表格中列出的 Capabilities 是 Docker 默认给容器添加的,我们可以通过 --cap-drop 去除其中一个或者多个:

--cap-add--cap-drop 这两参数都支持ALL值,比如如果你想让某个容器拥有除了MKNOD之外的所有内核权限,那么可以执行下面的命令: 

1$ sudo docker run --cap-add=ALL --cap-drop=MKNOD ...

假如需要修改网络接口数据,默认情况下是没有权限的,因为需要的 NET_ADMIN 这个 Capabilities 默认被移除了:

1$ docker run -it --rm busybox /bin/sh
2/ # ip link add dummy0 type dummy
3ip: RTNETLINK answers: Operation not permitted
4/ #

所以在不使用 --privileged 的情况下(不建议)我们可以使用 --cap-add=NET_ADMIN 将这个 Capabilities 添加回来:

1$ docker run -it --rm --cap-add=NET_ADMIN busybox /bin/sh
2/ # ip link add dummy0 type dummy
3/ #

K8S 配置 Capabilities

在 Kubernetes 中也可以很方便的来定义,我们只需要添加到 Pod 定义的 spec.containers.sercurityContext.capabilities中即可,也可以进行 add 和 drop 配置,同样上面的示例,我们要给 busybox 容器添加 NET_ADMIN 这个 Capabilities,对应的 YAML 文件可以这样定义:

 1apiVersion: v1
 2kind: Pod
 3metadata:
 4  name: cpb-demo
 5spec:
 6  containers:
 7    - name: cpb
 8      image: busybox
 9      args:
10        - sleep
11        - "3600"
12      securityContext:
13        capabilities:
14          add: # 添加
15            - NET_ADMIN
16          drop: # 删除
17            - KILL

在 Kubernetes 中通过 sercurityContext.capabilities 进行配置容器的 Capabilities,当然最终还是通过 Docker 的 libcontainer 去借助 Linux kernel capabilities 实现的权限管理。

参考资料:

  1. https://www.qikqiak.com/post/capabilities-on-k8s/