容器安全

从安全的角度来看,Kubernetes 中包含如下图所示的潜在攻击面:

安全 - 图1

(图片来自《Kubernetes Security - Operating Kubernetes Clusters and Applications Safely》)

为了保证集群以及容器应用的安全,Kubernetes 提供了多种安全机制,限制容器的行为,减少容器和集群的攻击面,保证整个系统的安全性。

  • 集群安全,比如组件(如 kube-apiserver、etcd、kubelet 等)只开放安全 API并开启 TLS 认证、开启 RBAC 等;
  • Security Context:限制容器的行为,包括 Capabilities、ReadOnlyRootFilesystem、Privileged、RunAsNonRoot、RunAsUser 以及 SELinuxOptions 等;
  • Pod Security Policy:集群级的 Pod 安全策略,自动为集群内的 Pod 和 Volume 设置 Security Context;
  • Sysctls:允许容器设置内核参数,分为安全 Sysctls 和非安全 Sysctls;
  • AppArmor:限制应用的访问权限;
  • Network Policies:精细控制容器应用和集群中的网络访问;
  • Seccomp:Secure computing mode 的缩写,限制容器应用可执行的系统调用。

除此之外,推荐尽量使用较新版本的 Kubernetes,因为它们通常会包含常见安全问题的修复。你可以参考 kubernetes-announce 来查询最新的 Kubernetes 发布情况,也可以参考 cvedetails.com 查询 Kubernetes 各个版本的 CVE (Common Vulnerabilities and Exposures) 列表。

集群安全

  • Kubernetes 组件(如 kube-apiserver、etcd、kubelet 等)只开放安全 API 并开启 TLS 认证。
  • 开启 RBAC 授权,赋予容器应用最小权限,并开启 NodeRestriction 准入控制(限制 Kubelet 权限)。
    • RBAC 规则过多或者无法满足实际需要时,推荐使用 Open Policy Agent (OPA) 配置更灵活的访问策略
  • 开启 Secret 加密存储(Secret Encryption),并配置 etcd 的 TLS 认证;
  • 禁止 Kubelet 的匿名访问和只读端口,开启 Kubelet 的证书轮替更新(Certificate Rotation)。
  • 禁止默认 ServiceAccount 的 automountServiceAccountToken,并在需要时创建容器应用的专用 ServiceAccount。
  • 禁止 Dashboard 的匿名访问,通过 RBAC 限制 Dashboard 的访问权限,并确保 Dashboard 仅可在内网访问(通过 kubectl proxy)。
  • 定期运行 CIS Kubernetes Benchmark,确保集群的配置或更新符合最佳的安全实践(使用 kube-benchkube-hunter)。
  • 在多租户场景中,还可以使用 Kata Containers、gVisor 等对容器进程进行强隔离,或者使用 Istio、Linkerd 等对容器应用之间的通信也进行自动加密。

TLS 安全

为保障 TLS 安全,并避免 Zombie POODLE and GOLDENDOODLE Vulnerabilities,请为 TLS 1.2 禁止 CBC (Cipher Block Chaining) 模式。

你可以使用 https://www.ssllabs.com/ 来测试 TLS 的安全问题。

