容器安全
Kubernetes提供了多种机制来限制容器的行为,减少容器攻击面,保证系统安全性。
- Security Context:限制容器的行为,包括Capabilities、ReadOnlyRootFilesystem、Privileged、RunAsNonRoot、RunAsUser以及SELinuxOptions等
- Pod Security Policy:集群级的Pod安全策略,自动为集群内的Pod和Volume设置Security Context
- Sysctls:允许容器设置内核参数,分为安全Sysctls和非安全Sysctls
- AppArmor:限制应用的访问权限
- Seccomp:Secure computing mode的缩写,限制容器应用可执行的系统调用
Security Context 安全上下文
Security Context的目的是限制不可信容器的行为,保护系统和其他容器不受其影响。 Kubernetes提供了三种配置Security Context的方法:
- Container-level Security Context:仅应用到指定的容器
- Pod-level Security Context:应用到Pod内所有容器以及Volume
- Pod Security Policies(PSP):应用到集群内部所有Pod以及Volume
Container-level Security Context
Container-level Security Context仅应用到指定的容器上,并且不会影响Volume。比如设置容器运行在特权模式:
apiVersion: v1
kind: Pod
metadata:
name: hello-world
spec:
containers:
- name: hello-world-container
# The container definition
# ...
securityContext:
privileged: true
Pod-level Security Context
Pod-level Security Context应用到Pod内所有容器,并且还会影响Volume(包括fsGroup和selinuxOptions)。
apiVersion: v1
kind: Pod
metadata:
name: hello-world
spec:
containers:
# specification of the pod's containers
# ...
securityContext:
fsGroup: 1234
supplementalGroups: [5678]
seLinuxOptions:
level: "s0:c123,c456"
Pod Security Policies(PSP)
Pod Security Policies(PSP)是集群级的Pod安全策略,自动为集群内的Pod和Volume设置Security Context。 使用PSP需要API Server开启extensions/v1beta1/podsecuritypolicy,并且配置PodSecurityPolicy admission控制器。 支持的控制项
控制项 | 说明
privileged | 运行特权容器
defaultAddCapabilities | 可添加到容器的Capabilities
requiredDropCapabilities |会从容器中删除的Capabilities
volumes| 控制容器可以使用哪些volume
hostNetwork| host网络
hostPorts |允许的host端口列表
hostPID| 使用host PID namespace
hostIPC| 使用host IPC namespace
seLinux | SELinux Context
runAsUser| user ID
supplementalGroups |允许的补充用户组
fsGroup| volume FSGroup
readOnlyRootFilesystem |只读根文件系统
示例
限制容器的host端口范围为8000-8080:
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:
- '*'
SELinux
SELinux (Security-Enhanced Linux) 是一种强制访问控制(mandatory access control)的实现。它的作法是以最小权限原则(principle of least privilege)为基础,在Linux核心中使用Linux安全模块(Linux Security Modules)。SELinux主要由美国国家安全局开发,并于2000年12月22日发行给开放源代码的开发社区。 可以通过runcon来为进程设置安全策略,ls和ps的-Z参数可以查看文件或进程的安全策略。
开启与关闭SELinux
修改/etc/selinux/config文件方法:
开启:SELINUX=enforcing
关闭:SELINUX=disabled
通过命令临时修改:
开启:setenforce 1
关闭:setenforce 0
查询SELinux状态:getenforce
示例
apiVersion: v1
kind: Pod
metadata:
name: hello-world
spec:
containers:
- image: gcr.io/google_containers/busybox:1.24
name: test-container
command:
- sleep
- "6000"
volumeMounts:
- mountPath: /mounted_volume
name: test-volume
restartPolicy: Never
hostPID: false
hostIPC: false
securityContext:
seLinuxOptions:
level: "s0:c2,c3"
volumes:
- name: test-volume
emptyDir: {}
这会自动给docker容器生成如下的HostConfig.Binds:
/var/lib/kubelet/pods/f734678c-95de-11e6-89b0-42010a8c0002/volumes/kubernetes.io~empty-dir/test-volume:/mounted_volume:Z
/var/lib/kubelet/pods/f734678c-95de-11e6-89b0-42010a8c0002/volumes/kubernetes.io~secret/default-token-88xxa:/var/run/secrets/kubernetes.io/serviceaccount:ro,Z
/var/lib/kubelet/pods/f734678c-95de-11e6-89b0-42010a8c0002/etc-hosts:/etc/hosts
对应的volume也都会正确设置SELinux:
$ ls -Z /var/lib/kubelet/pods/f734678c-95de-11e6-89b0-42010a8c0002/volumes
drwxr-xr-x. root root unconfined_u:object_r:svirt_sandbox_file_t:s0:c2,c3 kubernetes.io~empty-dir
drwxr-xr-x. root root unconfined_u:object_r:svirt_sandbox_file_t:s0:c2,c3 kubernetes.io~secret
关于SELinux的介绍可以参考: 图文教程:SELinux政策实施详解 这篇文章以漫画的形式来讲解 , 深入浅出
Sysctls
sysctl接口允许允许管理员在系统运行的状态下动态修改内核参数。 设置的参数在/proc/sys下可以看到。 其配置参数包含了多个Linux的多个子系统,比如:
- kernel(以kernel.开头的参数)
- networking(以net.开头的参数)
- virtual memory (以vm.开头的参数)
- MDADM (以dev.开头的参数)
namespaced 和 node-level 的sysctl参数: namespaced级别的sysctl参数运行每个pod各自配置而不冲突。 要在pod的语境里(编排文件中)使用, 必须namespaced级别的sysctl, 这些sysctl参数包括:
- kernel.shm*,
- kernel.msg*,
- kernel.sem,
- fs.mqueue.*,
- net.*. 对于node-level级别的sysctl参数,比如vm.开头,dev.开头的参数, 如果要进行设置,需要管理员在node节点上配置(比如写node的/etc/sysctl.conf文件),或者用DaemonSet启动一个有系统特权的容器来进行设置。 Sysctls允许容器设置内核参数,分为安全Sysctls和非安全Sysctls
- 安全Sysctls:即设置后不影响其他Pod的内核选项,只作用在容器namespace中,默认开启。包括以下几种
- kernel.shm_rmid_forced : 这个参数启用后,会销毁未被使用的共享内存, 不要轻易开启
- net.ipv4.ip_local_port_range: 表示用于向外连接的端口范围。缺省情况下很小:32768到61000
- net.ipv4.tcp_syncookies: 表示开启SYN Cookies。当出现SYN等待队列溢出时,启用cookies来处理,可防范少量SYN攻击,默认为0,表示关闭
- 非安全Sysctls:即设置好有可能影响其他Pod和Node上其他服务的内核选项,默认禁止。如果使用,需要管理员在配置kubelet时开启,如kubelet --experimental-allowed-unsafe-sysctls 'kernel.msg*,net.ipv4.route.min_pmtu'
Sysctls还在alpha阶段,需要通过Pod annotation设置,如:
apiVersion: v1 kind: Pod metadata: name: sysctl-example annotations: security.alpha.kubernetes.io/sysctls: kernel.shm_rmid_forced=1 security.alpha.kubernetes.io/unsafe-sysctls: net.ipv4.route.min_pmtu=1000,kernel.msgmax=1 2 3 spec: ...
关于sysctl的介绍可以参考sysctl.conf学习和调优 和 设置Linux内核参数 /etc/sysctl.conf
AppArmor
AppArmor(Application Armor)是Linux内核的一个安全模块,允许系统管理员将每个程序与一个安全配置文件关联,从而限制程序的功能。通过它你可以指定程序可以读、写或运行哪些文件,是否可以打开网络端口等。作为对传统Unix的自主访问控制模块的补充,AppArmor提供了强制访问控制机制。 在使用AppArmor之前需要注意
- Kubernetes版本>=v1.4
- apiserver和kubelet已开启AppArmor特性,--feature-gates=AppArmor=true
- 已开启apparmor内核模块,通过cat /sys/module/apparmor/parameters/enabled查看
- 仅支持docker container runtime
- AppArmor profile已经加载到内核,通过cat /sys/kernel/security/apparmor/profiles查看
AppArmor还在alpha阶段,需要通过Pod annotation container.apparmor.security.beta.kubernetes.io/
来设置。可选的值包括 - runtime/default: 使用Container Runtime的默认配置
- localhost/
: 使用已加载到内核的AppArmor profile
$ sudo apparmor_parser -q <<EOF
#include <tunables/global>
profile k8s-apparmor-example-deny-write flags=(attach_disconnected) {
#include <abstractions/base>
file,
# Deny all file writes.
deny /** w,
}
EOF'
$ kubectl create -f /dev/stdin <<EOF
apiVersion: v1
kind: Pod
metadata:
name: hello-apparmor
annotations:
container.apparmor.security.beta.kubernetes.io/hello: localhost/k8s-apparmor-example-deny-write
spec:
containers:
- name: hello
image: busybox
command: [ "sh", "-c", "echo 'Hello AppArmor!' && sleep 1h" ]
EOF
pod "hello-apparmor" created
$ kubectl exec hello-apparmor cat /proc/1/attr/current
k8s-apparmor-example-deny-write (enforce)
$ kubectl exec hello-apparmor touch /tmp/test
touch: /tmp/test: Permission denied
error: error executing remote command: command terminated with non-zero exit code: Error executing in Docker Container: 1
Seccomp
Seccomp是Secure computing mode的缩写,它是Linux内核提供的一个操作,用于限制一个进程可以执行的系统调用.Seccomp需要有一个配置文件来指明容器进程允许和禁止执行的系统调用。 在Kubernetes中,需要将seccomp配置文件放到/var/lib/kubelet/seccomp目录中(可以通过kubelet选项--seccomp-profile-root修改)。比如禁止chmod的格式为
$ cat /var/lib/kubelet/seccomp/chmod.json
{
"defaultAction": "SCMP_ACT_ALLOW",
"syscalls": [
{
"name": "chmod",
"action": "SCMP_ACT_ERRNO"
}
]
}
Seccomp还在alpha阶段,需要通过Pod annotation设置,包括:
- security.alpha.kubernetes.io/seccomp/pod:应用到该Pod的所有容器
- security.alpha.kubernetes.io/seccomp/container/
:应用到指定容器
而value有三个选项:
- runtime/default: 使用Container Runtime的默认配置
- unconfined: 允许所有系统调用
- localhost/
: 使用Node本地安装的seccomp,需要放到/var/lib/kubelet/seccomp目录中
比如使用刚才创建的seccomp配置:
apiVersion: v1
kind: Pod
metadata:
name: trustworthy-pod
annotations:
seccomp.security.alpha.kubernetes.io/pod: localhost/chmod
spec:
containers:
- name: trustworthy-container
image: sotrustworthy:latest
参考文献
容器安全 Kubernetes集群安全配置案例 轻松了解Kubernetes认证功能 Kubernetes技术分析之安全 Kubernetes双向TLS配置-Centos7