加固指南旨在与特定版本的 CIS Kubernetes Benchmark,Kubernetes 和 Rancher 一起使用:

点击这里下载 PDF 版本的加固指南

下面的安全加固指南是针对在生产环境的 Rancher v2.3.5 中使用 Kubernetes v1.15 版本的集群。它概述了如何满足互联网安全中心(CIS)提出的 Kubernetes 安全标准。

有关如果根据官方 CIS 基准评估集群的更多详细信息,请参阅。

已知问题

如果注册自定义节点时只提供了公共 IP,在 CIS 1.5 加固设置中,将无法正常在 Rancher UI 中使用执行命令行查看日志功能。如果想要使用上述两个功能,请在注册自定义节点时提供私有 IP 地址。

  • 如果注册自定义节点时只提供了公共 IP,在 CIS 1.5 加固设置中,将无法正常在 Rancher UI 中使用执行命令行查看日志功能。如果想要使用上述两个功能,请在注册自定义节点时提供私有 IP 地址。
  • restricted时,Rancher 在默认的 service account 中创建角色绑定集群角色绑定。CIS 1.5 要求默认 service account 没有绑定任何角色,不提供 service account 的 token,不分配特定的权限。

配置内核运行时参数

对于集群中的所有类型的节点,都建议使用以下的sysctl配置。在/etc/sysctl.d/90-kubelet.conf中设置以下参数:

执行sysctl -p /etc/sysctl.d/90-kubelet.conf来启用配置。

要创建etcd组,请运行以下控制台命令。

  1. addgroup --gid 52034 etcd
  2. useradd --comment "etcd service account" --uid 52034 --gid 52034 etcd

使用etcd用户的uidgid更新 RKE 的 config.yml文件:

  1. services:
  2. etcd:
  3. gid: 52034
  4. uid: 52034

将default服务账号的automountServiceAccountToken设置为 false。

Kubernetes 提供了一个默认服务账号(Service Account),如果集群的工作负载中没有为 Pod 分配任何特定服务账号,那么它将会使用这个default的服务账号。在需要从 Pod 访问 Kubernetes API 的情况下,应为该 Pod 创建一个特定的服务账号,并向该服务账号授予权限。这个default的服务账户应该被设置为不提供服务账号令牌(service account token)和任何权限。将automountServiceAccountToken设置为 false 之后,Kubernetes 在启动 Pod 时,将不会自动注入default服务账户。

对于每个命名空间中的,default服务账号必须包含以下值:

把下面的 yaml 另存为account_update.yaml

  1. apiVersion: v1
  2. kind: ServiceAccount
  3. metadata:
  4. name: default
  5. automountServiceAccountToken: false

创建一个名称为account_update.sh的脚本。通过运行chmod +x account_update.sh,使这个脚本有执行权限。

  1. #!/bin/bash -e
  2. for namespace in $(kubectl get namespaces -A -o json | jq -r '.items[].metadata.name'); do
  3. kubectl patch serviceaccount default -n ${namespace} -p "$(cat account_update.yaml)"
  4. done

确保所有命名空间均已定义网络策略

在同一个 Kubernetes 集群上运行不同的应用程序会产生一个风险,那就是应用可能受到相邻应用程序的攻击。为了确保容器只能与预期的容器进行通信,网络细分是必不可少的。通过设置网络策略(Network Policy),可以设置哪些 Pod 之间可以通信,以及是否可以和其他网络端点进行通信。

在集群上启用 CN​​I 插件后,您可以设置一个默认的网络策略。下面是一个宽松的网络策略示例,仅供参考。如果您想要允许到某个命名空间内所有 Pod 的流量(即使已经添加了一些策略,使得一些 Pods 被隔离了),您可以创建一个策略,明确允许该命名空间中的所有流量。将以下yaml另存为 default-allow-all.yaml。额外关于网络策略的信息,请查看Kubernetes 官方文档

:::important 重要 这个NetworkPolicy示例不建议在生产环境中使用。 :::

创建一个名称为apply_networkPolicy_to_all_ns.sh的脚本。通过运行chmod +x apply_networkPolicy_to_all_ns.sh,使这个脚本有执行权限。

  1. #!/bin/bash -e
  2. for namespace in $(kubectl get namespaces -A -o json | jq -r '.items[].metadata.name'); do
  3. kubectl apply -f default-allow-all.yaml -n ${namespace}
  4. done

运行脚本,以使全部的命名空间使用这个default-allow-all.yaml文件中的宽松NetworkPolicy

