Kubernetes 准入控制是保護叢集安全的重要機制,允許在資源持久化前進行驗證和修改。本文將探討如何組態准入 Webhook,包括避免多個 Webhook 修改同一欄位、確保 Webhook 的冪等性、以及合理設定 FailurePolicy 等。同時也將探討 Kubernetes 的授權機制,包括 ABAC、RBAC 和 Webhook 等授權模組的組態與使用,以及如何使用 SelfSubjectAccessReview 和 kubectl auth can-i 命令驗證許可權。最後,本文將介紹 GitOps 的核心概念、優勢和最佳實踐,以及如何使用 Flux 工具實作 GitOps 工作流程,並探討不同儲存函式庫結構和秘密管理方案的優缺點。
Kubernetes 准入控制與授權的最佳實踐
Kubernetes 的准入控制(Admission Control)是確保叢集安全性和穩定性的關鍵機制之一。它允許管理員在資源被持久化之前對其進行驗證和修改。本文將探討 Kubernetes 准入控制的最佳實踐,包括准入 Webhook 的組態、授權模組的使用等。
避免多個 Mutating Admission Webhook 修改相同欄位
當組態多個 Mutating Admission Webhook 時,需要注意避免它們修改相同的欄位,因為這可能導致不一致的行為。為瞭解決這個問題,可以使用 Validating Admission Webhook 來驗證最終的資源清單是否符合預期。
確保 Mutating Admission Webhook 是冪等的
Mutating Admission Webhook 必須是冪等的,這意味著它們必須能夠處理已經被修改的物件。這樣可以確保即使 Webhook 被多次呼叫,結果仍然是一致的。
合理組態 FailurePolicy
failurePolicy 欄位定義了當准入 Webhook 無法存取或遇到無法識別的錯誤時,API 伺服器應該如何處理請求。可以將其設定為 Ignore 或 Fail。Ignore 表示繼續處理請求,而 Fail 表示拒絕整個請求。需要根據具體情況選擇合適的策略。
內容解密:
failurePolicy的選擇取決於具體的業務需求和安全要求。- 設定為
Ignore可能會導致某些策略未被應用,而設定為Fail可能會導致請求被拒絕。 - 需要謹慎評估兩者的影響。
准入 Webhook 必須快速回應
准入 Webhook 的回應時間會直接影響使用者請求的處理速度。所有準入 Webhook 呼叫都組態了 30 秒的超時時間,超過該時間後,failurePolicy 將生效。因此,應該避免在准入 Webhook 中使用複雜的邏輯或依賴外部系統。
範圍設定準入 Webhook
可以使用 NamespaceSelector 欄位來限制准入 Webhook 的作用範圍。這樣可以確保只有特定的名稱空間中的資源才會被處理。
使用範例:
apiVersion: admissionregistration.k8s.io/v1
kind: MutatingWebhookConfiguration
metadata:
name: example-webhook
webhooks:
- name: example-webhook.example.com
namespaceSelector:
matchLabels:
admission-webhook: enabled
內容解密:
namespaceSelector可以根據名稱空間的標籤來選擇需要處理的資源。- 這樣可以實作對特定名稱空間的精細控制。
- 需要根據實際需求組態合適的標籤。
將准入 Webhook 佈署在單獨的名稱空間中
為了避免准入 Webhook 處理自身的資源,可以將其佈署在單獨的名稱空間中,並使用 NamespaceSelector 排除該名稱空間。
不要觸及 kube-system 名稱空間
kube-system 名稱空間是 Kubernetes 叢集中保留的名稱空間,用於執行系統級服務。應該避免對該名稱空間中的資源應用准入 Webhook。
使用 RBAC 鎖定準入 Webhook 組態
准入 Webhook 組態是一種 root 級別的操作,需要使用 RBAC 進行嚴格控制,以防止未授權的存取或修改。
不要傳送敏感資料
准入 Webhook 可能會接收到敏感資訊,如 Kubernetes Secrets 或 ConfigMaps。應該盡量減少傳送給准入 Webhook 的資料,以避免敏感資訊洩露。
Kubernetes 授權機制
Kubernetes 的授權機制用於確定使用者是否有權對特定資源執行特定操作。本文將介紹 Kubernetes 中的授權模組及其組態方法。
授權模組
Kubernetes 提供了多種授權模組,包括:
- Attribute-Based Access Control (ABAC):允許透過本地檔案組態授權策略。
- Role-Based Access Control (RBAC):允許透過 Kubernetes API 組態授權策略。
- Webhook:允許透過遠端 REST 端點處理授權請求。
- Node:專門用於授權來自 kubelet 的請求。
圖示說明:
此圖示說明瞭 Kubernetes 中的請求流程,包括認證、授權和准入控制等步驟。
內容解密:
- 圖中展示了 Kubernetes 請求流程的主要步驟。
- 每個步驟都有其特定的功能和作用。
- 圖表有助於理解 Kubernetes 的安全機制。
Kubernetes授權機制深度解析與最佳實踐
Kubernetes 的授權機制是確保叢集安全性的關鍵組成部分。本文將探討 Kubernetes 的授權模式、相關工具及其最佳實踐。
授權模式組態與運作原理
Kubernetes 的授權模組由叢集管理員透過 API 伺服器的 --authorization-mode 旗標進行組態。多個模組可以同時啟用,並按照設定的順序進行檢查。與准入控制器不同,只要有一個授權模組允許請求,該請求就可以繼續進行。只有當所有模組都拒絕請求時,才會向使用者傳回錯誤。
ABAC 授權模組例項解析
ABAC(Attribute-Based Access Control)是一種根據屬性的存取控制機制。以下是一個授予使用者 Mary 對 kube-system 名稱空間中 pod 的唯讀存取許可權的策略定義:
apiVersion: abac.authorization.kubernetes.io/v1beta1
kind: Policy
spec:
user: mary
resource: pods
readonly: true
namespace: kube-system
若 Mary 嘗試存取 demo-app 名稱空間中的 pod,由於她沒有相應許可權,該請求將被拒絕:
apiVersion: authorization.k8s.io/v1
kind: SubjectAccessReview
spec:
resourceAttributes:
verb: get
resource: pods
namespace: demo-app
使用 SelfSubjectAccessReview 進行許可權驗證
Kubernetes 提供了一組 API 用於檢查使用者的存取許可權,例如 SelfSubjectAccessReview。以下是一個使用 SelfSubjectAccessReview 檢查使用者許可權的範例:
$ cat << EOF | kubectl create -f - -o yaml
apiVersion: authorization.k8s.io/v1
kind: SelfSubjectAccessReview
spec:
resourceAttributes:
verb: get
resource: pods
namespace: demo-app
EOF
kubectl auth can-i 命令的使用
Kubernetes 也內建了 kubectl auth can-i 命令來簡化許可權檢查的過程:
$ kubectl auth can-i get pods --namespace demo-app
yes
$ kubectl auth can-i get pods --namespace demo-app --as mary
yes
RBAC 與 Webhook 授權模組簡介
- RBAC(Role-Based Access Control):根據角色的存取控制,詳細內容將在其他章節中介紹。
- Webhook:允許叢集管理員組態外部 REST 端點來委託授權流程。
Kubernetes 授權最佳實踐
- 避免在多個控制平面叢集中使用 ABAC:由於 ABAC 策略需要儲存在每個控制平面主機的檔案系統上並保持同步,因此不建議在多控制平面叢集中使用。
- 謹慎使用 Webhook 模組:雖然 Webhook 模組功能強大,但由於其可能導致叢集故障,因此除非經過徹底測試和驗證,否則不建議使用。
GitOps 與應用佈署
GitOps 是一種利用 Git 作為單一真實來源來佈署和管理 Kubernetes 應用程式的方法。本章節將探討 GitOps 的原理、優勢、工具,以及最佳實踐。
GitOps 的核心概念與優勢
GitOps 利用 Git 的版本控制功能來管理 Kubernetes 資源的佈署和變更,從而簡化應用程式的佈署和維運工作。其主要優勢包括:
- 版本控制:所有變更都有版本記錄,便於追蹤和回復。
- 自動化佈署:透過 GitOps 工具,可以實作自動化的佈署和更新。
- 一致性:確保開發、測試和生產環境的一致性。
GitOps 與其他佈署方法的比較
GitOps 與傳統的佈署方法相比,具有明顯的優勢。它不僅簡化了佈署流程,還提高了佈署的可靠性和可追溯性。
GitOps 最佳實踐與工具
Flux:一款流行的 GitOps 工具
Flux 是實作 GitOps 工作流程的流行工具之一。它可以與 Kubernetes 叢集整合,自動同步 Git 倉函式庫中的資源定義到叢集中。
設定 Flux GitOps Agent
- 安裝 Flux:首先需要在 Kubernetes 叢集中安裝 Flux。
- 連線 Git 倉函式庫:組態 Flux 連線到包含 Kubernetes 資源定義的 Git 倉函式庫。
- 同步資源:Flux 將自動同步 Git 倉函式庫中的資源到 Kubernetes 叢集。
GitOps 介紹與實踐
GitOps 是由 Weaveworks 團隊推廣的概念,其基礎源自於在生產環境中執行 Kubernetes 的經驗。GitOps 將軟體開發生命週期的概念應用於維運工作,將 Git 儲存函式庫作為真理來源,叢集狀態與 Git 儲存函式庫中的組態保持同步。例如,當更新 Kubernetes Deployment 清單時,這些組態變更會自動反映在 Git 中的叢集狀態。
為什麼選擇 GitOps?
傳統的佈署流程,如圖 18-2 所示,涉及多個手動步驟,容易出錯且難以追蹤問題源頭。開發人員需要手動更新 Kubernetes 清單,並將變更套用到叢集,這不僅耗時,還可能導致組態漂移。
GitOps 透過以下優勢解決了這些問題:
- 宣告式組態:所有組態以宣告式 YAML 檔案的形式儲存在 Git 中,提供單一的真理來源,方便稽核變更。
- 版本控制:Git 儲存函式庫支援不可變性和版本歷史,允許輕鬆追蹤變更並進行回復。
- 持續協調:叢集狀態持續與 Git 中定義的狀態進行協調,確保叢集的一致性。
- 安全性:使用 Git 管理佈署到 Kubernetes 的應用程式,可以獲得完整的變更稽核日誌,所有變更都記錄在 Git 儲存函式庫中。
GitOps 工作流程
圖 18-1 展示了一個典型的 GitOps 工作流程。開發人員將應用程式碼和 Kubernetes 清單儲存在 Git 儲存函式庫中,Flux 代理程式監控儲存函式庫中的變更。當開發人員提交程式碼變更時,Flux 代理程式會將新的變更同步到 Kubernetes 叢集。
在建立 GitOps 工作流程時,應考慮 OpenGitOps Project 定義的四個核心原則:
- 宣告式組態:所有組態以宣告式 YAML 檔案的形式儲存在 Git 中。
- 版本控制組態:所有組態儲存在 Git 中,所有變更都被追蹤和版本化。
- 不可變組態:所有組態都是不可變的,一旦變更,就不能被修改。
- 持續狀態協調:叢集狀態持續與 Git 中定義的狀態進行協調。
GitOps 儲存函式庫結構
結構 GitOps 儲存函式庫有許多不同的方法,每種方法都有其優缺點。常見的四種策略是:
- 單一 monorepo:將所有 Kubernetes 清單和應用程式碼儲存在單一儲存函式庫中。這種方法簡單,但隨著公司規模的擴大,會變得難以管理。
GitOps 工作流程
@startuml
skinparam backgroundColor #FEFEFE
skinparam componentStyle rectangle
title Kubernetes 准入控制與授權最佳實踐
package "Kubernetes Cluster" {
package "Control Plane" {
component [API Server] as api
component [Controller Manager] as cm
component [Scheduler] as sched
database [etcd] as etcd
}
package "Worker Nodes" {
component [Kubelet] as kubelet
component [Kube-proxy] as proxy
package "Pods" {
component [Container 1] as c1
component [Container 2] as c2
}
}
}
api --> etcd : 儲存狀態
api --> cm : 控制迴圈
api --> sched : 調度決策
api --> kubelet : 指令下達
kubelet --> c1
kubelet --> c2
proxy --> c1 : 網路代理
proxy --> c2
note right of api
核心 API 入口
所有操作經由此處
end note
@enduml此圖示展示了 GitOps 工作流程中各個元件之間的關係。Git 儲存函式庫中的變更被 Flux 代理程式監控,並同步到 Kubernetes 叢集,叢集狀態再與 Git 儲存函式庫中的狀態進行協調。
程式碼範例:Kubernetes Deployment 清單
apiVersion: apps/v1
kind: Deployment
metadata:
name: example-deployment
spec:
replicas: 3
selector:
matchLabels:
app: example
template:
metadata:
labels:
app: example
spec:
containers:
- name: example-container
image: example/image:latest
內容解密:
此 Kubernetes Deployment 清單定義了一個名為 example-deployment 的佈署,具有 3 個副本。該佈署使用 example 標籤選擇器,並定義了一個名為 example-container 的容器,使用 example/image:latest 映象。
apiVersion和kind指定了該資源的 API 版本和型別。metadata部分定義了佈署的元資料,包括名稱。spec部分定義了佈署的規格,包括副本數量、選擇器和範本。template部分定義了 Pod 的範本,包括元資料和規格。spec.containers部分定義了容器列表,包括名稱和映象。
透過使用 GitOps,可以確保叢集狀態與 Git 儲存函式庫中的組態保持一致,從而實作自動化佈署和管理。
GitOps 儲存函式庫結構與秘密管理
在實施 GitOps 工作流程時,儲存函式庫結構和秘密管理是兩個重要的考量因素。一個良好的儲存函式庫結構可以提高團隊的工作效率和程式碼的可維護性,而有效的秘密管理則可以確保敏感資訊的安全。
儲存函式庫結構的選擇
儲存函式庫結構有多種不同的設計方式,每種方式都有其優缺點。以下是一些常見的儲存函式庫結構:
Monorepo
將所有的 Kubernetes 組態檔存放在單一的儲存函式庫中。這種方法適用於小型公司,但隨著公司規模的擴大,這種方法會變得難以管理。
├── app-x
│ ├── common
│ └── deploy
│ └── manifest
├── app-y
│ ├── prod
│ └── staging
├── app-z
└── ops-team
├── flux
├── ingress
└── prometheus
每團隊一個儲存函式庫
每個團隊擁有自己的儲存函式庫,Kubernetes 組態檔存放在同一個儲存函式庫中。這種方法可以實作更好的組織和關注點分離,但隨著應用程式數量的增加,管理會變得更加困難。
├── ops-team
│ ├── elk
│ ├── flux
│ └── prometheus
├── team-x
│ └── app-x
│ └── deploy
│ └── manifest
└── team-y
├── prod
└── staging
每應用程式一個儲存函式庫
每個應用程式擁有自己的儲存函式庫,Kubernetes 組態檔存放在同一個儲存函式庫中。這種方法可以實作更好的組織和關注點分離,並且可以鎖定為團隊的唯讀存取許可權。
── ops-team-repo
│ ├── elk
│ ├── flux
│ └── prometheus
── team-x-repo
│ └── app-x
│ └── deploy
│ └── manifest
每環境一個分支
每個環境在同一個儲存函式庫中擁有自己的分支。這種方法可以透過簡單的 Git 合併來促進環境之間的變更,但可能會導致不必要的變更和合併衝突。
-- main
-- staging
-- QA
-- dev
通常,需要評估組織和團隊的佈局,以決定哪種結構最適合。從每團隊一個儲存函式庫開始是一個不錯的起點,因為它提供了清晰的關注點分離和簡單的儲存函式倉管理。
秘密管理
秘密管理是實施 GitOps 工作流程時的一個常見挑戰。有多種不同的方法可以管理秘密,以下是五種常見的方法:
- 直接將秘密儲存在 Git 中:這種方法最簡單,但不建議使用。因為這樣會將明文秘密儲存在可能公開的儲存函式庫中。
- 將秘密烘焙到容器映像中:這種方法比直接將秘密儲存在 Git 中稍微好一些,但仍然存在安全問題。因為每次輪換秘密時都需要重建映像,而且多個使用者可能能夠提取映像並執行它。
- 使用 Kubernetes Secrets:這種方法在 Kubernetes 中直接可用,提供了一種簡單的方式來開始。但是,Kubernetes Secrets 並不是真正的秘密,因為它們只是 base64 編碼。
- 使用 Sealed Secrets:Sealed Secrets 是 Bitnami 的一個專案,具有兩個元件:叢集控制器和客戶端工具 kubeseal。kubeseal 使用非對稱加密來加密只有控制器才能解密的秘密。這些秘密可以儲存在 Git 中加密,並且只能由叢集中的控制器解密。
- 將秘密儲存在秘密管理工具中:這種方法允許將秘密儲存在安全的位置,然後從叢集中存取它們。這些秘密可以儲存在外部秘密管理解決方案中,例如 HashiCorp Vault、Azure Keyvault、Google KMS 等。
內容解密:
- 直接將秘密儲存在 Git 中:這種方法不安全,因為明文秘密可能會被洩露給多個使用者。
- 將秘密烘焙到容器映像中:這種方法需要重建映像,並且存在安全風險。
- 使用 Kubernetes Secrets:這種方法不安全,因為 Kubernetes Secrets 只是 base64 編碼。
- 使用 Sealed Secrets:這種方法是推薦的,因為它使用非對稱加密來保護秘密。
- 將秘密儲存在秘密管理工具中:這種方法也是推薦的,因為它允許使用現有的解決方案來管理秘密。
設定 Flux
Flux 是一個 Kubernetes 操作器,它會監視 Git 儲存函式庫中的變更並自動將這些變更應用到叢集中。Flux 是實施 GitOps 的成熟工具,我們將在本章的其餘部分中使用它。
首先,我們需要設定 minikube 來佈署 Flux。可以從 minikube 網站安裝 minikube。使用 brew 安裝 minikube:
brew install minikube
接下來,我們需要安裝 Flux 並準備我們的叢集以同步到 Git 儲存函式庫。使用 flux CLI 安裝 Flux:
brew install fluxcd/tap/flux
匯出您的 GitHub token:
export GITHUB_TOKEN=<your-token>
export GITHUB_USER=<your-username>
內容解密:
brew install minikube:安裝 minikube 以佈署 Flux。brew install fluxcd/tap/flux:安裝 flux CLI 以安裝 Flux。export GITHUB_TOKEN=<your-token>和export GITHUB_USER=<your-username>:匯出您的 GitHub token 和使用者名稱以用於 Flux。