我试着玩了一下Kyverno

关于这篇文章

我在业务中使用Kyverno,但只使用了部分功能,尚未完全掌握所有功能,因此我正在撰写这篇文章进行调查。

Kyverno是什么?

Kyverno是专为Kubernetes设计的策略引擎。策略指的是在创建k8s资源时的规则。例如…

    • Podには必ず○○というLabelがついていないといけない

 

    • latestタグの利用禁止

 

    などなど

我认为与OpenPolicyAgent相比的一个重大区别是可以不使用像Rego这样的特殊语言来定义策略。

Kyverno的功能

    • リソースが新規作成された際に別のリソースを新規作成できる

 

    • リソースが新規作成・更新された際にパッチを当てられる

 

    リソースの作成された際に、ポリシーに則ってるか検証し、作成を拒否することができる

我想要分别体验这些功能!

安装

由於Manifest在GitHub上已準備好,我們將使用它。
順便一提,我們將使用Kyverno的版本為v1.4.1。

$ kubectl apply -f https://raw.githubusercontent.com/kyverno/kyverno/v1.4.1/definitions/install.yaml

碰一下试试

产生资源

Generate Resources是一个功能,用于在创建或更新资源时触发创建新资源。您可以在此链接中了解更多信息:https://kyverno.io/docs/writing-policies/generate/

先试试看吧!

我认为在不同的命名空间中可能会有使用相同的机密信息的情况。
为了应对这种情况,我会编写一个策略,当命名空间被创建时,可以拷贝已存在的机密信息。

首先,在默认命名空间中创建作为源的秘密。

apiVersion: v1
kind: Secret
metadata:
  name: sample-secret
  namespace: default
type: Opaque
data:
  password: aG9nZQo= # hoge

接下来,我们将定义一个复制此Secret的策略。

apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: sync-secrets
  annotations:
    policies.kyverno.io/title: Sync Secrets
    policies.kyverno.io/category: Sample
    policies.kyverno.io/subject: Secret
    policies.kyverno.io/description: >-
      copy sample secret from default namespace to requested namespace.
spec:
  background: false
  rules:
  - name: sync-sample-secret
    match:
      resources:
        kinds:
        - Namespace
    generate:
      kind: Secret
      name: sample-secret
      namespace: "{{request.object.metadata.name}}"
      synchronize: true
      clone:
        namespace: default
        name: sample-secret

让我们创建一个命名空间并进行操作以确认。

$ kubectl create namespace test
namespace/test created

# 関係あるところだけ抜粋
$ kubectl get secret sample-secret -o yaml -n test
apiVersion: v1
data:
  password: aG9nZQo=
kind: Secret
metadata:
  name: sample-secret
  namespace: test
type: Opaque

所以,我成功地做到了我想做的事情。

有疑問

我会写下尝试后出现的疑问和对应的答案。

spec.rules.generate.synchronize是什么意思?

在这个示例中,我们设置了 synchronize: true。这具体意味着什么呢?

如果资源是通过复制创建的,那么无法进行源代码管理。如果使用Yaml定义清单并在Git中进行管理,并使用GitOps,在这种情况下,可以直接编辑这些资源。为了防止这种情况,将synchronize设置为true,以便与复制的资源进行同步。

# コピーしたSecretリソースのパスワード部分変更
$ k edit secret sample-secret -n test
secret/sample-secret edited

# コピー元
$ k get secret sample-secret -o yaml -n default | grep password | head -1
  password: aG9nZQo=

# コピー先。editで更新したのに元に戻ってる
$ k get secret sample-secret -o yaml -n test | grep password | head -1
  password: aG9nZQo=

现在,刚才我们尝试编辑了复制的内容,那么如果我们编辑原始内容会发生什么呢?

# コピー元のSecretリソースのパスワード部分変更
$ k edit secret sample-secret -n default
secret/sample-secret edited

# コピー元
$ k get secret sample-secret -o yaml -n default | grep password | head -1
  password: YWFhCg==

# コピー先
$ k get secret sample-secret -o yaml -n test | grep password | head -1
  password: YWFhCg==

这个也会与之同步。很方便!

除了克隆(Clone)之外,还有哪些选项可供选择?

这次我们使用了克隆功能。

clone:
   namespace: default
  name: sample-secret

还可以直接按照声明的定义进行书写。

    generate:
      synchronize: true
      kind: ConfigMap
      name: zk-kafka-address
      # generate the resource in the new namespace
      namespace: "{{request.object.metadata.name}}"
      data:
        kind: ConfigMap
        metadata:
          labels:
            somekey: somevalue
        data:
          ZK_ADDRESS: "192.168.10.10:2181,192.168.10.11:2181,192.168.10.12:2181"
          KAFKA_ADDRESS: "192.168.10.13:9092,192.168.10.14:9092,192.168.10.15:9092"

资源变异

Mutate Resources是一种针对匹配资源应用修补程序的功能。

我想列举一些选项:
1. 我打算继续探讨下去。
2. 这次我们假设的场景是希望在一个命名空间的Pod下必须加载一个公共的ConfigMap。

首先,我们创建一个命名空间。

$ kubectl create namespace test2
namespace/test2 created

接下来,我们将创建一个要加载的ConfigMap。

apiVersion: v1
kind: ConfigMap
metadata:
  name: sample-configmap
  namespace: test2
