0%

K8s-Security Context

Security Context 概述及配置

Security Context 概述

Security Context(安全上下文)用来限制容器对宿主节点的可访问范围,以避免容器非法操作宿主节点的系统级别的内容,使得节点的系统或者节点上其他容器组受到影响。

Security Context可以按照如下几种方式设定:

  • 访问权限控制:是否可以访问某个对象(例如文件)是基于 userID(UID)和 groupID(GID)的
  • Security Enhanced Linux (SELinux):为对象分配Security标签
  • 以 privileged(特权)模式运行
  • Linux Capabilities:为容器组(或容器)分配一部分特权,而不是 root 用户的所有特权
  • AppArmor:自 Kubernetes v1.4 以来,一直处于 beta 状态
  • Seccomp:过滤容器中进程的系统调用(system call)
  • AllowPrivilegeEscalation(允许特权扩大):此项配置是一个布尔值,定义了一个进程是否可以比其父进程获得更多的特权,直接效果是,容器的进程上是否被设置 no_new_privs 标记。当出现如下情况时,AllowPrivilegeEscalation 的值始终为 true:
    • 容器以 privileged 模式运行
    • 容器拥有 CAP_SYS_ADMIN 的 Linux Capability

为Pod设置Security Context

在 Pod 的定义中增加 securityContext 字段,即可为 Pod 指定 Security 相关的设定。 securityContext 字段是一个 PodSecurityContext 对象。通过该字段指定的内容将对该 Pod 中所有的容器生效。

Pod示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
apiVersion: v1
kind: Pod
metadata:
name: security-context-demo
spec:
securityContext:
runAsUser: 1000
runAsGroup: 3000
fsGroup: 2000
volumes:
- name: sec-ctx-vol
emptyDir: {}
containers:
- name: sec-ctx-demo
image: busybox
command: [ "sh", "-c", "sleep 1h" ]
volumeMounts:
- name: sec-ctx-vol
mountPath: /data/demo
securityContext:
allowPrivilegeEscalation: false

在上面的例子中:

  • spec.securityContext.runAsUser 字段指定了该 Pod 中所有容器的进程都以UserID 1000 的身份运行,spec.securityContext.runAsGroup 字段指定了该 Pod 中所有容器的进程都以GroupID 3000 的身份运行

    • 如果该字段被省略,容器进程的GroupID为 root(0)
    • 容器中创建的文件,其所有者为 userID 1000,groupID 3000
  • spec.securityContext.fsGroup 字段指定了该 Pod 的 fsGroup 为 2000

    • 数据卷 (本例中,对应挂载点 /data/demo 的数据卷为 sec-ctx-demo) 的所有者以及在该数据卷下创建的任何文件,其 GroupID 为 2000

执行Pod示例

  • 创建 Pod
1
2
[root@k8s-master 0425]# kubectl apply -f security-context-1.yaml 
pod/security-context-demo created
  • 验证 Pod 已运行
1
2
3
[root@k8s-master 0425]# kubectl get pod security-context-demo
NAME READY STATUS RESTARTS AGE
security-context-demo 1/1 Running 2 159m
  • 进入容器的命令行界面
1
[root@k8s-master 0425]# kubectl exec -it security-context-demo -- sh
  • 在该命令行界面中,查看正在运行的进程,所有的进程都以 user 1000 的身份运行(由 runAsUser 指定)
1
2
3
4
5
/ $ ps
PID USER TIME COMMAND
1 1000 0:00 sleep 1h
6 1000 0:00 sh
11 1000 0:00 ps
  • 切换到目录 /data,并查看目录中的文件列表,/data/demo 目录的 groupID 为 2000(由 fsGroup 指定)
1
2
3
4
/ $ cd /data/
/data $ ls -l
total 0
drwxrwsrwx 2 root 2000 6 Apr 25 06:42 demo
  • 在命令行界面中,切换到目录 /data/demo,并创建一个文件,testfile 的 groupID 为 2000 (由 FSGroup 指定),输出结果如下所示:
1
2
3
4
5
/ $ cd /data/demo/
/data/demo $ echo hello > testfile
/data/demo $ ls -l
total 4
-rw-r--r-- 1 1000 2000 6 Apr 25 09:19 testfile
  • 在命令行界面中执行 id 命令,输出结果如下所示:
1
2
/data/demo $ id
uid=1000 gid=3000 groups=2000
  • gid 为 3000,与 runAsGroup 字段所指定的一致
  • 如果 runAsGroup 字段被省略,则 gid 取值为 0(即 root),此时容器中的进程将可以操作 root Group 的文件

为容器设置Security Context

容器的定义中包含 securityContext 字段,该字段接受 SecurityContext 对象。通过指定该字段,可以为容器设定安全相关的配置,当该字段的配置与 Pod 级别的 securityContext 配置相冲突时,容器级别的配置将覆盖 Pod 级别的配置。容器级别的 securityContext 不影响 Pod 中的数据卷。

下面的示例中的 Pod 包含一个 Container,且 Pod 和 Container 都有定义 securityContext 字段:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
apiVersion: v1
kind: Pod
metadata:
name: security-context-demo-2
spec:
securityContext:
runAsUser: 1000
containers:
- name: sec-ctx-demo-2
image: busybox
command: [ "sh", "-c", "sleep 1h" ]
securityContext:
runAsUser: 2000
allowPrivilegeEscalation: false
  • 执行命令以创建 Pod
1
2
[root@k8s-master 0426]# kubectl apply -f security-context-demo-2.yaml 
pod/security-context-demo-2 created
  • 执行命令以验证容器已运行
1
2
3
[root@k8s-master 0426]# kubectl get pod security-context-demo-2
NAME READY STATUS RESTARTS AGE
security-context-demo-2 1/1 Running 0 8s
  • 执行命令进入容器的命令行界面:
1
2
3
4
5
6
[root@k8s-master 0426]# kubectl exec -it security-context-demo-2 -- sh
/ $ ps
PID USER TIME COMMAND
1 2000 0:00 sleep 1h
6 2000 0:00 sh
11 2000 0:00 ps

注意: 容器的进程以 userID 2000 的身份运行。该取值由 spec.containers[*].securityContext.runAsUser 容器组中的字段定义。Pod 中定义的 spec.securityContext.runAsUser 取值 1000 被覆盖。

为容器设置SELinux标签

Pod 或容器定义的 securityContextseLinuxOptions 字段是一个 SELinuxOptions 对象,该字段可用于为容器指定 SELinux 标签。如下所示:

1
2
3
securityContext:
seLinuxOptions:
level: "s0:c123,c456"

为容器指定 SELinux 标签时,宿主节点的 SELinux 模块必须加载。

关于数据卷

Pod 的 securityContext 作用于 Pod 中所有的容器,同时对 Pod 的数据卷也同样生效。具体来说,fsGroupseLinuxOptions 将被按照如下方式应用到 Pod 中的数据卷:

  • fsGroup:对于支持 ownership 管理的数据卷,通过 fsGroup 指定的 GID 将被设置为该数据卷的 owner,并且可被 fsGroup 写入。
  • seLinuxOptions:对于支持 SELinux 标签的数据卷,将按照 seLinuxOptions 的设定重新打标签,以使 Pod 可以访问数据卷内容。通常只需要设置 seLinuxOptionslevel 这一部分内容。该设定为 Pod 中所有容器及数据卷设置 Multi-Category Security (MCS) 标签。