您可以用这个供您参考的cluster.yml,通过 RKE CLI 来创建安全加固的 Rancher Kubernetes Engine(RKE)集群。有关每个配置的详细信息,请参阅。

  1. # 如果您打算在离线环境中部署Kubernetes,
  2. # 请查阅有关如何配置自定义RKE镜像的文档。
  3. kubernetes_version: "v1.15.9-rancher1-1"
  4. enable_network_policy: true
  5. default_pod_security_policy_template_id: "restricted"
  6. services:
  7. etcd:
  8. uid: 52034
  9. gid: 52034
  10. kube-api:
  11. pod_security_policy: true
  12. secrets_encryption_config:
  13. enabled: true
  14. audit_log:
  15. enabled: true
  16. admission_configuration:
  17. event_rate_limit:
  18. enabled: true
  19. kube-controller:
  20. extra_args:
  21. feature-gates: "RotateKubeletServerCertificate=true"
  22. scheduler:
  23. image: ""
  24. extra_args: {}
  25. extra_binds: []
  26. extra_env: []
  27. kubelet:
  28. generate_serving_certificate: true
  29. extra_args:
  30. feature-gates: "RotateKubeletServerCertificate=true"
  31. protect-kernel-defaults: "true"
  32. tls-cipher-suites: "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305,TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,TLS_RSA_WITH_AES_256_GCM_SHA384,TLS_RSA_WITH_AES_128_GCM_SHA256"
  33. extra_binds: []
  34. extra_env: []
  35. cluster_domain: ""
  36. infra_container_image: ""
  37. cluster_dns_server: ""
  38. fail_swap_on: false
  39. kubeproxy:
  40. image: ""
  41. extra_args: {}
  42. extra_binds: []
  43. extra_env: []
  44. network:
  45. plugin: ""
  46. options: {}
  47. mtu: 0
  48. node_selector: {}
  49. authentication:
  50. strategy: ""
  51. sans: []
  52. webhook: null
  53. addons: |
  54. ---
  55. apiVersion: v1
  56. kind: Namespace
  57. metadata:
  58. name: ingress-nginx
  59. ---
  60. apiVersion: rbac.authorization.k8s.io/v1
  61. kind: Role
  62. metadata:
  63. name: default-psp-role
  64. namespace: ingress-nginx
  65. rules:
  66. - apiGroups:
  67. - extensions
  68. resourceNames:
  69. - default-psp
  70. resources:
  71. verbs:
  72. - use
  73. ---
  74. apiVersion: rbac.authorization.k8s.io/v1
  75. metadata:
  76. name: default-psp-rolebinding
  77. namespace: ingress-nginx
  78. roleRef:
  79. apiGroup: rbac.authorization.k8s.io
  80. kind: Role
  81. name: default-psp-role
  82. subjects:
  83. - apiGroup: rbac.authorization.k8s.io
  84. kind: Group
  85. name: system:serviceaccounts
  86. - apiGroup: rbac.authorization.k8s.io
  87. kind: Group
  88. name: system:authenticated
  89. ---
  90. apiVersion: v1
  91. kind: Namespace
  92. metadata:
  93. name: cattle-system
  94. ---
  95. apiVersion: rbac.authorization.k8s.io/v1
  96. kind: Role
  97. metadata:
  98. name: default-psp-role
  99. namespace: cattle-system
  100. rules:
  101. - apiGroups:
  102. - extensions
  103. resourceNames:
  104. - default-psp
  105. resources:
  106. - podsecuritypolicies
  107. verbs:
  108. - use
  109. ---
  110. apiVersion: rbac.authorization.k8s.io/v1
  111. kind: RoleBinding
  112. metadata:
  113. name: default-psp-rolebinding
  114. namespace: cattle-system
  115. roleRef:
  116. apiGroup: rbac.authorization.k8s.io
  117. kind: Role
  118. name: default-psp-role
  119. subjects:
  120. - apiGroup: rbac.authorization.k8s.io
  121. kind: Group
  122. name: system:serviceaccounts
  123. - apiGroup: rbac.authorization.k8s.io
  124. kind: Group
  125. name: system:authenticated
  126. ---
  127. apiVersion: policy/v1beta1
  128. kind: PodSecurityPolicy
  129. metadata:
  130. name: restricted
  131. spec:
  132. requiredDropCapabilities:
  133. - NET_RAW
  134. privileged: false
  135. allowPrivilegeEscalation: false
  136. defaultAllowPrivilegeEscalation: false
  137. fsGroup:
  138. rule: RunAsAny
  139. runAsUser:
  140. rule: MustRunAsNonRoot
  141. seLinux:
  142. rule: RunAsAny
  143. supplementalGroups:
  144. rule: RunAsAny
  145. volumes:
  146. - emptyDir
  147. - secret
  148. - persistentVolumeClaim
  149. - downwardAPI
  150. - configMap
  151. - projected
  152. ---
  153. apiVersion: rbac.authorization.k8s.io/v1
  154. kind: ClusterRole
  155. metadata:
  156. name: psp:restricted
  157. rules:
  158. - apiGroups:
  159. - extensions
  160. resourceNames:
  161. - restricted
  162. resources:
  163. - podsecuritypolicies
  164. verbs:
  165. - use
  166. ---
  167. apiVersion: rbac.authorization.k8s.io/v1
  168. kind: ClusterRoleBinding
  169. metadata:
  170. name: psp:restricted
  171. roleRef:
  172. apiGroup: rbac.authorization.k8s.io
  173. kind: ClusterRole
  174. name: psp:restricted
  175. subjects:
  176. - apiGroup: rbac.authorization.k8s.io
  177. kind: Group
  178. name: system:serviceaccounts
  179. - apiGroup: rbac.authorization.k8s.io
  180. name: system:authenticated
  181. apiVersion: v1
  182. kind: ServiceAccount
  183. metadata:
  184. name: tiller
  185. namespace: kube-system
  186. ---
  187. apiVersion: rbac.authorization.k8s.io/v1
  188. kind: ClusterRoleBinding
  189. metadata:
  190. name: tiller
  191. roleRef:
  192. apiGroup: rbac.authorization.k8s.io
  193. kind: ClusterRole
  194. name: cluster-admin
  195. subjects:
  196. - kind: ServiceAccount
  197. name: tiller
  198. namespace: kube-system
  199. addons_include: []
  200. system_images:
  201. etcd: ""
  202. alpine: ""
  203. nginx_proxy: ""
  204. cert_downloader: ""
  205. kubernetes_services_sidecar: ""
  206. kubedns: ""
  207. dnsmasq: ""
  208. kubedns_sidecar: ""
  209. kubedns_autoscaler: ""
  210. coredns: ""
  211. coredns_autoscaler: ""
  212. kubernetes: ""
  213. flannel: ""
  214. flannel_cni: ""
  215. calico_node: ""
  216. calico_cni: ""
  217. calico_controllers: ""
  218. calico_ctl: ""
  219. calico_flexvol: ""
  220. canal_node: ""
  221. canal_cni: ""
  222. canal_flannel: ""
  223. canal_flexvol: ""
  224. weave_node: ""
  225. weave_cni: ""
  226. pod_infra_container: ""
  227. ingress: ""
  228. ingress_backend: ""
  229. metrics_server: ""
  230. windows_pod_infra_container: ""
  231. ssh_key_path: ""
  232. ssh_cert_path: ""
  233. ssh_agent_auth: false
  234. authorization:
  235. mode: ""
  236. options: {}
  237. ignore_docker_version: false
  238. private_registries: []
  239. ingress:
  240. provider: ""
  241. options: {}
  242. node_selector: {}
  243. extra_args: {}
  244. dns_policy: ""
  245. extra_envs: []
  246. extra_volumes: []
  247. extra_volume_mounts: []
  248. cluster_name: ""
  249. prefix_path: ""
  250. addon_job_timeout: 0
  251. bastion_host:
  252. address: ""
  253. port: ""
  254. user: ""
  255. ssh_key: ""
  256. ssh_key_path: ""
  257. ssh_cert: ""
  258. ssh_cert_path: ""
  259. monitoring:
  260. provider: ""
  261. options: {}
  262. node_selector: {}
  263. restore:
  264. restore: false
  265. snapshot_name: ""
  266. dns: null

