在使用 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
实现的权限管理。
参考资料: