Kyverno 作為 Kubernetes 原生的策略引擎,提供強大的資源驗證、變更和生成能力,有效提升叢集安全性與管理效率。本文除了探討驗證圖片與生成策略外,也涵蓋了時間限制策略和 CEL 表示式的應用,讓開發者更全面地理解 Kyverno 的實用技巧。透過整合 Cosign 等工具,Kyverno 能夠驗證映像簽名,確保只有可信的映像佈署到叢集中。此外,自動生成 NetworkPolicy 和 PodDisruptionBudget 等資源,則簡化了日常維運工作,並提升了應用程式的可靠性。

Kyverno 策略管理與實踐

Kyverno 是一個強大的 Kubernetes 策略管理工具,它允許使用者透過定義策略來控制叢集中的資源。Kyverno 的策略可以分為多種型別,包括驗證、變更和驗證映像。本文將探討 Kyverno 的策略管理功能,並透過具體的例子來說明如何使用這些功能。

自動生成策略(Auto-Gen)與 Kverno 警告

當使用註解(annotation)來限制 Auto-Gen 時,您可能會看到類別似以下的 Kverno 警告:

Warning: Policies that match Pods apply to all Pods including those created 
and managed by controllers excluded from autogen. Use preconditions to 
exclude the Pods managed by controllers which are excluded from autogen.
Refer to https://kyverno.io/docs/writing-policies/autogen/ for details.

內容解密:

此警告指出,當前策略可能會匹配到所有 Pod,包括那些由不包含在自動生成(autogen)範圍內的控制器所建立和管理的 Pod。建議使用前置條件(preconditions)來排除這些 Pod,以避免不必要的策略應用。

Kyverno 的 Auto-Gen 功能透過自動生成規則和路徑來提高策略的表達能力,從而減少了手動編寫和管理多個策略的需求。這對於建立和管理 Pod 的工作負載尤其有用,因為它簡化了除錯過程。

時間限制策略(Time-bound Policies)

時間限制策略允許管理員設定策略僅在特定時間內生效。例如,以下策略規範定義了一個維護視窗,在此期間,禁止在 policy-test 名稱空間中建立或更新 Pod:

spec:
  validationFailureAction: Enforce
  background: false
  rules:
  - name: no-pods-during-maintenance
    match:
      any:
      - resources:
          kinds:
          - Pod
          namespaces:
          - policy-test
    preconditions:
      all:
      # 取得當前時間的小時數
      - key: "{{ time_now_utc().time_to_cron(@).split(@,' ') | [1].to_number(@) }}"
        operator: AnyIn
        # 僅在營業時間(東部標準時間上午 8 點至下午 5 點)內操作,對應 UTC 時間
        value: 13-22
      - key: "{{request.operation}}"
        operator: AnyIn
        value:
        - CREATE
        - UPDATE
    validate:
      message: "No pods during maintenance window."
      deny: {}

內容解密:

此策略透過檢查當前 UTC 時間的小時數,並與指定的營業時間(東部標準時間上午 8 點至下午 5 點,對應 UTC 時間的 13-22 點)進行比較,來決定是否允許 Pod 的建立或更新操作。如果操作不在允許的時間範圍內,則會拒絕該操作。

使用 Common Expression Language(CEL)的策略

Kyverno 策略也可以使用 CEL 表示式。以下是一個示例,用於限制 Pod 和容器級別的安全組態:

