本页面介绍如何使用 Gatekeeper 准入控制器将 Pod 级层的安全控制机制应用于 Google Kubernetes Engine (GKE) 集群。
概览
Gatekeeper 是一个准入控制器,使用开放政策代理 (OPA) 验证在 Kubernetes 集群上创建和更新 Pod 的请求。
借助 Gatekeeper,管理员可以使用“限制条件”来定义政策,这是一组允许或拒绝 Kubernetes 中的部署行为的条件。然后,您可以使用 ConstraintTemplate
在集群上强制执行这些政策。本文档提供了有关如何限制工作负载安全功能以确保使用 Gatekeeper 强制执行、测试和审核安全政策的示例。
Gatekeeper 还具有以下功能:
- 发布政策:以循序渐进的方式逐步执行政策,以限制中断工作负载的风险。
- 试运行政策更改:提供在强制执行之前测试政策影响和范围的机制。
- 审核现有政策:确保将安全控制机制应用于新的和现有的工作负载(审核控制)。
概念
Gatekeeper 引入了两个概念,以便为管理员提供强大、灵活控制其集群的控制方法:限制条件和约束模板,它们都是从开放式政策代理限制条件框架继承的概念。
限制条件是您的安全政策的表示形式,它们定义了强制执行的要求和范围。限制条件模板是可重复使用的语句(使用 Rego 编写),这些语句根据限制条件中定义的要求应用逻辑,以评估 Kubernetes 对象中的特定字段。
例如,您可能有一个限制条件,用于声明可应用于特定命名空间中 Pod 的允许 seccomp 配置文件,以及一个提供限制条件以提取这些值和处理强制执行情况的逻辑模板。
Gatekeeper 代码库中的以下限制条件模板会检查 Pod 规范中是否存在 securityContext.privileged
:
apiVersion: templates.gatekeeper.sh/v1beta1
kind: ConstraintTemplate
metadata:
name: k8spspprivilegedcontainer
spec:
crd:
spec:
names:
kind: K8sPSPPrivilegedContainer
targets:
- target: admission.k8s.gatekeeper.sh
rego: |
package k8spspprivileged
violation[{"msg": msg, "details": {}}] {
c := input_containers[_]
c.securityContext.privileged
msg := sprintf("Privileged container is not allowed: %v, securityContext: %v", [c.name, c.securityContext])
}
input_containers[c] {
c := input.review.object.spec.containers[_]
}
input_containers[c] {
c := input.review.object.spec.initContainers[_]
}
为扩展上述限制条件模板,以下限制定义了此 dryrun
模式下此限制条件模板的具体执行范围 (kinds
):
apiVersion: constraints.gatekeeper.sh/v1beta1
kind: K8sPSPPrivilegedContainer
metadata:
name: psp-privileged-container
spec:
enforcementAction: dryrun
match:
kinds:
- apiGroups: [""]
kinds: ["Pod"]
借助 Gatekeeper,您可以创建自己的限制条件和限制条件模板来满足特定需求。您还可以在 Gatekeeper 代码库中使用一组标准限制条件和限制条件模板,以实现快速采用并强制执行安全机制。每个限制条件还附带示例 Pod 配置。
Google Cloud 提供官方支持的代管式开源 Gatekeeper 版本,名为 Policy Controller。Google 并不正式支持开源 Gatekeeper 项目。
准备工作
在开始之前,请确保您已执行以下任务:
- 启用 Google Kubernetes Engine API。 启用 Google Kubernetes Engine API
- 如果您要使用 Google Cloud CLI 执行此任务,请安装并初始化 gcloud CLI。 如果您之前安装了 gcloud CLI,请运行
gcloud components update
以获取最新版本。
在使用 Config Management 的集群上启用 Gatekeeper
Config Management 提供了 Policy Controller,这是一个基于 Gatekeeper 开源项目构建的政策引擎。Google 建议使用 Config Management,因为它可以解决与大规模强制执行政策相关的常见问题,包括政策即代码、多集群支持、与 Cloud Logging 的集成以及同步配置的功能。
如需在集群上启用 Policy Controller,请按照 Config Management 安装指南操作。
启用限制条件和限制条件模板
您可以安装并启用 Gatekeeper 及其限制条件模板,而不会对现有或新的工作负载产生负面影响。因此,建议将所有适用的 Pod 安全限制条件模板应用于集群。
此外,还可以实现 Gatekeeper 限制条件,以强制对特定对象(例如命名空间和 Pod)的控制。
请观看下面的示例,该示例范围限制为位于生产命名空间中的 Pod,方法是在限制条件匹配语句中定一它们:
...
spec:
match:
kinds:
- apiGroups: [""]
kinds: ["Pod"]
namespaces:
- "production"
如需详细了解 Constraint
和 ConstraintTemplate
对象的可用选项,请参阅如何使用 Gatekeeper。
测试政策
向现有集群引入新政策可能会产生不利行为,例如限制现有工作负载。使用 Gatekeeper 实现 Pod 安全性的一个优势在于,可以使用试运行模式测试政策的有效性和可能产生的影响,而不必作出实际更改。这样,您就可以针对正在运行的集群对政策配置进行测试,而无需强制执行。系统会记录并识别政策违规,而不会造成干扰。
以下步骤演示了开发者、运营商或管理员如何应用限制条件模板和限制条件来确定其有效性或潜在影响:
应用 Gatekeeper 配置以复制数据,进行审核和试运行功能:
kubectl create -f- <<EOF apiVersion: config.gatekeeper.sh/v1alpha1 kind: Config metadata: name: config namespace: "gatekeeper-system" spec: sync: syncOnly: - group: "" version: "v1" kind: "Namespace" - group: "" version: "v1" kind: "Pod" EOF
在未应用任何限制条件的情况下,我们运行具有提升权限的工作负载:
kubectl create -f- <<EOF apiVersion: v1 kind: Pod metadata: name: nginx labels: app: nginx spec: containers: - name: nginx image: nginx securityContext: privileged: true EOF
加载前面所述的
k8spspprivilegedcontainer
限制条件模板:kubectl create -f- <<EOF apiVersion: templates.gatekeeper.sh/v1beta1 kind: ConstraintTemplate metadata: name: k8spspprivilegedcontainer spec: crd: spec: names: kind: K8sPSPPrivilegedContainer targets: - target: admission.k8s.gatekeeper.sh rego: | package k8spspprivileged violation[{"msg": msg, "details": {}}] { c := input_containers[_] c.securityContext.privileged msg := sprintf("Privileged container is not allowed: %v, securityContext: %v", [c.name, c.securityContext]) } input_containers[c] { c := input.review.object.spec.containers[_] } input_containers[c] { c := input.review.object.spec.initContainers[_] } EOF
现在,让我们来创建一个新限制条件来扩展此限制条件模板。这次,我们将
enforcementAction
设置为dryrun
:kubectl create -f- <<EOF apiVersion: constraints.gatekeeper.sh/v1beta1 kind: K8sPSPPrivilegedContainer metadata: name: psp-privileged-container spec: enforcementAction: dryrun match: kinds: - apiGroups: [""] kinds: ["Pod"] EOF
通过 Gatekeeper 同步运行的对象数据并被动地检查是否存在违规,我们可以检查限制的
status
,确认是否有任何违规行为:kubectl get k8spspprivilegedcontainer.constraints.gatekeeper.sh/psp-privileged-container -o yaml
apiVersion: constraints.gatekeeper.sh/v1beta1 kind: K8sPSPPrivilegedContainer metadata: ... name: psp-privileged-container ... spec: enforcementAction: dryrun match: kinds: - apiGroups: - "" kinds: - Pod status: auditTimestamp: "2019-12-15T22:19:54Z" byPod: - enforced: true id: gatekeeper-controller-manager-0 violations: - enforcementAction: dryrun kind: Pod message: 'Privileged container is not allowed: nginx, securityContext: {"privileged": true}' name: nginx namespace: default
让我们运行另一个特权 Pod,以确认该政策不会干扰部署:
kubectl create -f- <<EOF apiVersion: v1 kind: Pod metadata: name: privpod labels: app: privpod spec: containers: - name: nginx image: nginx securityContext: privileged: true EOF
这个新 Pod 将成功部署。
如需清理本部分中创建的资源,请运行以下命令:
kubectl delete k8spspprivilegedcontainer.constraints.gatekeeper.sh/psp-privileged-container kubectl delete constrainttemplate k8spspprivilegedcontainer kubectl delete pod/nginx kubectl delete pod/privpod
强制执行政策
现在,我们可以在不影响现有工作负载或新工作负载的情况下确认政策的有效性和影响,下面我们实施全面强制执行的政策。
基于用于验证上述政策的示例,以下步骤演示了开发者、运维人员或管理员如何应用限制条件模板和限制条件来强制执行政策:
加载前面所述的
k8spspprivilegedcontainer
限制条件模板:kubectl create -f- <<EOF apiVersion: templates.gatekeeper.sh/v1beta1 kind: ConstraintTemplate metadata: name: k8spspprivilegedcontainer spec: crd: spec: names: kind: K8sPSPPrivilegedContainer targets: - target: admission.k8s.gatekeeper.sh rego: | package k8spspprivileged violation[{"msg": msg, "details": {}}] { c := input_containers[_] c.securityContext.privileged msg := sprintf("Privileged container is not allowed: %v, securityContext: %v", [c.name, c.securityContext]) } input_containers[c] { c := input.review.object.spec.containers[_] } input_containers[c] { c := input.review.object.spec.initContainers[_] } EOF
现在,让我们来创建一个新限制条件来扩展此限制条件模板。这次,我们不会设置
enforcementAction
键。默认情况下,enforcementAction
键设置为deny
:kubectl create -f- <<EOF apiVersion: constraints.gatekeeper.sh/v1beta1 kind: K8sPSPPrivilegedContainer metadata: name: psp-privileged-container spec: match: kinds: - apiGroups: [""] kinds: ["Pod"] EOF
尝试部署用于声明特许权限的容器:
kubectl create -f- <<EOF apiVersion: v1 kind: Pod metadata: name: nginx labels: app: nginx spec: containers: - name: nginx image: nginx securityContext: privileged: true EOF
您应该会收到以下错误消息:
Error from server ([denied by psp-privileged-container] Privileged container is not allowed: nginx, securityContext: {"privileged": true}): error when creating "STDIN": admission webhook "validation.gatekeeper.sh" denied the request: [denied by psp-privileged-container] Privileged container is not allowed: nginx, securityContext: {"privileged": true}
如需清理,请运行以下命令:
kubectl delete k8spspprivilegedcontainer.constraints.gatekeeper.sh/psp-privileged-container kubectl delete constrainttemplate k8spspprivilegedcontainer
Gatekeeper 的替代方案
借助 Gatekeeper,您可以声明和应用自定义 Pod 级层安全政策。您还可以使用 Kubernetes 的内置 PodSecurity
准入控制器来应用预定义的 Pod 级层安全政策。这些预定义政策与 Pod 安全标准定义的级层一致。
后续步骤
Gatekeeper 提供了一种极其强大的方法,可以使用声明式政策来在 GKE 集群上强制执行和验证安全性。但是,Gatekeeper 的使用超出了安全范围,可用于管理和操作的其他方面。