赞
踩
目录
在云原生时代,Kubernetes 已经成为容器编排的事实标准,提供了强大的功能以支持各种规模和复杂度的应用部署。然而,随着 Kubernetes 在企业中的广泛应用,安全性问题也日益凸显。为了确保集群安全,我们必须对运行在 Kubernetes 中的容器和 Pod 进行严格的安全管控。Pod 安全上下文(Security Context)是 Kubernetes 提供的关键特性之一,它允许在 Pod 和容器级别设置安全相关的参数,以实现对容器的细粒度安全控制。
本文将探讨 Pod 安全上下文的核心概念、应用场景、操作方法及其在实际环境中的应用。从以非 Root 用户运行容器的好处、限制容器的特权模式的必要性、设置只读文件系统的优点,以及如何利用 Linux Capabilities 进行更细粒度的权限控制等方面进行探讨。通过合理配置这些安全机制,我们可以显著提高 Kubernetes 集群的安全性,降低潜在的安全威胁。
在Kubernetes中,Pod安全上下文(Security Context)是一种提供安全机制的重要特性,它允许用户在Pod和容器级别设置特权和访问控制。通过合理配置安全上下文,我们可以增强应用程序的安全性,降低容器逃逸和提权等安全风险。
安全上下文主要从以下几个维度对Pod和容器进行限制:
其中一些安全机制可以在Pod级别进行设置,作用于Pod内的所有容器;而有些则可以在容器级别进行更细粒度的控制。通常,容器级别的安全设置可以覆盖Pod级别的设置。
默认情况下,容器中的应用程序都是以Root用户运行的。然而容器内的Root用户与宿主机的Root用户权限相当,拥有对Linux内核的大部分系统调用权限,存在一定的安全隐患。因此,我们应该尽量避免使用Root用户运行容器进程,转而使用普通用户以最小权限原则运行。
设置普通用户可以通过以下两种方式实现:
1、在Dockerfile中使用USER指令指定运行用户
Dockerfile
- FROM ubuntu:20.04
- RUN useradd -m appuser
- USER appuser #设置运行用户为appuser
- CMD ["sleep", "infinity"]
2、在Pod的spec.securityContext或containers[].securityContext字段中设置runAsUser,指定容器的默认用户UID,在spec下层级设置(pod级别),在containers下层级设置(container级别)。需要注意的是,普通用户的UID默认从1000开始分配,而Root用户的UID为0
在pod级别设置
- apiVersion: v1
- kind: Pod
- metadata:
- name: security-context-user-example
- spec:
- securityContext:
- runAsUser: 1000
- containers:
- - name: app
- image: ubuntu:20.04
- command: ["sleep", "infinity"]
在容器级别设置
- apiVersion: v1
- kind: Pod
- metadata:
- name: container-user-example
- spec:
- containers:
- - name: app
- image: ubuntu:20.04
- command: ["sleep", "infinity"]
- securityContext:
- runAsUser: 1000
某些容器化应用可能需要访问宿主机设备、修改内核参数等敏感操作,这时候可能会启用特权模式(privileged mode)。然而,开启特权模式就意味着容器几乎拥有了访问Linux内核的所有能力,极大地增加了安全风险。
为了在授予容器必要权限的同时最小化安全风险,我们可以使用Linux Capabilities机制,更细粒度地控制容器对宿主机内核的访问能力,避免直接使用privileged模式。
打开特权模式Yaml(如果不设置,默认为关闭)
- apiVersion: v1
- kind: Pod
- metadata:
- name: privileged-pod-example
- spec:
- containers:
- - name: privileged-container
- image: ubuntu:20.04
- command: ["sleep", "infinity"]
- securityContext:
- privileged: true
使用Capabilities机制,只给容器分配必需的内核能力,而不是直接使用特权模式
在容器的securityContext中,首先使用capabilities.drop字段删除了容器的所有Capabilities。这一步相当于从容器中收回了所有的特权,使其权限降到最低。
接下来,使用capabilities.add字段,只为容器添加了NET_RAW这一种Capability。NET_RAW允许容器使用原始套接字(RAW Sockets),这是执行ping命令所必需的能力。
有了NET_RAW,就可以在容器内执行ping命令了:
- apiVersion: v1
- kind: Pod
- metadata:
- name: cap-net-raw-example
- spec:
- containers:
- - name: ping-container
- image: alpine:3.14
- command: ["sleep", "infinity"]
- securityContext:
- capabilities:
- drop:
- - ALL
- add: ["NET_RAW"]
在某些场景下,容器只需要读取持久化数据,而不需要对其进行修改。这时我们可以在容器的安全上下文中设置readOnlyRootFilesystem参数为true,将容器的根文件系统挂载为只读模式。这样即使容器中存在恶意程序,它也无法创建或修改容器内的文件,一定程度上保障了宿主机的安全。
在容器的securityContext中设置了readOnlyRootFilesystem: true,这会将容器的根文件系统挂载为只读模式。在只读模式下,容器内的进程无法对根文件系统进行任何写操作,包括创建、修改和删除文件。
- apiVersion: v1
- kind: Pod
- metadata:
- name: readonly-pod-example
- spec:
- containers:
- - name: readonly-container
- image: nginx:1.21
- securityContext:
- readOnlyRootFilesystem: true
- volumeMounts:
- - name: temp-volume
- mountPath: /tmp
- - name: logs-volume
- mountPath: /var/log/nginx
- volumes:
- - name: temp-volume
- emptyDir: {}
- - name: logs-volume
- emptyDir: {}
设置只读文件系统是提高容器安全性的一种有效手段,特别适用于无状态的应用程序。合理使用这一特性,结合必要的读写卷,可以在不影响功能的前提下,最小化容器的攻击面,提供更强的安全保证。
Linux Capabilities是在Linux内核2.2版本中引入的一种权限控制机制,用于实现比传统超级用户更细粒度的权限划分。在传统的Unix权限模型中,进程或者要完全拥有Root权限,或者完全没有特权。而Capabilities将Root权限划分成了不同的能力,例如修改文件所有者、挂载文件系统、设置系统时间等,进程可以只拥有其中一部分能力,减少潜在的安全风险。
目前Linux内核定义了40多种不同的Capability,可以通过man 7 capabilities命令查看完整列表。下面列举一些常见的Capabilities:
overview of Linux capabilities:capabilities(7) - Linux manual page
在Kubernetes中,我们可以通过Pod或Container的securityContext.capabilities字段来添加或删除容器的Capabilities。
示例1:为容器添加SYS_TIME能力
在这个例子中,通过capabilities.add字段为容器添加了SYS_TIME能力,使其可以修改系统时间,同时移除了其他非必要的特权。
- apiVersion: v1
- kind: Pod
- metadata:
- name: cap-add-example
- spec:
- containers:
- - name: example
- image: centos:7
- command: ["/bin/sleep", "999999"]
- securityContext:
- capabilities:
- add: ["SYS_TIME"]
示例2:删除容器的所有Capabilities
这个例子使用capabilities.drop字段移除了容器的所有Capabilities,将其权限降至最低,这种做法适用于对安全要求很高,应用程序也不需要任何特权的场景。
- apiVersion: v1
- kind: Pod
- metadata:
- name: cap-drop-example
- spec:
- containers:
- - name: example
- image: centos:7
- command: ["/bin/sleep", "999999"]
- securityContext:
- capabilities:
- drop:
- - ALL
示例3:设置容器默认的Capabilities
在这个例子中,在Pod级别的securityContext中删除了所有默认的Capabilities,然后只添加了容器必需的NET_BIND_SERVICE能力(允许绑定到低于1024的端口)。这个配置会作用于Pod内的所有容器。
- apiVersion: v1
- kind: Pod
- metadata:
- name: cap-default-example
- spec:
- containers:
- - name: example
- image: centos:7
- command: ["/bin/sleep", "999999"]
- securityContext:
- capabilities:
- drop:
- - ALL
- add: ["NET_BIND_SERVICE"]
Pod安全上下文是Kubernetes提供的一种细粒度的安全机制,管理员和开发者应该合理利用这一特性,在提供必要权限的同时遵循最小权限原则。通过以普通用户运行容器、限制特权模式、设置文件系统只读等方法,再辅以Linux Capabilities进行精细化控制,多管齐下,可以全面提升Kubernetes集群内的容器安全性,使其更加适应生产环境的需求。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。