Open Policy Containers (OPCR) 提供了一種將 OPA 策略和資料封裝成 OCI 映像檔的標準化方法,讓策略的版本控制、佈署和管理更加便捷。此方法利用了容器技術的優勢,使得在 Kubernetes 環境中佈署和更新策略變得更加容易。透過 OCI 映像檔,可以確保策略的一致性,並簡化跨不同環境的策略分發。此外,OPCR 還支援資料範圍界定,允許 OPA 從多個來源載入資料,而不會造成衝突,提升了策略管理的靈活性。結合 OCI 映像檔和 OPA,可以有效地提升 Kubernetes 叢集的安全性與合規性。
由於容器化的普及和 OCI 標準的建立,使用 OCI 映像檔來封裝和分發 OPA 策略和資料已成為一個趨勢。透過 OPCR CLI,可以輕鬆地將策略和資料封裝成 OCI 映像檔,並推播到容器登入檔,例如 GitHub Container Registry (GHCR)。在 Kubernetes 叢集中,OPA 可以直接從容器登入檔中提取策略映像檔,實作策略的自動化佈署和更新。這不僅簡化了策略管理流程,也提高了策略佈署的效率和可靠性。
使用OCI映像檔與OPA及Open Policy Containers
Open Policy Containers(OPCR)結合了Open Container Initiative(OCI)登入檔和CLI,用於封裝和儲存OPA政策和資料。OPCR於2022年12月12日被接受為CNCF的沙盒專案。透過OPCR,您可以將政策和資料建置、版本控制並釋出為OCI映像檔。由於容器化的廣泛採用以及OCI建立和分享的開放標準,將政策和資料以OCI相容的容器映像檔形式提供給OPA代理使用是非常合理的。從0.40.0版本開始,OPA就可以使用以OCI映像檔形式封裝的政策/資料捆綁包。
入門
首先,我建立了一個具有最低許可權的GitHub個人存取權杖(PAT),以便透過OPCR CLI登入我的GitHub Container Registry(GHCR)帳戶。獲得帳戶和憑證後,我安裝了CLI並使用它登入OPCR:
# 安裝OPCR CLI
$ brew install opcr-io/tap/policy
# 使用GitHub PAT作為密碼登入遠端帳戶
$ GH_PAT=`cat <PATH_TO_GH_PAT_FILE>`
policy login -u jimmyraywv -p "$GH_PAT"
Logging in.
server: ghcr.io
user: jimmyraywv
OK.
內容解密:
此段落程式碼展示瞭如何安裝OPCR CLI並使用GitHub PAT登入GHCR帳戶。其中,brew install
用於安裝CLI,policy login
命令則用於登入,-u
引數指定使用者名稱,-p
引數指定密碼(在此例中為GitHub PAT)。登入成功後,會顯示伺服器位址和使用者名稱,並提示OK.
表示登入成功。
建置OCI映像檔
接下來,我使用CLI從以下捆綁包材料建置了一個政策OCI映像檔:
# OPCR OCI映像檔內容
-rw-r--r-- .manifest
-rw-r--r-- data.json
-rw-r--r-- policy.rego
除了資料和Rego檔案外,我還新增了一個可選的manifest檔案。該檔案是一個具有特定格式和專案的JSON檔案。
內容解密:
此處列出了建置OCI映像檔所需的檔案,包括.manifest
、data.json
和policy.rego
。.manifest
檔案用於定義捆綁包的元資料,而data.json
和policy.rego
則分別包含資料和政策定義。
使用Manifest檔案進行資料範圍界定
我使用manifest檔案的主要原因是為了在OPA中進行資料範圍界定。如果OPA被組態為從捆綁包下載資料,其預設行為是從捆綁包載入其整個政策和資料快取。透過在捆綁包manifest中定義名稱空間,可以更容易地對來自多個資料來源的政策和資料進行範圍界定。
{
"roots": ["normal","pacbook"]
}
當載入此捆綁包時,只有來自roots
專案的資料才會被寫入或覆寫,從而允許OPA從多個來源載入資料而不會發生資料衝突。
內容解密:
此JSON程式碼定義了一個捆綁包manifest,其中包含一個roots
欄位,用於指定要載入到OPA中的資料根名稱空間。這樣可以避免不同資料來源之間的衝突。
建置和佈署映像檔
我使用Makefile來建置映像檔,以確保流程的可重複性:
# 建置捆綁包材料
$ make build
[METADATA]
timestamp: [2022-12-11_05:54:07PM]
git commit: [793309a9eaf0ad39a61c5c964e813299752da8ee]
Image version: [v0.1.0-793309a9ea]
policy build ./bundle-material -t ghcr.io/jimmyraywv/pacbook:v0.1.0-793309a9ea
Created new image.
digest: sha256:cabd3a636541622cde59b92bf22033627bc137840cefc57ed6265f000a12e187
Tagging image.
reference: ghcr.io/jimmyraywv/pacbook:v0.1.0-793309a9ea
內容解密:
此Makefile程式碼片段展示瞭如何使用make build
命令建置OCI映像檔。其中,policy build
命令用於建置映像檔,-t
引數指定了映像檔的標籤。
檢視和管理映像檔
建置好的映像檔可以像Docker映像檔一樣被檢視和管理:
# 列出映像檔
$ policy images
REPOSITORY TAG IMAGE ID CREATED SIZE
ghcr.io/jimmyraywv/pacbook v0.1.0-793309a9ea cabd3a636541 1 hour ago 348B
# 檢查映像檔
$ policy inspect ghcr.io/jimmyraywv/pacbook:v0.1.0-793309a9ea
digest: sha256:cabd3a636541622cde59b92bf22033627bc137840cefc57ed6265f000a12e187
size: 348
created_at: 2022-12-11 17:54:07.502764 -0500 EST
updated_at: 2022-12-11 17:54:07.502764 -0500 EST
Annotations
ANNOTATION VALUE
org.opencontainers.image.created 2022-12-11T22:54:07Z
org.opencontainers.image.ref.name ghcr.io/jimmyraywv/pacbook:v0.1.0-793309a9ea
org.opencontainers.image.title ghcr.io/jimmyraywv/pacbook
org.openpolicyregistry.type policy
內容解密:
此處展示瞭如何使用policy images
命令列出可用的OCI映像檔,以及如何使用policy inspect
命令檢查特定映像檔的詳細資訊。
使用建置的映像檔
我使用policy repl
命令並指定政策來執行OPA REPL,並查看了資料:
# 使用新建立的政策/資料捆綁包執行OPA REPL
$ policy repl ghcr.io/jimmyraywv/pacbook:v0.1.0-793309a9ea
running policy [ghcr.io/jimmyraywv/pacbook:v0.1.0-793309a9ea]
# 在OPA REPL中檢視資料
> data
{
"normal": {
"stuff": [
{
"lead": "jimmy",
"method": "GET",
"project": "book"
}
]
},
"pacbook": {
"things": {
"allow": false
}
}
}
內容解密:
此段落程式碼展示瞭如何使用建置的OCI映像檔執行OPA REPL,並在REPL中查詢資料。查詢結果顯示了載入的資料結構。
將映像檔推播到遠端登入檔
最後,我將映像檔推播到遠端登入檔:
# 推播映像檔
$ make push
[METADATA]
timestamp: [2022-12-11_05:58:23PM]
git commit: [793309a9eaf0ad39a61c5c964e813299752da8ee]
Image version: [v0.1.0-793309a9ea]
policy push ghcr.io/jimmyraywv/pacbook:v0.1.0-793309a9ea
Resolved ref [ghcr.io/jimmyraywv/pacbook:v0.1.0-793309a9ea].
digest: sha256:cabd3a636541622cde59b92bf22033627bc137840cefc57ed6265f000a12e187
Pushed ref [ghcr.io/jimmyraywv/pacbook:v0.1.0-793309a9ea].
digest: sha256:7a6b6d5187bb6de682609f671dc3012499726f407b1fcb08e2f06fae007801bc
內容解密:
此Makefile程式碼片段展示瞭如何使用make push
命令將OCI映像檔推播到遠端登入檔。其中,policy push
命令用於推播映像檔。
未來展望與建議
自動化政策更新流程
未來的發展方向之一是實作政策更新流程的自動化。透過結合CI/CD管道,可以在每次政策變更時自動建置、測試並佈署新的OCI映像檔。這樣不僅可以提高效率,還能減少人為錯誤。
多租戶環境下的政策管理
在多租戶環境中,如何有效地隔離和管理不同租戶的政策是一個挑戰。可以考慮使用名稱空間或標籤來區分不同租戶的政策,並利用OCI映像檔的分層特性來最佳化儲存和分發。
安全性考量
在使用OCI映像檔分發政策時,需要確保傳輸過程的安全性。可以採用簽署映像檔的方式來驗證其完整性和真實性,防止惡意篡改。
OPCR流程圖示
graph LR; A[開始] --> B[建立GitHub PAT]; B --> C[安裝OPCR CLI]; C --> D[登入GHCR]; D --> E[建置OCI映像檔]; E --> F[推播映像檔到GHCR]; F --> G[在OPA中使用映像檔]; G --> H[結束];
圖表翻譯: 此圖示展示了使用OPCR建置和管理OCI映像檔的主要流程。首先,建立GitHub個人存取權杖(PAT),然後安裝OPCR CLI並登入GitHub Container Registry(GHCR)。接著,建置OCI映像檔並將其推播到GHCR,最後在OPA中使用該映像檔。整個流程展示了從準備到佈署的完整步驟。
策略即程式碼與 Kubernetes
2018 年,我接手長官一個團隊,該團隊正在開發用於佈建 Kubernetes 的工具,類別似於「Kubernetes the hard way」。我們主要使用 Bash shell 指令碼開發工具來佈建和管理叢集。當時,我已經斷斷續續地使用 Kubernetes 近兩年。我們曾考慮使用 kOps 等工具來幫助建立和升級叢集,但當時 kOps 並不能滿足我們的雲端運算需求。
即使在現今有許多自動化服務、平台、API 和工具可供使用來幫助建立和管理 Kubernetes,我仍然建議您研究並嘗試透過「Kubernetes the hard way」的方式來執行。這段經驗對我的學習曲線來說是無價的。
我的首要任務之一是在 Kubernetes 內部實施控制措施,以防止不必要的叢集變更。我們舉辦了一場內部駭客松,以幫助產生有關 Kubernetes 控制的想法。那是我第一次將 PaC 用於 Kubernetes,並發現如何將策略整合到 Kubernetes API 中。
在本章中,我們將探討如何將 PaC 與 Kubernetes 結合使用,以建立控制措施來防止不必要的變更、設定指導方針以引導最佳實踐,並執行授權。我將介紹有關 PaC 和 Kubernetes 整合的概念,並在必要時使用範例。在後續章節中,我們將更深入地探討每個 PaC 解決方案。
CNCF 簡介與 Kubernetes 社群組織
首先,我將簡要回顧雲原生運算基金會(CNCF)並介紹 Kubernetes 社群組織;然後,我將帶領您快速瀏覽 PaC 可以為 Kubernetes 提供的各種使用案例和解決方案。我們將為後續更探討每個 PaC 解決方案做好準備。
為何使用 PaC 與 Kubernetes?
在探討細節之前,讓我們先了解為何 PaC 與 Kubernetes 的結合如此重要。Kubernetes 是一個強大的容器協調平台,但其靈活性也帶來了複雜性。PaC 提供了一種方法,可以在不修改程式碼的情況下,將策略和控制措施整合到 Kubernetes 中。
使用 PaC 的好處
- 動態策略管理:PaC 允許您動態地管理和更新策略,而無需更改程式碼或重新佈署應用程式。
- 提高安全性:透過將策略作為程式碼,您可以確保您的 Kubernetes 叢集遵循安全最佳實踐,並防止不必要的變更。
- 一致性和合規性:PaC 有助於確保您的 Kubernetes 環境保持一致性和合規性,從而降低風險。
PaC 在 Kubernetes 中的應用場景
存取控制:使用 PaC 可以實作細粒度的存取控制,確保只有授權使用者和服務可以存取特定的資源。
package kubernetes.authz # 允許具有特定標籤的 pod 被建立 allow { input.request.kind.kind == "Pod" input.request.object.metadata.labels["allow"] == "true" }
內容解密:
這段 Rego 程式碼定義了一個名為
allow
的規則,用於決定是否允許建立具有特定標籤的 Pod。當請求的kind
為Pod
且其metadata.labels
中包含allow: true
時,該規則允許請求透過。資源管理:PaC 可以用於管理 Kubernetes 資源,例如限制特定名稱空間中的資源使用量。
package kubernetes.resource # 限制特定名稱空間中的 CPU 使用量 deny[msg] { input.request.kind.kind == "Pod" input.request.namespace == "default" cpu_request := input.request.object.spec.containers[0].resources.requests.cpu cpu_request > "2" msg := "CPU request exceeds the limit" }
內容解密:
此 Rego 程式碼定義了一個名為
deny
的規則,用於檢查在default
名稱空間中建立的 Pod 是否超過了 CPU 請求限制。如果 Pod 的 CPU 請求超過了設定的閾值(此例中為 2 核),則該規則將拒絕請求並傳回錯誤訊息。合規性檢查:透過 PaC,您可以實施合規性檢查,以確保您的 Kubernetes 資源符合組織的安全和合規要求。
PaC 工具與 Kubernetes 的整合
有多種 PaC 工具可以與 Kubernetes 整合,提供策略管理和執行的能力。一些流行的工具包括:
Open Policy Agent (OPA):OPA 是一個通用策略引擎,可以與 Kubernetes 整合,提供動態存取控制和資源管理。
Kyverno:Kyverno 是另一個流行的 PaC 工具,專門為 Kubernetes 設計,提供策略管理和驗證功能。
Gatekeeper:Gatekeeper 是 OPA 的一個擴充套件,專門為 Kubernetes 設計,提供根據 OPA 的策略管理。
CNCF與Kubernetes策略管理
在第一章中,我們介紹了雲原生計算基金會(Cloud Native Computing Foundation, CNCF)及其專案結構。在本章中,我們將簡要介紹Kubernetes如何融入CNCF。Kubernetes於2016年被納入CNCF,目前已成為畢業專案。然而,CNCF仍然深度參與Kubernetes的方向以及Kubernetes專案社群。
Kubernetes專案社群的組織結構
在Kubernetes專案社群中,各項活動的管理由特殊興趣小組(Special Interest Groups, SIGs)負責。這些SIGs涵蓋了廣泛的努力,以改善Kubernetes。每個SIG都是實踐社群,專注於Kubernetes專案中特定且相關的工作。特別是,Auth SIG(sig-auth)專注於與Kubernetes身份驗證(AuthN)、授權(AuthZ)和安全策略相關的持續性工作。
工作小組(Working Groups, WGs)的角色
當需要更狹隘的焦點進行臨時工作時,會成立工作小組(WGs)。SIGs贊助WGs,並且也是WG努力的利益相關者。策略WG(Policy WG)專注於Kubernetes的策略管理架構和策略提案。sig-auth贊助了策略WG,並且是列出的利益相關者。在第三章中,您已經瞭解了儲存在sig-security專案中的Kubernetes策略管理白皮書。
使用PaC增強和控制Kubernetes操作
Kubernetes提供的豐富功能集減少或消除了在規模上執行容器所涉及的常見任務和繁重工作。其中包括安全組態,以及可以遵循最佳實踐的設定。正如安全性不是簡單地在軟體專案結束時附加的東西一樣,計劃一個Kubernetes叢集——或其集合——需要在您的Kubernetes之旅開始時(第0天,如果您願意的話)進行安全設計和決策。
策略即程式碼(Policy as Code, PaC)的作用
即使您擁有所有可以拉動的槓桿來保護您的Kubernetes應用程式並加強其執行的強健性,Kubernetes也不會強迫您遵循最佳實踐或建議的安全設定。這個差距可以透過PaC來填補。為了了解PaC如何增強Kubernetes並幫助控制叢集內的行為,我們必須首先檢查如何透過API伺服器請求對正在執行的Kubernetes叢集進行更改。
API伺服器請求
Kubernetes元件分為在控制平面(Control Plane, CP)上執行的元件和在資料平面(Data Plane, DP)中的節點上執行的元件。CP元件管理叢集。無需探討Kubernetes架構,圖4-1顯示了CP元件和DP(節點)元件之間的關係。
Kubernetes API伺服器的關鍵角色
將所有事物聯絡在一起的關鍵元件是Kubernetes API伺服器。API伺服器處理來自外部客戶端(如kubectl)的請求,以及內部客戶端(如節點kubelet代理和控制器)的請求。
graph LR A[Kubernetes API 伺服器] -->|請求處理| B[控制平面元件] A -->|請求處理| C[節點kubelet代理] B -->|變更持久化| D[etcd] C -->|變更持久化| D
圖表翻譯: 此圖示展示了Kubernetes API伺服器與控制平面元件、節點kubelet代理之間的關係,以及變更如何持久化到etcd中。
准入控制器(Admission Controllers)
在Kubernetes中,准入控制器是在API伺服器請求經過身份驗證和授權之後,但在請求導致對etcd進行更改之前執行的程式碼。准入控制器被編譯到Kubernetes中,用於攔截傳入的請求。這些控制器可以是變異型、驗證型,甚至兩者兼有,並且它們為叢集安全性和行為增加了內建控制。
# 變異准入控制器
Loaded 12 mutating admission controller(s) successfully in the following order:
NamespaceLifecycle,LimitRanger,ServiceAccount,NodeRestriction,TaintNodesByCondition,
Priority,DefaultTolerationSeconds,DefaultStorageClass,StorageObjectInUseProtection,
RuntimeClass,DefaultIngressClass,MutatingAdmissionWebhook.
# 驗證准入控制器
Loaded 11 validating admission controller(s) successfully in the following order:
LimitRanger,ServiceAccount,PodSecurity,Priority,PersistentVolumeClaimResize,
RuntimeClass,CertificateApproval,CertificateSigning,CertificateSubjectRestriction,
ValidatingAdmissionWebhook,ResourceQuota.
內容解密:
上述輸出顯示了minikube 1.27.1中預設載入的變異和驗證准入控制器。它們按照特定的順序載入,以確保請求在被持久化到etcd之前得到正確處理。
隨著Kubernetes的不斷發展,PaC和策略管理的角色將變得越來越重要。未來,我們可以預期看到更多根據PaC的創新和改進,以進一步增強Kubernetes的安全性和可管理性。同時,CNCF和Kubernetes社群將繼續合作,以推動雲原生技術的發展和採用。
參考資料
- Kubernetes 社群檔案:https://kubernetes.io/docs/
- CNCF 網站:https://www.cncf.io/