Security Context 和 Pod Security Policy

  1. apiVersion: extensions/v1beta1
  2. kind: PodSecurityPolicy
  3. metadata:
  4. name: restricted
  5. annotations:
  6. # Seccomp v1.11 使用 'runtime/default',而 v1.10 及更早版本使用 'docker/default'
  7. seccomp.security.alpha.kubernetes.io/allowedProfileNames: 'runtime/default'
  8. seccomp.security.alpha.kubernetes.io/defaultProfileName: 'runtime/default'
  9. apparmor.security.beta.kubernetes.io/allowedProfileNames: 'runtime/default'
  10. apparmor.security.beta.kubernetes.io/defaultProfileName: 'runtime/default'
  11. spec:
  12. privileged: false
  13. # Required to prevent escalations to root.
  14. allowPrivilegeEscalation: false
  15. # This is redundant with non-root + disallow privilege escalation,
  16. # but we can provide it for defense in depth.
  17. requiredDropCapabilities:
  18. - ALL
  19. # Allow core volume types.
  20. volumes:
  21. - 'configMap'
  22. - 'emptyDir'
  23. - 'projected'
  24. - 'secret'
  25. - 'downwardAPI'
  26. # Assume that persistentVolumes set up by the cluster admin are safe to use.
  27. - 'persistentVolumeClaim'
  28. hostNetwork: false
  29. hostIPC: false
  30. hostPID: false
  31. runAsUser:
  32. # Require the container to run without root privileges.
  33. rule: 'MustRunAsNonRoot'
  34. seLinux:
  35. # This policy assumes the nodes are using AppArmor rather than SELinux.
  36. rule: 'RunAsAny'
  37. supplementalGroups:
  38. rule: 'MustRunAs'
  39. ranges:
  40. # Forbid adding the root group.
  41. - min: 1
  42. max: 65535
  43. fsGroup:
  44. rule: 'MustRunAs'
  45. ranges:
  46. # Forbid adding the root group.
  47. - min: 1
  48. max: 65535
  49. readOnlyRootFilesystem: false

完整参考见这里

Sysctls

Sysctls 允许容器设置内核参数,分为安全 Sysctls 和非安全 Sysctls

  • 安全 Sysctls:即设置后不影响其他 Pod 的内核选项,只作用在容器 namespace 中,默认开启。包括以下几种
    • kernel.shm_rmid_forced
    • net.ipv4.ip_local_port_range
    • net.ipv4.tcp_syncookies
  • 非安全 Sysctls:即设置好有可能影响其他 Pod 和 Node 上其他服务的内核选项,默认禁止。如果使用,需要管理员在配置 kubelet 时开启,如 kubelet --experimental-allowed-unsafe-sysctls 'kernel.msg*,net.ipv4.route.min_pmtu'

Sysctls 在 v1.11 升级为 Beta 版,可以通过 PSP spec 直接设置,如

  1. apiVersion: policy/v1beta1
  2. kind: PodSecurityPolicy
  3. metadata:
  4. name: sysctl-psp
  5. spec:
  6. allowedUnsafeSysctls:
  7. - kernel.msg*
  8. forbiddenSysctls:
  9. - kernel.shm_rmid_forced

