1

我想禁止在没有ResourceQuota的命名空间中创建 Pod 。如果可能的话,我希望 Gatekeeper在允许创建 Pod 之前确保有一个 ResourceQuota 设置limits.cpulimits.memory

我创建了以下配置,但它们没有解决我的问题:

模板

apiVersion: templates.gatekeeper.sh/v1beta1 
kind: ConstraintTemplate 
metadata: 
  name: k8sresoucequota 
spec:
  crd:
    spec:
      names:
        kind: k8sResouceQuota
  targets:
    - target: admission.k8s.gatekeeper.sh
      rego: |
        package k8sresoucequota

        violation[{"msg": msg}] {
          input.request.kind.kind == "Pod"
          requestns := input.request.object.metadata.namespace
          existingrqs := {e | e := data.inventory.namespace[requestns]["v1beta1"]["ResourceQuota"].metadata.name}
          not ns_exists(requestns,existingrqs)
          msg := sprintf("container <%v> could not be created because the <%v> namespace does not have ResourceQuotas defined", [input.request.object.metadata.name,input.request.object.metadata.namespace])
        }

        ns_exists(ns,arr) {
          arr[_] = ns
        }

约束

apiVersion: constraints.gatekeeper.sh/v1beta1
kind: k8sResouceQuota
metadata:
  name: namespace-must-have-resourcequota
spec:
  match:
    kinds:
      - apiGroups: [""]
        kinds: ["Pod"]
    excludedNamespaces:
      - kube-system
      - kube-public
      - kube-node-lease
      - default
      - gatekeeper-system
      - kubernetes-dashboard

同步.yaml

apiVersion: config.gatekeeper.sh/v1alpha1
kind: Config
metadata:
  name: config
  namespace: "gatekeeper-system"
spec:
  sync:
    syncOnly:
      - group: ""
        version: "v1beta1"
        kind: "Pod"
      - group: ""
        version: "v1beta1"
        kind: "Namespace"
      - group: ""
        version: "v1beta1"
        kind: "ResourceQuota"
4

1 回答 1

0

第 1 部分:“没有与命名空间同名的 ResourceQuota”

让我们一一浏览您的 Rego 的这三行。

requestns := input.request.object.metadata.namespace
existingrqs := {e | e := data.inventory.namespace[requestns]["v1beta1"]["ResourceQuota"].metadata.name}
not ns_exists(requestns,existingrqs)
  1. 此行获取保存正在评估的 Pod 的命名空间的名称。
requestns := input.request.object.metadata.namespace
  1. 此行无效。或者更确切地说,它将返回一个空集。
existingrqs := {e | e := data.inventory.namespace[requestns]["v1beta1"]["ResourceQuota"].metadata.name}

我假设您要说的是“在与 Pod 相同的命名空间中获取每个 ResourceQuota 的名称。

回想一下,数据的格式data.inventory.namespace[<namespace>][groupVersion][<kind>][<name>]. 所以真的应该是:

existingrqs := {e | e := data.inventory.namespace[requestns]["v1beta1"]["ResourceQuota"][_].metadata.name

这将遍历 Pod 命名空间中的所有 ResourceQuota,并创建一个包含所有名称的集合。

  1. 您将其拆分为它自己的函数 ( ns_exists),但看起来您正在尝试查找是否存在与命名空间同名的 ResourceQuota。相反,您应该使用:
not existingrqs[requestns]

该语句将评估false同名的 ResourceQuota 是否存在,true如果不存在。但这实际上比我们需要的要多。我们只关心 ResourceQuota 是否存在。我们可以将第 2 行和第 3 行合并为:

not data.inventory.namespace[requestns]["v1beta1"]["ResourceQuota"][requestns]

这将评估true是否缺少 ResourceQuota,或者false是否存在这样的 ResourceQuota

完成的 Rego 应该是:

package k8sresoucequota

violation[{"msg": msg}] {
  input.request.kind.kind == "Pod"
  requestns := input.request.object.metadata.namespace
  not data.inventory.namespace[requestns]["v1beta1"]["ResourceQuota"][requestns]
  msg := sprintf("container <%v> could not be created because the <%v> namespace does not have ResourceQuotas defined", [input.request.object.metadata.name,input.request.object.metadata.namespace])
}

在英语中,如果对象是 Pod,并且 Namespace 不包含与 Namespace 同名的 ResourceQuota,这将造成违规

第 2 部分:“ResourceQuota 设置limits.cpu 和limits.memory”

对于 Rego,我们使用增量规则来创建 OR 条件。尽管可能,但它被认为是一种反模式,可以避免 Rego 函数中的所有语句都被 AND 运算在一起。limits.cpu所以我们需要一个不同的违规来检查 ResourceQuota 是否已经limits.memory设置。

violation[{"msg": msg}] {
  input.request.kind.kind == "Pod"
  requestns := input.request.object.metadata.namespace
  data.inventory.namespace[requestns]["v1beta1"]["ResourceQuota"][requestns]
  rq := data.inventory.namespace[requestns]["v1beta1"]["ResourceQuota"][requestns]
  not defines_limits(rq)
  msg := sprintf("container <%v> could not be created because the <%v> namespace does not enforce limits.cpu or limits.memory", [input.request.object.metadata.name,input.request.object.metadata.namespace])
}

defines_limits(rq) {
  rq.limits.cpu
}

defines_limits(rq) {
  rq.limits.memory
}

此违规检查:

  1. 存在所需名称的 ResourceQuota。
  2. ResourceQuota 无法设置limits.cpu和之一limits.memory。也就是说,我们找到的 ResourceQuota 必须同时设置,才能允许创建 Pod。

这个答案很好地解释了增量规则是如何工作的。

于 2021-05-15T02:44:15.897 回答