本文发表于一年多前。旧文章可能包含过时内容。请检查页面中的信息自发布以来是否已变得不正确。
Kubernetes 部署的安全最佳实践
注意:本帖子中的一些建议已不再是最新的。当前的集群强化选项请参见此文档。
编者按:今天的文章由 Aqua Security 的 Amir Jerbi 和 Michael Cherny 撰写,基于他们在本地和云部署中各种用例收集的数据,描述了 Kubernetes 部署的安全最佳实践。
Kubernetes 提供了许多可以大大提高应用程序安全性的控制措施。配置这些控制措施需要对 Kubernetes 和部署的安全要求有深入的了解。我们在这里强调的最佳实践与容器生命周期(构建、发布和运行)保持一致,并专门为 Kubernetes 部署量身定制。我们在我们自己的 SaaS 部署中采用了这些最佳实践,该部署在 Google Cloud Platform 上运行 Kubernetes。
以下是我们部署安全 Kubernetes 应用程序的建议
**确保镜像没有漏洞 **
运行带有漏洞的容器会使您的环境面临被轻易入侵的风险。许多攻击可以通过确保没有已知漏洞的软件组件来缓解。
实施持续安全漏洞扫描——容器可能包含带有已知漏洞(CVE)的过时软件包。这不能是“一次性”过程,因为新的漏洞每天都会发布。持续评估镜像的持续过程对于确保所需的安全性态势至关重要。
定期对您的环境应用安全更新——一旦在运行的容器中发现漏洞,您应该始终更新源镜像并重新部署容器。尽量避免直接更新(例如“apt-update”)正在运行的容器,因为这可能会破坏镜像-容器关系。使用 Kubernetes 的滚动更新功能升级容器非常容易——这允许通过将其镜像升级到最新版本来逐步更新正在运行的应用程序。
确保您的环境中只使用授权镜像
如果没有一个流程来确保只允许运行符合组织策略的镜像,组织就面临运行易受攻击甚至恶意容器的风险。从未知来源下载和运行镜像很危险。这相当于在生产服务器上运行来自未知供应商的软件。不要这样做。
使用私有注册表来存储您批准的镜像——确保您只将批准的镜像推送到这些注册表。这本身就已经缩小了范围,将进入您管道的潜在镜像数量减少到数十万个公开可用镜像的一小部分。构建一个集成了安全评估(如漏洞扫描)的 CI 管道,使其成为构建过程的一部分。
CI 管道应确保只使用经过审查的代码(批准用于生产)来构建镜像。一旦镜像构建完成,就应扫描其安全漏洞,只有在没有发现任何问题的情况下,才将镜像推送到私有注册表,然后从该注册表部署到生产环境。安全评估失败应导致管道失败,阻止具有不良安全质量的镜像被推送到镜像注册表。
Kubernetes 正在进行镜像授权插件的工作(预计在 Kubernetes 1.4 中发布),这将允许阻止发布未经授权的镜像。有关更多信息,请参阅此拉取请求。
限制对 Kubernetes 节点的直接访问
您应该限制对 Kubernetes 节点的 SSH 访问,以降低未经授权访问主机资源的风险。相反,您应该要求用户使用“kubectl exec”,这将提供对容器环境的直接访问,而无需访问主机。
您可以使用 Kubernetes 授权插件来进一步控制用户对资源的访问。这允许为特定命名空间、容器和操作定义细粒度访问控制规则。
在资源之间创建管理边界
限制用户权限的范围可以减少错误或恶意活动的影响。Kubernetes 命名空间允许您将创建的资源划分为逻辑命名的组。在一个命名空间中创建的资源可以对其他命名空间隐藏。默认情况下,用户在 Kubernetes 集群中创建的每个资源都在一个名为“default”的默认命名空间中运行。您可以创建额外的命名空间,并将资源和用户附加到它们。您可以使用 Kubernetes 授权插件创建策略,以隔离不同用户对命名空间资源的访问。
例如:以下策略将允许“alice”从命名空间“fronto”读取 Pod。
{
"apiVersion": "abac.authorization.kubernetes.io/v1beta1",
"kind": "Policy",
"spec": {
"user": "alice",
"namespace": "fronto",
"resource": "pods",
"readonly": true
}
}
定义资源配额
运行不受资源限制的容器会使您的系统面临 DoS 或“吵闹的邻居”场景的风险。为了防止和最小化这些风险,您应该定义资源配额。默认情况下,Kubernetes 集群中的所有资源都以不受限制的 CPU 和内存请求/限制创建。您可以创建资源配额策略,附加到 Kubernetes 命名空间,以限制 Pod 允许消耗的 CPU 和内存。
以下是命名空间资源配额定义的示例,它将命名空间中的 Pod 数量限制为 4 个,将它们的 CPU 请求限制在 1 到 2 之间,内存请求限制在 1GB 到 2GB 之间。
compute-resources.yaml
apiVersion: v1
kind: ResourceQuota
metadata:
name: compute-resources
spec:
hard:
pods: "4"
requests.cpu: "1"
requests.memory: 1Gi
limits.cpu: "2"
limits.memory: 2Gi
为命名空间分配资源配额
kubectl create -f ./compute-resources.yaml --namespace=myspace
实施网络分段
在同一个 Kubernetes 集群上运行不同的应用程序会产生一个应用程序受到攻击并攻击相邻应用程序的风险。网络分段对于确保容器只能与它们应该通信的容器进行通信非常重要。
Kubernetes 部署中的挑战之一是在 Pod、服务和容器之间创建网络分段。由于容器网络身份 (IP) 的“动态”性质,以及容器可以在同一节点内部或节点之间进行通信的事实,这是一个挑战。
Google Cloud Platform 的用户可以受益于自动防火墙规则,防止跨集群通信。可以使用网络防火墙或 SDN 解决方案在本地部署类似的实现。Kubernetes 网络 SIG 正在这方面开展工作,这将大大改善 Pod 到 Pod 的通信策略。新的网络策略 API 应该解决围绕 Pod 创建防火墙规则的需求,限制容器化应用程序可以拥有的网络访问权限。
以下是一个网络策略的示例,它控制“backend”Pod 的网络,只允许来自“frontend”Pod 的入站网络访问
POST /apis/net.alpha.kubernetes.io/v1alpha1/namespaces/tenant-a/networkpolicys
{
"kind": "NetworkPolicy",
"metadata": {
"name": "pol1"
},
"spec": {
"allowIncoming": {
"from": [{
"pods": { "segment": "frontend" }
}],
"toPorts": [{
"port": 80,
"protocol": "TCP"
}]
},
"podSelector": {
"segment": "backend"
}
}
}
在此处阅读更多关于网络策略的信息:这里。
为您的 Pod 和容器应用安全上下文
在设计容器和 Pod 时,请确保为您的 Pod、容器和卷配置安全上下文。安全上下文是部署 yaml 中定义的一个属性。它控制将分配给 Pod/容器/卷的安全参数。其中一些重要参数是
安全上下文设置 | 描述 |
---|---|
SecurityContext->runAsNonRoot | 表示容器应以非 root 用户身份运行 |
SecurityContext->Capabilities | 控制分配给容器的 Linux 功能。 |
SecurityContext->readOnlyRootFilesystem | 控制容器是否能够写入根文件系统。 |
PodSecurityContext->runAsNonRoot | 防止容器在 Pod 中以 'root' 用户身份运行 |
以下是带有安全上下文参数的 Pod 定义示例
apiVersion: v1
kind: Pod
metadata:
name: hello-world
spec:
containers:
# specification of the pod’s containers
# ...
securityContext:
readOnlyRootFilesystem: true
runAsNonRoot: true
参考这里。
如果您正在运行具有提升权限(--privileged)的容器,您应该考虑使用“DenyEscalatingExec”准入控制。此控制拒绝以允许主机访问的提升权限运行的 Pod 的 exec 和 attach 命令。这包括以特权身份运行、有权访问主机 IPC 命名空间和有权访问主机 PID 命名空间的 Pod。有关准入控制的更多详细信息,请参阅 Kubernetes 文档。
记录一切
Kubernetes 提供基于集群的日志记录,允许将容器活动记录到中央日志中心。创建集群后,每个容器的标准输出和标准错误输出可以通过在每个节点上运行的 Fluentd 代理摄取到 Google Stackdriver Logging 或 Elasticsearch 中,并使用 Kibana 查看。
总结
Kubernetes 提供了许多创建安全部署的选项。没有一刀切的解决方案可以用于所有地方,因此需要对这些选项有一定程度的熟悉,并了解它们如何增强应用程序的安全性。
我们建议实施本博客中强调的最佳实践,并利用 Kubernetes 灵活的配置功能将安全流程整合到持续集成管道中,通过安全“无缝嵌入”来自动化整个过程。
- 下载 Kubernetes
- 在 GitHub 上参与 Kubernetes 项目
- 在 Stack Overflow 上提问(或回答问题)
- 在 Slack 上与社区联系
- 在 Twitter 上关注我们 @Kubernetesio 获取最新更新