spec:
  background: true
  validationFailureAction: Audit
  rules:
  - name: check-seccomp
    match:
      any:
      - resources:
          kinds:
          - Pod
    validate:
      cel:
        expressions:
        - expression: >-
            !has(object.spec.securityContext) ||
            !has(object.spec.securityContext.seccompProfile) ||
            !has(object.spec.securityContext.seccompProfile.type) ||
            object.spec.securityContext.seccompProfile.type ==
            'RuntimeDefault' ||
            object.spec.securityContext.seccompProfile.type ==
            'Localhost'
          message: >-
            Use of custom Seccomp profiles is disallowed. The field 
            spec.securityContext.seccompProfile.type must be unset or 
            set to `RuntimeDefault` or `Localhost`.
        - expression: >-
            object.spec.containers.all(container,
            !has(container.securityContext) ||
            !has(container.securityContext.seccompProfile) ||
            !has(container.securityContext.seccompProfile.type) ||
            container.securityContext.seccompProfile.type ==
            'RuntimeDefault' ||
            container.securityContext.seccompProfile.type ==
            'Localhost')
          message: >-
            Use of custom Seccomp profiles is disallowed. The field 
            spec.containers[*].securityContext.seccompProfile.type must 
            be unset or set to `RuntimeDefault` or `Localhost`.

內容解密:

此策略使用 CEL 表示式檢查 Pod 和其容器的安全組態,確保 seccomp 組態檔的型別被限制為 RuntimeDefaultLocalhost。如果組態不符合要求,則會記錄稽核訊息。

驗證映像(VerifyImages)策略

驗證映像策略透過驗證 OCI 映像的簽名來增強 Kubernetes 的安全性。以下是一個使用 Cosign 簽名的映像驗證策略示例:

apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: verify-image
spec:
  validationFailureAction: enforce
  background: false
  rules:
  - name: verify-image
    match:
      any:
      - resources:
          kinds:
          - Pod
    verifyImages:
    - imageReferences:
      - "ghcr.io/kyverno/test-verify-image*"
      mutateDigest: true
      attestors:
      - entries:
        - keys:
            publicKeys: |
              -----BEGIN PUBLIC KEY-----
              # 公鑰內容
              -----END PUBLIC KEY-----

內容解密:

此策略驗證來自指定倉函式庫的映像簽名,確保只有經過驗證的映像可以被佈署到叢集中。透過使用 Cosign 的公鑰進行驗證,Kyverno 能夠確保映像的完整性和來源的可信度。

Kyverno 在 Kubernetes 中的應用:驗證與生成策略

Kyverno 是一個強大的 Kubernetes 策略引擎,能夠驗證、變更和生成 Kubernetes 資源。本文將探討 Kyverno 的驗證圖片(Verify Images)功能以及生成策略(Generate Policies)的使用方法。

驗證圖片(Verify Images)

驗證圖片是確保容器映像完整性和安全性的重要步驟。Kyverno 提供 verifyImages 規則型別,用於驗證映像簽名並將映像標籤替換為映像摘要(Digest)。

使用公鑰進行驗證

在 Kyverno 中,可以使用公鑰作為驗證機構(Attestor)來驗證 OCI 映像。私鑰用於簽署儲存在 OCI 儲存函式庫中的映像。

apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: check-image
spec:
  validation:
    message: "The image is not signed"
    rules:
    - name: verify-image
      match:
        any:
        - resources:
            kinds:
            - Pod
      verifyImages:
      - imageReferences:
        - "ghcr.io/myorg/myimage*"
        attestors:
        - count: 1
          entries:
          - keys:
              publicKeys: |
                -----BEGIN PUBLIC KEY-----
                MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE8nXRh950IZbRj8Ra/N9sbqOPZrfM
                5/KAQN0/KjHcorm/J5yctVd7iEcnessRQjU917hmKO6JWVGHpDguIyakZA==
                -----END PUBLIC KEY-----

內容解密:

此 YAML 組態定義了一個 Kyverno ClusterPolicy,用於驗證 Pod 中使用的映像是否經過簽署。主要步驟如下:

  1. 匹配資源:該規則匹配所有 Pod 資源。
  2. 驗證映像:使用 verifyImages 規則驗證映像簽名。
    • imageReferences 指定要驗證的映像,這裡匹配 ghcr.io/myorg/myimage 開頭的映像。
    • attestors 定義驗證機構,使用公鑰進行驗證。
    • publicKeys 欄位包含用於驗證的公鑰。

使用映像摘要(Digest)而非標籤是最佳實踐,因為摘要是唯一且不可變的,能確保映像的完整性。

