Cloud Custodian 是一款開源工具,能有效管理和監控雲端資源,近年來也支援 Kubernetes。本文將會介紹如何利用 Cloud Custodian 定義策略,篩選和操作 Kubernetes 資源,例如刪除或標註 Pod。文章會以實際案例說明如何撰寫 YAML 策略檔,並解析執行結果與日誌資訊。此外,還會探討 Cloud Custodian 的控制器模式,說明如何整合 Kubernetes 的動態准入控制器和變異 Webhook,實作更自動化的資源管理。最後,文章將提供安裝指令碼範例,以及策略驗證和測試方法,協助讀者快速上手並應用於實際環境。

Cloud Custodian 在 Kubernetes 中的應用與實踐

前言

Cloud Custodian(簡稱 c7n)是一個強大的開源工具,用於管理和監控雲端資源的合規性與成本最佳化。隨著 Kubernetes 的廣泛採用,c7n 也擴充套件了對 Kubernetes 資源的管理能力。本文將探討如何使用 c7n 來管理和監控 Kubernetes 中的資源。

使用 c7n 管理 Kubernetes 資源

c7n 透過定義策略(policies)來對 Kubernetes 資源進行篩選和操作。這些策略可以根據資源的屬性、標籤等進行篩選,並執行相應的操作,如刪除、標註等。

執行策略刪除 Pod

以下是一個實際的例子,展示瞭如何使用 c7n 策略刪除特定的 Pod:

policies:
  - name: delete-pods
    resource: k8s.pod
    filters:
      - type: value
        key: metadata.labels.test
        value: c7n
    actions:
      - type: delete

內容解密:

  1. policies: 定義了一組策略。
  2. name: 策略的名稱為 delete-pods
  3. resource: 指定了要操作的 Kubernetes 資源型別為 k8s.pod
  4. filters: 篩選條件,這裡根據 Pod 的標籤 test=c7n 進行篩選。
  5. actions: 操作型別,這裡定義了刪除(delete)操作。

執行上述策略後,c7n 會篩選出符合條件的 Pod 並將其刪除。日誌輸出如下:

2023-07-03 00:02:03,442 - custodian.policy - DEBUG - Running policy:delete-pods resource:k8s.pod region:default c7n:0.9.28
2023-07-03 00:02:03,495 - custodian.resources.pod - DEBUG - Filtered from 8 to 1 pod
2023-07-03 00:02:03,526 - custodian.policy - INFO - policy:delete-pods action:delete resource resources:1 execution_time:0.03

內容解密:

  1. Running policy: 表示正在執行 delete-pods 策略。
  2. Filtered from 8 to 1 pod: 表示從 8 個 Pod 中篩選出 1 個 Pod。
  3. action:delete: 表示執行了刪除操作,成功刪除了 1 個 Pod。

探索 c7n 對資源的表示方式

c7n 可以用來發現和了解其內部對不同 Kubernetes 資源的表示方式。例如,透過編寫一個粗粒度的 Pod 策略,可以收集叢集中所有 Pod 的資料。

粗粒度 Pod 策略範例

policies:
  - name: get-all-pods
    description: Collects all pods.
    resource: k8s.pod

內容解密:

  1. name: 策略名稱為 get-all-pods
  2. resource: 操作的資源型別為 k8s.pod
  3. description: 策略的描述,說明該策略用於收集所有 Pod 的資料。

透過執行上述策略,c7n 將收集叢集中所有 Pod 的資源資料,並可以進一步分析這些資料以瞭解 c7n 對 Pod 資源的內部表示方式。

使用 c7n 篩選缺少 securityContext 的 Pod

在實際應用中,可以編寫策略來檢測 Pod 或容器是否缺少 securityContext 組態。以下是一個範例策略:

policies:
  - name: security-context-pods
    resource: k8s.pod
    filters:
      - type: value
        key: metadata.labels.test
        value: c7n
      - type: value
        key: spec.security_context
        value: empty
      - type: list-item
        key: spec.containers[]
        attrs:
          - type: value
            key: security_context
            value: empty

內容解密:

  1. filters: 定義了多個篩選條件,包括檢查 Pod 標籤、spec.security_context 是否為空,以及容器級別的 security_context 是否為空。
  2. type: list-item: 用於檢查列表中的元素(這裡指容器)是否符合特定條件。

該策略能夠篩選出那些在 Pod 級別或容器級別缺少 securityContext 組態的 Pod。

對符合條件的 Pod 進行標註和註解

進一步,可以在策略中新增 patch 操作,對符合條件的 Pod 新增標籤和註解:

policies:
  - name: security-context-pods
    resource: k8s.pod
    filters:
      - type: value
        key: metadata.labels.test
        value: c7n
      - type: list-item
        key: spec.containers[]
        attrs:
          - type: value
            key: security_context
            value: empty
    actions:
      - type: patch
        options:
          metadata:
            labels:
              'compliance-issue': 'sec-con-missing'
            annotations:
              'compliance-issue': 'One or more containers are missing the securityContext element.'

