一、kubernetes资源对象之security context
Security Context,即安全上下文,用于定义Pod或Container的权限和访问控制。
Kubernetes 提供了三种配置 Security Context 的方法:
Container-level Security Context:应用于容器级别
Pod-level Security Context:应用于Pod级别
Pod Security Policy:应用于集群级别
安全上下文(Security Context)定义 Pod 或 Container 的特权与访问控制设置。安全上下文包括但不限于:
自主访问控制(Discretionary Access Control):基于用户 ID(UID)和组 ID(GID)来判定对对象(例如文件)的访问权限。
安全性增强的 Linux(SELinux):为对象赋予安全性标签。
以特权模式或者非特权模式运行。
Linux 权能:为进程赋予 root 用户的部分特权而非全部特权。
AppArmor:使用程序框架来限制个别程序的权能。
Seccomp:过滤进程的系统调用。
AllowPrivilegeEscalation:控制进程是否可以获得超出其父进程的特权。 此布尔值直接控制是否为容器进程设置 no_new_privs 标志。当容器以特权模式运行或者具有 CAP_SYS_ADMIN 权能时,AllowPrivilegeEscalation 总是为 true。
readOnlyRootFilesystem:以只读方式加载容器的根文件系统。
SecurityContext 可以应用于 Container 和 Pod 维度:
在 Pod 上设置的安全性配置会应用到 Pod 中所有 Container 上,并且会还会影响 Volume
在 Container 上设置的安全性配置仅适用于该容器本身,不会影响到其他容器以及 Pod 的 Volume
1.1、容器级别
仅应用到指定的容器上,并且不会影响 Volume;
apiVersion: v1
kind: Pod
metadata:
name: hello-world
spec:
containers:
- name: hello-world-container
securityContext:
privileged: true
1.2、Pod级别
应用到 Pod 内所有容器,会影响 Volume;
1
2
3
4
5
6
7
8
9
10
11
apiVersion: v1
kind: Pod
metadata:
name: hello-world
spec:
containers:
securityContext:
fsGroup: 1234
supplementalGroups: [5678]
seLinuxOptions:
level: "s0:c123,c456"
1.3、PSP集群级别
PSP 是集群级的 Pod 安全策略,自动为集群内的 Pod 和 Volume 设置 Security Context;
支持的控制项
RunAsUser
MustRunAs - 必须配置一个 range。使用该范围内的第一个值作为默认值。验证是否不在配置的该范围内。
MustRunAsNonRoot - 要求提交的 Pod 具有非零 runAsUser 值,或在镜像中定义了 USER 环境变量。不提供默认值。
RunAsAny - 没有提供默认值。允许指定任何 runAsUser 。
SELinux
MustRunAs - 如果没有使用预分配的值,必须配置 seLinuxOptions。默认使用 seLinuxOptions。
RunAsAny - 没有提供默认值。允许任意指定的 seLinuxOptions ID。
SupplementalGroups
MustRunAs - 至少需要指定一个范围。默认使用第一个范围的最小值。
RunAsAny - 没有提供默认值。允许任意指定的 supplementalGroups ID
FSGroup
MustRunAs - 至少需要指定一个范围。默认使用第一个范围的最小值。
RunAsAny - 没有提供默认值。允许任意指定的 fsGroup ID
主机网络
HostPorts , 默认为 empty。HostPortRange 列表通过 min(包含) and max(包含) 来定义,指定了被允许的主机端口。
允许的主机路径
AllowedHostPaths 是一个被允许的主机路径前缀的白名单。空值表示所有的主机路径都可以使用。
控制卷
通过设置 PSP 卷字段,能够控制具体卷类型的使用。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
apiVersion: extensions/v1beta1
kind: PodSecurityPolicy
metadata:
name: permissive
spec:
seLinux:
rule: RunAsAny
supplementalGroups:
rule: RunAsAny
runAsUser:
rule: RunAsAny
fsGroup:
rule: RunAsAny
hostPorts:
- min: 8000
max: 8080
volumes:
- '*'
二、应用场景
2.1、自定义对象访问权限
也就是上文中提到的自主访问控制(Discretionary Access Control),通过设置 UID 和 GID 来达到限制容器权限的目的。
1
2
3
4
5
6
...
securityContext:
runAsUser: 1000
runAsGroup: 3000
fsGroup: 2000
...
如上这个配置,可以看到 Pod 中所有容器内的进程都是已用户 uid=1000 和主组 gid=3000来运行的,而创建的任何文件的属组都是 groups=2000。通过这样的方法,可以达到让用户的进程不使用默认的 Root (uid=0,gid=0)权限的目的。
附文:
要解决容器运行环境问题可以从两方面入手
1.从构建镜像的角度下手
将非root用户添加到Dockerfile
# RUN命令执行创建用户和用户组(命令创建了一个用户newuser设定ID为5000,并指定了用户登录后使用的主目录和shell)
RUN groupadd --gid 5000 newuser \
&& useradd --home-dir /home/newuser --create-home --uid 5000 --gid 5000 --shell /bin/sh --skel /dev/null newuser
# 指定用户,从这一行往下开始的每个命令都是以newuser身份而不是root身份运行(比如后面的CMD、EntryPoint)
USER newuser
在实际项目应用中,并不是所有要运行的镜像都是我们自己构建的。我们还使用了许多第三方镜像,这种情况我们无法像上面那样直接设定用户。
这些第三方Docker镜像默认情况下一般都是以root用户身份运行,除非我们对其进行处理。
如果是你用K8S,则Kubernetes中Pod安全上下文和Pod安全策略,可以帮助我们以非root身份运行镜像。
2.从K8S启动容器的角度下手
可以使用Pod安全上下文,将Pod的执行限制为特定的非root用户。
通过Pod构建文件中添加securityContext来配置Pod的安全设置。
如下示例:
apiVersion: v1
kind: Pod
metadata:
name: pod-helloworld
spec:
securityContext:
runAsNonRoot: true
runAsUser: 5000
runAsGroup: 5000
fsGroup: 5000
runAsUser指定Pod内的任何容器仅以userID为5000的运行,runAsGroup指定的容器内所有进程的组ID(组ID不指定默认为0)。
你可以先进入容器,然后使用 ps 命令查看进程的用户。
关于Pod的更多安全策略可以详见 http://docs.kubernetes.org.cn/690.html#FSGroup
查看容器当前用户的命令可以使用 whoami 或者 ps -aux
之所以出现这个问题,有两个原因:一是docker容器本质是宿主机服务器上的一个进程,不做特殊处理的情况下,容器里的root用户和宿主机上的root用户实际上是同一个用户;二是docker存在一个守护进程,即使用systemctl start docker启动的那个服务进程。因为我们安装docker是root用户安装的,该守护进程也是用root用户启动的,即使容器是非root用户运行的也存在较大的安全问题,是docker安全性问题的重要风险点。
解决这个问题有两个通用方法:就是容器用户与宿主机用户的id段映射;二是使用非root用户搭建docker并启动守护进程。
————————————————
版权声明:本文为CSDN博主「Lucas Tang」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_47961772/article/details/127111287