生成策略(Generate Policies)

Kyverno 的生成策略允許建立新的 Kubernetes 資源。例如,當建立 Namespace 時,可以生成 NetworkPolicy 資源來限制 Pod 的網路流量。

生成 NetworkPolicy 資源

以下是一個生成策略的範例,用於在建立 Namespace 時生成一個拒絕所有流量的 NetworkPolicy:

apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: generate-network-policy
spec:
  generateExisting: true
  rules:
  - name: deny-all-traffic
    match:
      any:
      - resources:
          kinds:
          - Namespace
    exclude:
      any:
      - resources:
          namespaces:
          - kube-system
          - default
          - kube-public
          - kyverno
    generate:
      kind: NetworkPolicy
      apiVersion: networking.k8s.io/v1
      name: deny-all-traffic
      namespace: "{{request.object.metadata.name}}"
      data:
        spec:
          podSelector: {}
          policyTypes:
          - Ingress
          - Egress

內容解密:

此生成策略在建立 Namespace 時生成一個 NetworkPolicy,主要組態如下:

  1. 匹配資源:匹配所有 Namespace 資源。
  2. 排除特定 Namespace:排除 kube-systemdefaultkube-publickyverno 等系統 Namespace。
  3. 生成 NetworkPolicy:在新建立的 Namespace 中生成一個名為 deny-all-traffic 的 NetworkPolicy。
    • podSelector: {} 表示該策略適用於 Namespace 中的所有 Pod。
    • policyTypes 包含 IngressEgress,表示該策略同時控制入口和出口流量。

連結生成的資源

Kyverno 允許透過 generate.synchronize=true 組態將生成的資源與觸發生成的資源進行連結。例如,建立 Deployment 時可以生成對應的 PodDisruptionBudget(PDB),並在 Deployment 被刪除時自動刪除相關的 PDB。

apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: create-default-pdb
spec:
  generateExisting: true
  rules:
  - name: create-default-pdb
    match:
      any:
      - resources:
          kinds:
          - Deployment
    generate:
      apiVersion: policy/v1
      kind: PodDisruptionBudget
      name: "{{request.object.metadata.name}}-default-pdb"
      namespace: "{{request.object.metadata.namespace}}"
      synchronize: true
      data:
        spec:
          minAvailable: 1
          selector:
            matchLabels:
              "{{request.object.metadata.labels}}"

內容解密:

此策略在建立或更新 Deployment 時生成對應的 PodDisruptionBudget,主要組態如下:

  1. 匹配資源:匹配所有 Deployment 資源。
  2. 生成 PDB:為每個 Deployment 生成一個 PDB,名稱格式為 <deployment-name>-default-pdb>
    • synchronize: true 表示當 Deployment 被刪除時,相關的 PDB 也會被自動刪除。
    • minAvailable: 1 確保至少有一個副本可用。
    • matchLabels 將 PDB 與對應的 Deployment 連結起來,透過匹配 Deployment 的標籤。

Kyverno 策略工作流程

  graph LR;
    A[Kubernetes 資源建立] --> B{Kyverno 策略檢查};
    B -->|驗證圖片| C[檢查映像簽名];
    B -->|生成策略| D[生成新的 Kubernetes 資源];
    C -->|簽名有效| E[允許資源建立];
    C -->|簽名無效| F[拒絕資源建立];
    D --> G[生成 NetworkPolicy 或 PDB];
    G --> H[將生成的資源連結到原始資源];

圖表翻譯: 此圖表展示了 Kyverno 在 Kubernetes 中的工作流程:

  1. 當 Kubernetes 資源被建立時,Kyverno 會根據設定的策略進行檢查。
  2. 如果是驗證圖片,則檢查映像簽名。如果簽名有效,允許資源建立;否則拒絕。
  3. 如果是生成策略,則根據規則生成新的 Kubernetes 資源,如 NetworkPolicy 或 PodDisruptionBudget。
  4. 生成的資源可以與原始資源進行連結,實作同步管理。