而 v1.10 及更早版本则为 Alpha 阶段,需要通过 Pod annotation 设置,如:

  1. apiVersion: v1
  2. kind: Pod
  3. metadata:
  4. name: sysctl-example
  5. annotations:
  6. security.alpha.kubernetes.io/sysctls: kernel.shm_rmid_forced=1
  7. security.alpha.kubernetes.io/unsafe-sysctls: net.ipv4.route.min_pmtu=1000,kernel.msgmax=1 2 3
  8. spec:
  9. ...

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/<container_name> 来设置。可选的值包括

  • runtime/default: 使用 Container Runtime 的默认配置
  • localhost/<profile_name>: 使用已加载到内核的 AppArmor profile
  1. $ sudo apparmor_parser -q <<EOF
  2. #include <tunables/global>
  3. profile k8s-apparmor-example-deny-write flags=(attach_disconnected) {
  4. #include <abstractions/base>
  5. file,
  6. # Deny all file writes.
  7. deny /** w,
  8. }
  9. EOF'
  10. $ kubectl create -f /dev/stdin <<EOF
  11. apiVersion: v1
  12. kind: Pod
  13. metadata:
  14. name: hello-apparmor
  15. annotations:
  16. container.apparmor.security.beta.kubernetes.io/hello: localhost/k8s-apparmor-example-deny-write
  17. spec:
  18. containers:
  19. - name: hello
  20. image: busybox
  21. command: ["sh", "-c", "echo'Hello AppArmor!'&& sleep 1h"]
  22. EOF
  23. pod "hello-apparmor" created
  24. $ kubectl exec hello-apparmor cat /proc/1/attr/current
  25. k8s-apparmor-example-deny-write (enforce)
  26. $ kubectl exec hello-apparmor touch /tmp/test
  27. touch: /tmp/test: Permission denied
  28. 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 的格式为

  1. $ cat /var/lib/kubelet/seccomp/chmod.json
  2. {
  3. "defaultAction": "SCMP_ACT_ALLOW",
  4. "syscalls": [
  5. {
  6. "name": "chmod",
  7. "action": "SCMP_ACT_ERRNO"
  8. }
  9. ]
  10. }

Seccomp 还在 alpha 阶段,需要通过 Pod annotation 设置,包括

  • security.alpha.kubernetes.io/seccomp/pod:应用到该 Pod 的所有容器
  • security.alpha.kubernetes.io/seccomp/container/<container name>:应用到指定容器

而 value 有三个选项

  • runtime/default: 使用 Container Runtime 的默认配置
  • unconfined: 允许所有系统调用
  • localhost/<profile-name>: 使用 Node 本地安装的 seccomp,需要放到 /var/lib/kubelet/seccomp 目录中

比如使用刚才创建的 seccomp 配置:

  1. apiVersion: v1
  2. kind: Pod
  3. metadata:
  4. name: trustworthy-pod
  5. annotations:
  6. seccomp.security.alpha.kubernetes.io/pod: localhost/chmod
  7. spec:
  8. containers:
  9. - name: trustworthy-container
  10. image: sotrustworthy:latest

kube-bench

kube-bench 提供了一个简单的工具来检查 Kubernetes 的配置(包括 master 和 node)是否符合最佳的安全实践(基于 CIS Kubernetes Benchmark)。

推荐所有生产环境的 Kubernetes 集群定期运行 kube-bench,保证集群配置符合最佳的安全实践。

安装 kube-bench

  1. $ docker run --rm -v `pwd`:/host aquasec/kube-bench:latest install
  2. $ ./kube-bench <master|node>

当然,kube-bench 也可以直接在容器内运行,比如通常对 Master 和 Node 的检查命令分别为:

  1. $ kubectl apply -f https://github.com/feiskyer/kubernetes-handbook/raw/master/examples/job-master.yaml
  2. job.batch/kube-bench-master created
  3. $ kubectl apply -f https://github.com/feiskyer/kubernetes-handbook/raw/master/examples/job-node.yaml
  4. job.batch/kube-bench-node created
  5. # Wait for a few seconds for the job to complete
  6. $ kubectl get pods
  7. NAME READY STATUS RESTARTS AGE
  8. kube-bench-master-k7jdd 0/1 Completed 0 2m15s
  9. kube-bench-node-p9sl9 0/1 Completed 0 2m15s
  10. # The results are held in the pod's logs
  11. $ kubectl logs kube-bench-master-k7jdd
  12. [INFO] 1 Master Node Security Configuration
  13. [INFO] 1.1 API Server
  14. ...

镜像安全

Clair

Clair 是 CoreOS 开源的容器安全工具,用来静态分析镜像中潜在的安全问题。推荐将 Clair 集成到 Devops 流程中,自动对所有镜像进行安全扫描。

安装 Clair 的方法为:

  1. git clone https://github.com/coreos/clair
  2. cd clair/contrib/helm
  3. helm dependency update clair
  4. helm install clair

Clair 项目本身只提供了 API,在实际使用中还需要一个客户端(或集成Clair的服务)配合使用。比如,使用 reg 的方法为

  1. # Install
  2. $ go get github.com/genuinetools/reg
  3. # Vulnerability Reports
  4. $ reg vulns --clair https://clair.j3ss.co r.j3ss.co/chrome
  5. # Generating Static Website for a Registry
  6. $ $ reg server --clair https://clair.j3ss.co

trivy

trivy 是 Aqua Security 开源的容器漏洞扫描工具。相对于 Clair 来说,使用起来更为简单,可以更方便集成到 CI 中。

  1. # Install
  2. sudo apt-get install wget apt-transport-https gnupg lsb-release
  3. wget -qO - https://aquasecurity.github.io/trivy-repo/deb/public.key | sudo apt-key add -
  4. echo deb https://aquasecurity.github.io/trivy-repo/deb $(lsb_release -sc) main | sudo tee -a /etc/apt/sources.list.d/trivy.list
  5. sudo apt-get update
  6. sudo apt-get install -y trivy
  7. # Image Scanning
  8. trivy python:3.4-alpine

其他工具

其他镜像安全扫描工具还有:

安全工具

开源产品:

商业产品

参考文档