前言
k8s本身并不负责容器的定义与实现,Kubernetes 通过使用容器运行时接口来实现容器的管理,而容器的实现通过容器运行时(如 Docker、CRI-O 等)来实现。
非根容器和默认容器的区别
容器内部默认是以root用户来执行指令的,这意味着应用程序在它所在的容器内部都拥有最高的执行权限,程序都可以修改容器内部的系统文件,访问机密信息,可以在运行时安装系统包,还可以绑定1024以下的任意端口。
而非根容器的出现就是为了阻止这些不安全行为。非根容器启动之后是无法再转变成根容器的,应用程序只能以特定的用户角色运行,可以防止恶意代码获取最高运行权限。
非根容器的优/缺点
优点:1. 安全 ,某些k8s发行版如Openshift要求必须使用非根容器。
缺点:应用程序可能会因为权限不足,无法访问或创建某些文件、目录。例如mysql,git等应用。
如何解决非根容器的局限性
假如应用程序必须使用root权限做一些事情,但是又希望使用非根容器运行,那么可以考虑以下几种方案:
- 使用initContainers。initContainers是一种特殊的容器,它可以在Pod的其他容器启动之前运行,用于初始化容器所需的环境。
- 修改Dockerfile,在Dockerfile中以root用户完成要做的事情之后,再切换回指定用户。
- 在Dockerfile中修改运行时需要访问的文件权限(不推荐)
- 在使用挂载卷时,修改UID等参数将挂载卷的所有者设置为非根容器使用的用户或组。这样非根容器才可以以自己的用户身份来访问挂载卷。
如何创建非根容器
非根容器的创建需要分为两部分:
Dockerfile
在Dockerfile中可以通过命令 USER <UID>将默认root用户切换为指定用户。
如下所示,USER 1001之后的命令将以UID为1001的用户权限来执行,如果该用户不存在,docker会尝试使用该UID创建一个用户。
需要注意的是红帽公司推出的Pass平台 Openshift 会忽略掉dockerfile中指定的user,而是使用一个随机的UID,这也意味着在Openshift 上所有容器都是默认以非根方式运行的。
FROM bitnami/minideb-extras:jessie-r22
LABEL maintainer "Bitnami <[email protected]>"
ENV BITNAMI_PKG_CHMOD="-R g+rwX"
...
RUN bitnami-pkg unpack nginx-1.12.2-0 --checksum cb54ea083954cddbd3d9a93eeae0b81247176235c966a7b5e70abc3c944d4339
...
USER 1001
ENTRYPOINT ["/app-entrypoint.sh"]
CMD ["nginx","-g","daemon off;"]
Kubernetes
在Kubernetes中,创建非根容器需要在Pod的容器定义中设置securityContext。即通过设置runAsUser和runAsGroup字段来指定容器中进程的用户和组,以此创建非根容器。
同时,还需要在Dockerfile中使用USER指令将文件和目录的权限设置为非root用户和组,否则可能会在以非root用户身份运行容器时出现权限问题。
apiVersion: v1
kind: Pod
metadata:
name: non-root-container-pod
spec:
containers:
- name: non-root-container
image: my-non-root-image
securityContext:
runAsUser: 1000 # 指定非root用户
runAsGroup: 3000 # 指定非root组
参考
Why non-root containers are important for security (bitnami.com)