data:
  environment_name: staging

我们需要写一个策略,让test2中的Pod能够加载上述的ConfigMap。使得ConfigMap中的值可以变为环境变量。

apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: add-configmap-policy
  annotations:
    policies.kyverno.io/title: add configmap
    policies.kyverno.io/category: Sample
    policies.kyverno.io/subject: Pod
    policies.kyverno.io/description: >-
      Add env to pods which place to test2 namespace.
spec:
  rules:
  - name: "Set common environment variables"
    match:
      resources:
        kinds:
        - Pod
        namespaces:
        - test2
    mutate:
      overlay:
        spec:
          containers:
          - (name): "*"
            env:
              - name: ENVIRONMENT
                valueFrom:
                  configMapKeyRef:
                    name: sample-configmap
                    key: environment_name

最终,将创建用于测试的部署。

apiVersion: apps/v1
kind: Deployment
metadata:
  name: test-deployment
  namespace: test2
spec:
  selector:
    matchLabels:
      app: test
  replicas: 1
  template:
    metadata:
      labels:
        app: test
    spec:
      containers:
      - name: nginx
        image: nginx:latest
        ports:
        - containerPort: 80

让我们来看看,这个部署将为创建的Pod添加了将ConfigMap中定义的值设置为环境变量的设置。

$ kubectl describe pod -n test2 test-deployment-c49854788-s2wg4 | grep -i ENVIRONMENT
    Environment:
      ENVIRONMENT:  <set to the key 'environment_name' of config map 'sample-configmap'>  Optional: false

我们成功地设置了一种可以自动插入env配置的设置。

问题

spec.rules.mutate.overlay是什么?

变异可以指定以下3种补丁的应用方式。

    • overlay

追加・置き換えたいマニフェストを記述する方法です

Strategic Merge Patch

overlayと同じく、追加や置き換えの記述が出来ます
削除も可能です

RFC 6902 JSONPatch

リソースに対して json patchを当てる方法です。kustomizeでいう patchesJson6902

Strategi Merge Patchでは実現できない更新をしたいときに使います

例えばarrayの一部要素を書き換えたいとか

在match中可以指定什么?

详细的信息可以在这里找到:
https://kyverno.io/docs/writing-policies/match-exclude/

您可以通过资源的名称或标签来限制目标对象,并且还可以进行排除设置。

验证资源

这个功能是用来检查新的或现有资源是否符合定义的策略。

这次的情景设置是「必须在Pod中加入resources.requests/limits。如果没有加入,就不会生成Pod」。
首先,我们要撰写这个限制的策略。

apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: all-containers-need-requests-and-limits
spec:
  validationFailureAction: enforce
  background: false
  rules:
  - name: check-container-resources
    match:
      resources:
        kinds:
        - Pod
        namespaces:
        - test2
    validate:
      message: "All containers must have CPU and memory resource requests and limits defined."
      pattern:
        spec:
          containers:
          - name: "*"
            resources:
              limits:
                memory: "?*"
                cpu: "?*"
              requests:
                memory: "?*"
                cpu: "?*"

我会应用使用过的Deployment来进行变异。
然后…

$ kubectl apply -f test.yaml
Error from server: error when creating "test.yaml": admission webhook "validate.kyverno.svc" denied the request:

resource Deployment/test2/test-deployment was blocked due to the following policies

all-containers-need-requests-and-limits:
  autogen-check-container-resources: 'validation error: All containers must have CPU
    and memory resource requests and limits defined. Rule autogen-check-container-resources
    failed at path /spec/template/spec/containers/0/resources/limits/'

# Podは作成されていない
$ kubectl -n test2 get pods
No resources found in test2 namespace.

所以,我成功完成了我想做的事情。

这是一个疑问

spec.background是什么?

如果将此设置为 true,则会对现有资源执行策略检查。
https://kyverno.io/docs/writing-policies/background/

如果现有资源违反政策,尽管现有资源保持不变,
但会创建名为ClusterPolicyReport或PolicyReport的资源。

$ kubectl get policyreport -A
NAMESPACE   NAME            PASS   FAIL   WARN   ERROR   SKIP   AGE
test2       polr-ns-test2   0      1      0      0       0      67s

查看内部内容后,会显示错误原因。

这个 spec.background 的默认值是true,对于mutate或generate没有影响。

可以在spec.validationFailureAction中指定什么内容?

    • enforce

ポリシー違反の場合、新規リソースの場合は、そのリソースは作成されません

audit

ポリシー違反の場合、ClusterPolicyReport または PolicyReport というリソースが作成されます
ポリシー違反でもそのリソースは作成されます

其他方便功能

这一次我没有亲自触摸,但是我会介绍一下似乎在熟练使用时很方便的功能。

变量

您可以将请求的资源信息作为变量使用。
https://kyverno.io/docs/writing-policies/variables/

还可以调用ConfigMap的信息。
这意味着可以基于ConfigMap定义的值进行验证或其他操作。
https://kyverno.io/docs/writing-policies/external-data-sources/

本题要求以中文原生方式重新表达给定的短语”前提条件”。

假设基础

如果想要进行比”match”或”exclude”更精细的条件指定,可以使用”preconditions”。
https://kyverno.io/docs/writing-policies/preconditions/

广告
将在 10 秒后关闭
bannerAds