安全上下文
在生产环境中,往往需要对 Pod 的安全性进行设置,用户可以在 Pod 中通过安全上下文选项配置其安全性相关的特性。可以通过 pod.spec.securityContext
对 Pod 中的所有容器进行设置,或者通过 pod.spec.containers.securityContext
对 Pod 中指定的容器单独进行设置。
安全上下文主要包括以下可配置的选项:
指定容器中默认运行进程的用户(用户 ID);
阻止容器使用 root 用户运行(容器默认使用的用户通常在构建容器时指定,所以为了安全可能需要阻止容器以 root 用户运行);
使用特权模式运行容器,使其对宿主机节点的内核具有完全的访问权限;
通过添加或禁用内核功能,配置细粒度的内核访问权限;
设置 SELinux 选项,加强对容器的限制;
阻止进程写入容器的根文件系统;
指定容器中运行进程的默认用户
可以在 pod.spec.securityContext.runAsUser
中指定运行的用户 ID(若想单独为一个容器指定,则在 pod.spec.containers.securityContext.runAsUser
中指定即可 )。
🌰 创建一个 Pod,其中的名为 main 的容器中的默认运行用户 ID 修改为 405
,即 guest
用户:
查看创建的 Pod 中的容器的
id
命令:可以发现其 uid 被修改为 405,gid 也被分配为 uid 默认属于的组 ID
不同用户共享存储卷
Linux 中可以使用 ls -la
查看文件或目录的权限,其定义规范如下:
在 Pod 中,若有两个容器,且每个容器都是以不同的用户运行的,因此若想要两个用户均能对同一个存储卷进行操作,则可以 将这两个用户放入同一个组,再 修改组用户对卷设备的权限,这样就可以实现不同的用户均能对同一个卷设备中进行读写。
🕹 通过设置 pod.spec.securityContext.fsGroup
和 pod.spec.securityContext.supplementalGroups
可以将 Pod 中的容器中运行的用户划分进指定的用户组中,其中前者用于指定卷设备所属的组用户,两者都定义了用户关联的额外的用户组。
🌰 创建一个包含两个容器的 Pod,一个容器中是 1111
用户运行,另一个容器中则是 2222
用户运行,将这两个容器加入用户组 555
、666
、777
中,其中用户组 555
是 fsGroup
指定的,即卷设备的所属组 ID 为 555
:
创建完 Pod 后,观察 1111 用户的所属组信息,可以看到其所属组为 0, 555, 666, 777:
观察挂载的卷设备的信息如下,该卷设备属于用户 root,属于组 555,因此只要属于 555 组的用户均可以向其中读写:
1111 用户向其中创建一个名为 foo 的文件,并查看其权限如下:
该文件属于用户 1111 以及 用户组 555,且从其权限
rw-r--r--
可以知道,除了用户 1111 可以对其读写外,同属于用户组 555 的用户 2222 只可以对该文件进行读,而没有其他权限
阻止容器以 root 用户运行
可以在 pod.spec.securityContext.runAsNonRoot=true
中指定 Pod 中的容器必须以非 root 用户运行(若想单独为一个容器指定,则在 pod.spec.containers.securityContext.runAsNonRoot
中指定即可 ),在指定了该特性以后,若容器是以 root 用户运行的,则该 Pod 会一直无法进入 Ready 状态。
🌰 创建一个 Pod,使用镜像 alpine
,该镜像默认是使用的 root 用户,在 Pod 中定义阻止容器以 root 用户运行,创建该 Pod:
通过
kubectl get pod
可以看到没有 READY,其状态显示为CreateContainerConfigError
:通过
kubectl describe
可以看到其失败的详细原因为Error: container has runAsNonRoot and image will run as root
:
使用特权模式运行 Pod
可以在 pod.spec.securityContext.privileged=true
中指定 Pod 中的容器以特权模式运行(若想单独为一个容器指定,则在 pod.spec.containers.securityContext.privileged=true
中指定即可 )。
🌰 创建一个 Pod,开启特权模式:
为容器添加、禁用内核功能
相比于直接令容器以特权模式运行,赋予其所有权限的方法,更加安全的做法是只给它真正需要的内核功能权限,从而实现更精细粒度的权限控制。
添加内核功能
可以在 pod.spec.securityContext.capabilities.add
中指定为 Pod 中所有容器添加的内核功能(若想单独为一个容器指定,则在 pod.spec.containers.securityContext.capabilities.add
中指定即可 )。
🌰 默认不开启特权模式的情况下,容器是不允许修改系统时间的(因为修改容器的修改时间会影响其所在 Node 的系统时间),而提供该功能的内核功能名称为 CAP_SYS_TIME
。下面创建一个 Pod,为其中的容器添加该内核功能:
添加了该功能后,该 Pod 中的容器就可以通过
date
命令修改时间了
禁用内核功能
相对于上面的添加功能,将 add
改为 drop
即可,即可以在 pod.spec.securityContext.capabilities.drop
中指定为 Pod 中所有容器禁用的内核功能(若想单独为一个容器指定,则在 pod.spec.containers.securityContext.capabilities.drop
中指定即可 )。
🌰 默认情况下的容器可以使用 chown
命令修改容器中的文件的持有者,这是 CAP_CHOWN
内核功能提供的。下面创建一个 Pod,将该功能禁用:
禁用了该功能后,该 Pod 中的容器将无法使用
chown
命令修改文件的持有者
阻止对容器根文件系统的写入
可以在 pod.spec.securityContext.readOnlyRootFileSystem
中指定为 Pod 中所有容器添加的内核功能(若想单独为一个容器指定,则在 pod.spec.containers.securityContext.readOnlyRootFileSystem
中指定即可 )。
当指定了该特性之后,意味着 Pod 中的容器将只能对其根文件系统进行读取,而不能进行写入,因此往往需要为其提供 卷设备 以储存业务所需数据,注意该设备必须是可写的,否则通常情况下容器将无法正常满足业务场景的使用。
🌰 创建一个容器,并且阻止其对根文件系统的写入:
创建的容器将只能对挂载的卷设备进行写入操作,而对根文件系统则只能够读取
Last updated
Was this helpful?