內容解密:

  1. actions: 定義了對篩選出的 Pod 執行的操作,這裡是 patch 操作,用於修改 Pod 的後設資料。
  2. metadata.labelsmetadata.annotations: 分別用於新增標籤和註解,以標記這些 Pod 存在安全組態問題。

隨著 Kubernetes 生態系統的不斷發展,c7n 將繼續演進,以更好地支援 Kubernetes 資源的管理和監控。未來的發展方向可能包括:

  1. 更豐富的資源支援:擴充套件對更多 Kubernetes 資源的支援,如 Custom Resources 等。
  2. 更強大的策略引擎:增強策略引擎的能力,以支援更複雜的篩選和操作邏輯。
  3. 更好的整合與相容性:改進與其他 Kubernetes 生態工具的整合,如 Argo CD、Flux 等。

透過不斷的改進和創新,c7n 將成為 Kubernetes 使用者管理和監控叢集資源的得力助手。

控制器模式詳解與實務操作

在前面的章節中,我們已經建立了 c7n_kube 策略並透過 c7n CLI 進行套用。同時,我們檢視了 c7n 策略執行所產生的檔案,以深入瞭解 c7n_kube 的結構與物件模型,從而編寫出更完善的策略。在本章節中,我們將探討如何在傳統的 Kubernetes 動態准入控制器(dynamic admission controller)中,以控制器模式執行 c7n 策略。

控制器模式簡介

c7n Kubernetes 提供者(c7n-kube)的控制器模式與過往的解決方案有一定差異。儘管 c7n-kube 使用了 Kubernetes 的動態准入控制器,但它僅採用了變異 Webhook 組態(mutating webhook configuration),而未安裝驗證 Webhook 組態(validating webhook configuration)。

安裝與設定

初始安裝問題與解決方案

在初次使用控制器模式時,遇到了 c7n 檔案過時的問題。由於使用了 Helm 進行安裝,發現檔案中的範例 values 檔案與目前的 JSON 結構不符。因此,直接使用了 GitHub 儲存函式庫中的 values 檔案並進行了自定義修改。

# c7n-kube 控制器模式 Helm 安裝引數
certManager:
  enabled: yes
  issuer:
    create: yes
    certificate:
      create: yes
      name: "{{ .Release.Name }}-issuer"
controller:
  annotations: {}
  create: true
  image: cloudcustodian/c7n:0.9.35.0
  name: "{{ .Release.Name }}"
  onException: warn
  port: 8443
  replicas: 1
  pod:
    annotations: {}
    labels:
      app: c7n_kube
    name: "{{ .Release.Name }}"
policies:
  configMap:
    name: "{{ .Release.Name }}-policies"
  policies:
    - name: 'warn-all-pods'
      resource: 'k8s.pod'
      mode:
        type: k8s-admission
        on-match: warn
      operations:
        - CREATE
        - UPDATE
    - name: missing-required-labels-pods
      mode:
        type: k8s-admission
        on-match: deny
      operations:
        - CREATE
        - UPDATE
      description: |
        所有 Pod 都需要包含以下標籤:
        app
        billing
        env
        owner
      resource: k7s.pod
      filters:
        - or:
          - metadata.labels.app: absent
          - metadata.labels.billing: absent
          - metadata.labels.env: absent
          - metadata.labels.owner: absent
      source: configMap
service:
  create: true
  name: "{{ .Release.Name }}"
  port: 8443
webhook:
  create: true
  failurePolicy: Ignore
  namespaceSelector:
    matchExpressions:
      - key: policy
        operator: In
        values: ["enabled"]
  rules:
    - apiGroups:
        - '*'
      apiVersions:
        - 'v1'
      operations:
        - CREATE
      resources:
        - pods

主要組態解說

  1. 憑證管理:使用 cert-manager 自動建立 TLS 憑證,以確保 Kubernetes API 伺服器與 Webhook 服務之間的通訊安全。
  2. 控制器映像檔:指定 c7n Kubernetes 控制器的 Docker 映像檔版本。
  3. 策略定義:在安裝控制器時一併載入所需的策略。
  4. Webhook 組態
    • 設定失敗策略為「忽略」(Ignore),以避免因 Webhook 呼叫失敗而阻擋資源變更。
    • 使用名稱空間選擇器(Namespace selector)來實作「選擇性加入」(opt-in)的管理模式。
    • 設定 Webhook 只監控 Pod 資源的相關操作。

安裝指令碼自動化

為了簡化安裝與解除安裝流程,特別編寫了 up.shdown.sh 指令碼:

# up.sh 指令碼內容片段
#!/usr/bin/env bash

