Gatekeeper 作為 Kubernetes 原生的策略引擎,根據 Open Policy Agent (OPA) 構建,能有效控制和治理叢集資源。理解 Gatekeeper 的核心功能至關重要,包含策略範本的定義、約束的建立以及資料複製的組態。策略範本以 Rego 語言定義可重用的策略邏輯,約束則提供特定引數以應用策略,而 Config 資源則管理需快取的資料以供策略評估。這些機制共同組成了 Gatekeeper 的運作核心,確保叢集安全和合規性。深入瞭解這些組成部分,才能有效運用 Gatekeeper 管理 Kubernetes 叢集。
Gatekeeper:Kubernetes 的政策與治理工具
Gatekeeper 是 Kubernetes 中一個強大的政策和治理工具,允許使用者定義和執行各種策略,以確保叢集的安全性和合規性。本文將探討 Gatekeeper 的核心功能,包括其架構、策略定義和執行機制。
策略範本(Constraint Template)
Gatekeeper 使用策略範本來定義可重用的策略邏輯。策略範本包含三個主要部分:
- Kubernetes CRD 中繼資料:定義策略範本的名稱和相關資訊。
- 輸入引數的架構:定義策略範本所需的輸入引數及其型別。
- 策略定義:使用 Rego 語言定義策略邏輯。
以下是一個範例策略範本,用於檢查容器映像是否來自允許的儲存函式庫:
violation[{"msg": msg}] {
container := input.review.object.spec.containers[_]
satisfied := [good | repo = input.parameters.repos[_] ; good = startswith(container.image, repo)]
not any(satisfied)
msg := sprintf("initContainer <%v> has an invalid image repo <%v>, allowed repos are %v", [container.name, container.image, input.parameters.repos])
}
內容解密:
violation[{"msg": msg}]:定義一個違反策略的規則,當條件滿足時觸發。container := input.review.object.spec.containers[_]:遍歷所有容器。satisfied := [good | repo = input.parameters.repos[_] ; good = startswith(container.image, repo)]:檢查容器的映像是否來自允許的儲存函式庫。not any(satisfied):如果沒有任何一個儲存函式庫符合,則視為違反策略。msg := sprintf(...):生成錯誤訊息。
定義約束(Constraint)
要使用策略範本,需要建立一個約束資源,提供必要的引數。約束資源的 kind 欄位必須與策略範本的名稱相符。
以下是一個範例約束資源,用於檢查生產環境中的 Pod 是否使用允許的映像儲存函式庫:
apiVersion: constraints.gatekeeper.sh/v1beta1
kind: K8sAllowedRepos
metadata:
name: prod-repo-is-openpolicyagent
spec:
enforcementAction: deny
match:
kinds:
- apiGroups: [""]
kinds: ["Pod"]
namespaces:
- "production"
parameters:
repos:
- "openpolicyagent/"
內容解密:
apiVersion和kind:指定約束資源的 API 版本和型別。metadata.name:約束資源的名稱。spec.enforcementAction:定義執行動作,此處為deny,表示違反策略時拒絕請求。spec.match:定義約束的比對條件,此處比對生產環境中的 Pod。spec.parameters:提供策略範本所需的引數,此處為允許的映像儲存函式庫字首。
資料複製(Data Replication)
Gatekeeper 使用 Config 資源來管理需要快取的資料,以便進行策略評估。例如,要檢查 Ingress 資源的主機名稱是否重疊,需要快取所有 Ingress 資源。
以下是一個範例 Config 資源,用於快取 v1 Service、Pod 和 Namespace:
apiVersion: config.gatekeeper.sh/v1alpha1
kind: Config
metadata:
name: config
namespace: gatekeeper-system
spec:
sync:
syncOnly:
- kind: Service
version: v1
- kind: Pod
version: v1
- kind: Namespace
version: v1
內容解密:
apiVersion和kind:指定 Config 資源的 API 版本和型別。metadata.name和metadata.namespace:Config 資源的名稱和名稱空間。spec.sync.syncOnly:定義需要快取的資源型別和版本。
使用執行動作和稽核(Using Enforcement Action and Audit)
Gatekeeper 允許使用者組態執行動作和稽核功能。執行動作可以設為 deny、warn 或 dryrun,以滿足不同的需求。
使用 Gatekeeper 進行政策與治理的最佳實踐
Gatekeeper 是根據 Open Policy Agent(OPA)建構的 Kubernetes 原生政策引擎,能夠對叢集內的資源進行有效的政策控制與治理。在本章中,我們將探討如何利用 Gatekeeper 實施政策與治理,並介紹相關的最佳實踐。
瞭解 Gatekeeper 的基本功能
Gatekeeper 提供了兩種主要的政策控制功能:資源驗證(Validation)和變更(Mutation)。資源驗證功能可以檢查叢集內的資源是否符合預先定義的政策,而變更功能則可以在資源建立時對其進行修改。然而,變更功能並不被視為最佳實踐,因為它可能會破壞 Kubernetes 的宣告式組態特性。
使用 Enforcement Action 和 Audit 進行政策控制
Gatekeeper 的 enforcementAction 欄位允許定義政策違規時的處理方式。當設定為 deny 時,違規的資源將無法建立,並會傳回錯誤訊息。如果設定為 warn,資源仍可建立,但會記錄警告訊息並傳回給使用者。最後,如果設定為 dryrun,資源將被建立,但違規的資源將被記錄在稽核日誌中。
無論選擇何種 enforcementAction,Gatekeeper 都會定期評估叢集內的資源是否符合政策,並提供稽核日誌以協助檢測和修正違規的資源。
稽核功能的例項
假設我們已經定義了一個名為 prod-repo-is-openpolicyagent 的約束(Constraint),並且在生產名稱空間中已經有一個名為 nginx 的 Pod 在執行。我們可以使用稽核功能檢查該 Pod 是否符合政策:
$ kubectl get k8sallowedrepos
NAME ENFORCEMENT-ACTION TOTAL-VIOLATIONS
prod-repo-is-openpolicyagent deny 1
$ kubectl get k8sallowedrepos prod-repo-is-openpolicyagent -o yaml
apiVersion: constraints.gatekeeper.sh/v1beta1
kind: K8sAllowedRepos
metadata:
annotations:
kubectl.kubernetes.io/last-applied-configuration: ...
creationTimestamp: "..."
generation: 1
name: prod-repo-is-openpolicyagent
resourceVersion: "..."
uid: ...
spec:
match:
kinds:
- apiGroups:
- ""
kinds:
- Pod
namespaces:
- production
parameters:
repos:
- openpolicyagent/
status:
auditTimestamp: "2022-11-27T23:37:42Z"
totalViolations: 1
violations:
- enforcementAction: deny
group: ""
kind: Pod
message: container <nginx> has an invalid image repo <nginx>, allowed repos are ["openpolicyagent/"]
name: nginx
namespace: production
version: v1
程式碼解析:
apiVersion: constraints.gatekeeper.sh/v1beta1
kind: K8sAllowedRepos
metadata:
name: prod-repo-is-openpolicyagent
spec:
match:
kinds:
- apiGroups:
- ""
kinds:
- Pod
namespaces:
- production
parameters:
repos:
- openpolicyagent/
內容解密:
apiVersion和kind:定義了 Kubernetes 資源的 API 版本和型別,這裡是 Gatekeeper 的約束資源。metadata.name:指定了約束的名稱,在這裡是prod-repo-is-openpolicyagent。spec.match.kinds:定義了要比對的 Kubernetes 資源型別,這裡是 Pod。spec.match.namespaces:指定了要檢查的名稱空間,這裡是production。spec.parameters.repos:定義了允許的容器映象倉函式庫,這裡只允許openpolicyagent/。
使用 gator CLI 測試政策
Gatekeeper 提供了一個名為 gator 的 CLI 工具,可以在本地環境中測試政策和評估結果。這使得開發人員可以在將政策佈署到生產叢集之前,先在本地進行測試和修正。
Gatekeeper 的最佳實踐
在使用 Gatekeeper 時,應遵循以下最佳實踐:
- 確定要檢查和執行的 Kubernetes 資源規格欄位。
- 將約束的範圍縮小到特定的資源,以確保一致的政策行為。
- 在已經佈署資源的叢集中,使用
warn和dryrun以及稽核功能來修正違規的資源,然後再將enforcementAction設定為deny。 - 避免使用變更(Mutation)政策,而是考慮使用其他宣告式方法,例如 GitOps。
- 不要同步和執行敏感資料,例如 Kubernetes Secrets。
管理多個 Kubernetes 叢集的最佳實踐
在採用 Kubernetes 的過程中,您可能會遇到需要管理多個叢集的情況。為了更好地理解多叢集管理的挑戰和解決方案,本章將探討多叢集管理與聯邦(federation)之間的差異、管理多個叢集的工具,以及管理多個叢集的操作模式。
為什麼需要多個叢集?
Kubernetes 最初被設計用來將多個工作負載整合到一個叢集中,但某些情況下,您可能需要使用多個叢集。例如,跨區域的工作負載、爆炸半徑(blast radius)問題、法規遵從性要求以及專門的工作負載等。
考量因素
在決定是否採用多叢集架構時,需要考慮以下幾個因素:
- 爆炸半徑
- 法規遵從性
- 安全性
- 硬性多租戶(hard multitenancy)
- 根據區域的工作負載
- 專門的工作負載
爆炸半徑是設計多叢集架構時需要考慮的一個重要因素。就像在微服務架構中使用斷路器、重試機制、隔板和速率限制來限制系統損壞的範圍一樣,多個叢集可以幫助防止由於軟體問題引起的連鎖故障。
法規遵從性是另一個需要考慮的因素。某些工作負載,例如涉及支付卡行業(PCI)或健康保險可攜性和責任法案(HIPAA)的應用,可能需要特定的安全強化、非分享元件或專門的工作負載需求。在這種情況下,將這些工作負載與一般用途工作負載分開會更容易管理。
在大規模 Kubernetes 叢集中,安全性可能會變得難以管理。隨著越來越多的團隊加入叢集,每個團隊可能都有不同的安全需求。在單一叢集中管理 RBAC、網路策略和 Pod 安全策略可能會變得非常困難。使用多個叢集可以限制由於組態錯誤引起的安全風險。
Kubernetes 並不提供硬性多租戶功能,因為所有在叢集中執行的負載分享相同的 API 界限。雖然名稱空間(namespace)提供了良好的軟性多租戶功能,但不足以保護叢集免受惡意負載的影響。硬性多租戶通常是雲端服務提供商或託管 SaaS 軟體的需求。
多叢集設計挑戰
在選擇多叢集設計時,您可能會遇到一些挑戰。這些挑戰可能包括:
- 資料複製
- 服務發現
- 網路路由
- 維運管理
- 連續佈署
多叢集管理的工具和技術
為了克服多叢集設計挑戰,您可以使用各種工具和技術。例如,Kubernetes 聯邦(federation)可以幫助您管理跨多個叢集的資源。
Kubernetes 聯邦
Kubernetes 聯邦是一種將多個叢集納入單一控制平面的技術。這使得您可以在多個叢集中管理和協調資源。
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: example-ingress
spec:
rules:
- host: example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: example-service
port:
number: 80
內容解密:
上述 YAML 程式碼定義了一個 Kubernetes Ingress 資源,用於將流量路由到名為 example-service 的服務。其中:
apiVersion和kind指定了資源的 API 版本和型別。metadata部分定義了資源的名稱。spec部分定義了 Ingress 資源的規格,包括規則和後端服務。
在這個例子中,Ingress 資源將所有到達 example.com 的流量路由到 example-service 服務的 80 埠。
多叢集管理挑戰與解決方案
在跨地域和多叢集佈署工作負載時,資料複製和一致性一直是關鍵挑戰。執行這些服務時,需要決定哪些服務執行在哪裡,並制定複製策略。大多數資料函式庫都有內建的複製工具,但需要設計應用程式以處理複製策略。對於NoSQL型資料函式庫服務,這可能更容易,因為它們可以處理跨多個例項的擴充套件,但仍需要確保應用程式能夠處理跨地域的最終一致性或至少跨地域的延遲。一些雲端服務,如Google Cloud Spanner和Microsoft Azure CosmosDB,已建立資料函式庫服務以幫助處理跨多個地域的資料複雜性。
每個Kubernetes叢集都會佈署自己的服務發現登入檔,但登入檔並不同步於多個叢集之間。這使得應用程式難以輕易識別和發現彼此。像HashiCorp的Consul這樣的工具可以透明地同步來自多個叢集的服務,甚至是駐留在Kubernetes外部的服務。其他像Istio、Linkerd和Cilium等工具正在建立多叢集架構,以擴充套件叢集之間的服務發現。
網路挑戰與解決方案
Kubernetes使叢集內的網路變得非常容易,因為它是一個扁平網路,避免使用網路位址轉換(NAT)。如果需要路由進出叢集的流量,這就變得更加複雜。進入叢集的入口流量被實作為入口資源與叢集之間的1:1對映,因為它不支援具有入口資源的多叢集拓撲結構。您還需要考慮叢集之間的出口流量以及如何路由該流量。當應用程式駐留在單個叢集內時,這很容易,但引入多叢集時,您需要考慮具有應用程式依賴性的服務的額外跳躍延遲。對於具有緊密耦合依賴性的應用程式,您應該考慮在同一個叢集內執行這些服務,以消除延遲和額外的複雜性。
程式碼範例:組態Kubernetes入口資源
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: example-ingress
spec:
rules:
- host: example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: example-service
port:
number: 80
內容解密:
apiVersion和kind定義了Kubernetes資源的API版本和型別。metadata部分包含了資源的中繼資料,如名稱。spec部分定義了入口資源的規格,包括規則和後端服務組態。rules定義了根據主機名稱和路徑的路由規則。backend指定了處理流量的後端服務和連線埠。
營運管理挑戰
管理多叢集的最大開銷之一是營運管理。您現在可能需要管理環境中的許多叢集,而不是一兩個叢集。管理多叢集的最重要方面之一是確保您有良好的自動化實踐,因為這將有助於減少營運負擔。在自動化叢集時,您需要考慮基礎設施佈署和管理叢集的附加功能。使用像HashiCorp的Terraform這樣的工具可以幫助佈署和管理跨叢集艦隊的一致狀態。
使用Terraform進行基礎設施即程式碼(IaC)
Terraform提供了一種可重複的方式來佈署叢集。使用IaC工具的好處包括:
- 一致性:確保所有叢集具有相同的組態。
- 版本控制:可以對基礎設施組態進行版本控制。
- 重複佈署:可以輕易地在不同環境中重複佈署相同的基礎設施。
多叢集佈署管理
管理多叢集佈署的第一步是使用像Terraform這樣的IaC工具來設定佈署。自動化是成功管理環境中多個叢集的關鍵。您可能在第一天沒有實作所有自動化,但您應該優先考慮自動化叢集佈署和營運的所有方面。
Kubernetes Cluster API是一個有趣的專案,它為叢集建立、組態和管理帶來了宣告式、Kubernetes風格的API。它在核心Kubernetes之上提供了可選的附加功能。Cluster API透過共同的API提供了叢集級別的組態宣告,這將使您能夠輕易地自動化和圍繞叢集自動化構建工具。
佈署和管理模式
Kubernetes運算元被引入作為軟體基礎設施概念的實作。使用它們可以讓您抽象出在Kubernetes叢集中佈署應用程式和服務。例如,假設您想要將Prometheus標準化為監控Kubernetes叢集。您需要為每個叢集和團隊建立和管理各種物件(佈署、服務、入口等)。您還需要維護Prometheus的基本組態,如版本、永續性、保留策略和副本。可以想象,在大量叢集和團隊中維護這樣的解決方案可能很困難。
使用Kubernetes運算元簡化佈署
Kubernetes運算元允許您封裝應用程式的佈署和管理邏輯,使其更容易在多個叢集中保持一致性和可重複性。