安全加固的 RKE 模板配置参考

这个 RKE 参考模板提供了安装安全加固的 Kubenetes 所需的配置。RKE 模板用于配置 Kubernetes 和定义 Rancher 设置。请参阅Rancher 文档获得更多安装和 RKE 模板的详细信息。

安全加固的 Ubuntu 18.04 LTS cloud-config参考配置

这个供您参考的cloud-config通常被用于云基础架构环境中,来进行计算实例的配置管理。这个参考配置了在安装 kubernetes 之前需要的 Ubuntu 操作系统级别的设置。

  1. #cloud-config
  2. packages:
  3. - curl
  4. - jq
  5. runcmd:
  6. - sysctl -w vm.overcommit_memory=1
  7. - sysctl -w kernel.panic=10
  8. - sysctl -w kernel.panic_on_oops=1
  9. - curl https://releases.rancher.com/install-docker/18.09.sh | sh
  10. - usermod -aG docker ubuntu
  11. - return=1; while [ $return != 0 ]; do sleep 2; docker ps; return=$?; done
  12. - addgroup --gid 52034 etcd
  13. - useradd --comment "etcd service account" --uid 52034 --gid 52034 etcd
  14. write_files:
  15. - path: /etc/sysctl.d/kubelet.conf
  16. owner: root:root
  17. permissions: "0644"
  18. content: |
  19. vm.overcommit_memory=1
  20. kernel.panic=10