# 設定錯誤處理機制
set -e
trap 'catch $? $LINENO' ERR

# 安裝 cert-manager
read -p "是否安裝 cert-manager?" yn
case $yn in
  [Yy]* ) kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.12.0/cert-manager.yaml
          sleep 120 # 等待 cert-manager 初始化完成
esac

# 安裝 c7n-kube
helm install c7n-kube c7n/c7n-kube -n $NS --create-namespace --values values.yaml

# down.sh 指令碼內容片段,用於解除安裝 c7n-kube 與 cert-manager
helm -n $NS uninstall c7n-kube

# 可選:刪除 cert-manager
read -p "是否解除安裝 cert-manager?" yn
case $yn in
  [Yy]* ) kubectl delete -f https://github.com/cert-manager/cert-manager/releases/download/v1.12.0/cert-manager.yaml --ignore-not-found
esac

策略驗證與測試

安裝完成後,使用特定的名稱空間(Namespace)與 Pod 清單來驗證策略執行結果:

apiVersion: v1
kind: Namespace
metadata:
  name: policy-test
  labels:
    app: test
    billing: lob-cc
    env: dev
    owner: jimmy
    policy: enabled

---
apiVersion: v1
kind: Pod
metadata:
  name: test-pod-1
  namespace: policy-test
  labels:
    test: c7n # 缺少必要的標籤,如 app, billing 等

spec:
  containers:
    - name: c1 # 略...

策略測試結果分析

  • 由於 test-pod-1 缺少必要的標籤(app、billing、env、owner),根據設定的策略,將會被拒絕建立。
  • 相關日誌與事件資訊可用於進一步的稽核與除錯。
  1. 持續最佳化安裝流程:研究更完善的自動化指令碼,以減少人工干預並提升佈署效率。
  2. 擴充套件策略範疇:開發更多符合實際需求的策略,以強化叢集的安全性和規範性。
  3. 提升系統穩定性:持續監控系統運作狀態,最佳化資源組態,確保高用性。

透過上述措施,能夠進一步鞏固 c7n-kube 在 Kubernetes 環境下的應用基礎,為企業帶來更高的安全性與維運效率。

詳細程式碼解析:

在上述 up.shdown.sh 指令碼中,我們使用了多項技術來實作自動化佈署與管理:

#!/usr/bin/env bash 
set -e 
trap 'catch $? $LINENO' ERR 
catch() { 
    if [ "$1" != "0" ]; then 
        echo "Error $1 occurred on $2" 
    fi 
} 
KUBECTL="kubectl" 
NS=${1:-c7n-kube} 

read -p "Do you wish to install certmanager?" yn 
yn=${yn:-n} 
case $yn in 
    [Yy]* ) ${KUBECTL} apply -f \ https://github.com/cert-manager/cert-manager/releases/download/v1.12.0/cert-manager.yaml 
    sleep 120 
esac 

read -p "Do you wish to install/update the namespace?" yn 
yn=${yn:-n} 
case $yn in 
    [Yy]* ) ${KUBECTL} apply -f k8s/0-ns.yaml 
esac 

helm install c7n-kube c7n/c7n-kube -n $NS \ --create-namespace --values values.yaml 
 

#### 程式碼解析:
此指令碼主要用於自動化安裝 `cert-manager``c7n-kube`。透過使用 `read` 命令進行互動式輸入,允許使用者選擇是否安裝或更新特定元件。同時,利用 `helm` 命令進行 `c7n-kube` 的佈署,並指定對應的 `values.yaml` 組態檔案。

1. **錯誤處理機制**:
   ```bash 
   set -e 
   trap 'catch $? $LINENO' ERR 

這段程式碼啟用了嚴格的錯誤處理,一旦執行過程中出現錯誤,便會觸發 catch 函式輸出錯誤資訊。

  1. 互動式安裝選項

    read -p "Do you wish to install certmanager?" yn 
    case $yn in 
        [Yy]* ) ${KUBECTL} apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.12.0/cert-manager.yaml 
    esac 
    

    使用者可以選擇是否安裝 cert-manager。如果是,則會從指定的 URL 下載並應用相關資源組態。

  2. Helm 安裝指令

    helm install c7n-kube c7n/c7n-kube -n $NS --create-namespace --values values.yaml 
    

    此命令用於透過 Helm 安裝 c7n-kube,並指定名稱空間及自定義的 values.yaml 組態檔案。

  3. 名稱空間管理

    read -p "Do you wish to install/update the namespace?" yn 
    case $yn in 
        [Yy]* ) ${KUBECTL} apply -f k8s/0-ns.yaml 
    esac 
    

    提供選項讓使用者決定是否建立或更新指定的名稱空間。

綜上所述,這些指令碼大幅簡化了 c7n-kube 與相關元件的佈署流程,並提供了靈活的互動選項供使用者自定義安裝步驟。