iT邦幫忙

2026 iThome 鐵人賽

DAY 28
0
IT Operation

寫完微服務然後呢?走向平台工程的黃金路徑系列 第 28 篇

Day 28 - Gatekeeper 如何檢查 Kubernetes 資源設定

  • 分享至 

  • xImage
  •  

前一篇談的是「誰可以操作 Kubernetes API」,透過角色型存取控制(Role-Based Access Control,RBAC)分配權限;今天要看的則是「提交的資源內容是否符合規範」,也就是政策(Policy)的檢查。即使擁有建立 Deployment 的權限,也不代表任何 Deployment 設定都會被接受。

Todo API 只需要處理 HTTP 請求,沒有操作主機裝置的需求。如果部署設定卻讓容器取得這些權限,我們會希望在部署前就拒絕這份設定。今天就用這個情境,說明 Kubernetes 如何檢查資源內容,以及 Gatekeeper 如何執行團隊的部署規則。

為什麼要限制容器的權限?

一份 Deployment 能通過 Kubernetes 的欄位驗證,代表它符合這種資源的格式,卻不代表它符合團隊的部署要求。Kubernetes 提供許多進階選項,但其中部分是為系統元件或特殊工作負載設計,一般服務未必需要。

我們可以先訂一條具體規則:「Todo API 的容器不能啟用 privileged 模式。」

容器通常受到 Linux 的權限與隔離機制限制。將 securityContext.privileged 設為 true,會放寬多項安全限制,讓容器能存取主機裝置等資源。這稱為 privileged mode,權限比單純在容器內以 root 執行程式更大。

對 Todo API 而言,這些額外權限沒有用途,卻可能讓入侵容器的攻擊者影響主機,因此我們禁止它啟用這個模式。需要操作主機裝置的系統元件,則要另外評估,不能直接套用相同要求。

這類部署要求稱為政策(Policy)。如果只寫在文件裡,每次 review 都得靠人記得檢查。我們也可以把要求寫成可執行的規則,交給系統檢查,並透過版本管理、審查與測試維護規則。這種做法稱為政策即程式碼(Policy as Code)。

Kubernetes 在什麼時候檢查?

當 Operator 向 API Server 請求建立 Deployment,API Server 會先驗證 Operator 的身分,再檢查它是否有建立資源的權限。通過授權後,還會經過准入控制(Admission Control),在資源寫入前檢查請求內容。

Admission 有修改與驗證兩類功能。修改可以替資源加入或調整欄位;驗證則判斷設定是否符合要求。這次要做的是驗證:如果容器啟用了 privileged 模式,就拒絕請求,讓提交者修正設定。

除了 Kubernetes 內建的檢查,API Server 也能透過 webhook 請外部服務協助驗證。這裡的 webhook 是 API Server 在處理請求時,呼叫已登錄的驗證服務,將資源內容送過去,再取得允許或拒絕的回應。這發生在資源寫入前,而不是部署完成後的通知機制。

要透過 webhook 檢查剛才的部署要求,驗證服務就必須讀取容器設定,判斷是否啟用了 privileged。OPA 可以負責這部分的判斷。

OPA 負責根據資料判斷規則

Open Policy Agent(OPA)是開源的政策引擎。你提供要檢查的資料與規則,它根據規則計算結果。OPA 不只用於 Kubernetes,也能用來判斷 API 存取、CI 設定等問題。

以 Todo API 為例,我們把容器設定交給 OPA,讓它檢查是否啟用了 privileged,並回傳違規容器的名稱與原因。OPA 只負責判斷結果;要檢查哪些資源、是否拒絕請求,則由整合它的系統決定。

OPA 使用 Rego 語言描述政策。以這條規則來說,Rego 程式需要逐一檢查容器的 privileged 欄位,找出值為 true 的容器,再回傳違規訊息。它不負責建立或更新 Deployment。

不過,單有 OPA 還沒有接上 Kubernetes 的 admission。我們仍需要一個元件接收 webhook 請求、管理政策,並將評估結果回傳給 API Server。

Gatekeeper 把政策檢查接到 Kubernetes

Gatekeeper 是將 OPA 整合進 Kubernetes Admission 流程的元件。它部署在叢集裡,提供 validating webhook,讓 API Server 可以在 admission 階段請它檢查資源。

當驗證請求送到 Gatekeeper,它會找出適用於這筆資源的規則,再評估是否違規。如果規則要求拒絕違規請求,Gatekeeper 就把拒絕結果與原因回傳給 API Server,這次資源建立或更新便不會成功。

因此,API Server 會請 Gatekeeper 驗證資源內容,Gatekeeper 再使用 OPA 評估政策。無論資源由 Operator、Argo CD 或使用者提交,只要符合檢查範圍,都要接受同樣的驗證。

下面以 Operator 提交 Todo API 的 Deployment 為例,畫出這個檢查流程。圖中假設規則使用 deny 模式,呈現的是運作方式,不是叢集實測結果。ConstraintTemplate 與 Constraint 的作用會在下一節說明。

Operator 提交 Deployment,API Server 呼叫 Gatekeeper,由 OPA 執行 Rego,依 Constraint 的 deny 模式回傳允許或拒絕

怎麼告訴 Gatekeeper 要檢查什麼?

Gatekeeper 用 Kubernetes 資源管理驗證政策,主要分成 ConstraintTemplate 與 Constraint。前者定義怎麼檢查,後者指定要檢查哪些資源,以及發現違規時怎麼處理。

Kubernetes 用資源種類(Kind)區分不同的資源,例如 Deployment、Pod 與 Service。Gatekeeper 的規則本身也是資源,因此也需要定義自己的資源種類。

ConstraintTemplate 定義檢查邏輯,也定義這種規則的資源種類與可接受的參數。例如禁止 privileged 的 Template,就包含前面提到的 Rego 邏輯:檢查每個容器,並回報啟用這個模式的容器名稱。Gatekeeper 會依 Template 建立對應的自訂資源定義(Custom Resource Definition,CRD),讓 Kubernetes 認識這種規則。

有了這份 CRD,平台團隊就能建立實際的規則資源,這類資源統稱為 Constraint。Constraint 的 spec.match 指定要檢查哪些資源種類、哪些 Namespace,spec.enforcementAction 決定發現違規時怎麼處理。如果檢查邏輯需要參數,再透過 spec.parameters 提供。

假設我們要拒絕 todo 裡啟用 privileged 的 Deployment,就先定義檢查容器設定的 Template。接著建立 Constraint,將範圍設為 todo Namespace 裡的 Deployment,並將 spec.enforcementAction 設為 deny,表示拒絕違規請求。

只建立 Template,還不會啟用這條規則;還需要 Constraint 指定檢查範圍。如果 Constraint 選的是其他 Namespace,就不會檢查 todo。政策未生效時,除了檢查規則內容,也要確認 spec.match 是否涵蓋目標資源。

再走一次 Todo API 的建立請求

假設上述規則已經設定好,webhook 也正常運作。Operator 提交 Todo API 的 Deployment 時,處理順序會是:

  1. API Server 驗證 Operator 的身分,RBAC 確認它有權在 todo 建立 Deployment。
  2. 請求進入 admission,API Server 將符合 webhook 設定範圍的驗證請求送到 Gatekeeper。
  3. Gatekeeper 找出符合這筆 Deployment 的 Constraint,依 Template 的邏輯檢查 Pod template 裡各個容器的設定。
  4. 如果找到 privileged=true 的容器,請求就會被這條 deny 規則拒絕,並回傳容器名稱與原因。若沒有違規,則不因這條規則拒絕,仍須通過其他適用的檢查。

這裡的拒絕發生在資源寫入前。建立被拒絕,就不會新增這筆 Deployment;更新被拒絕,則不會將這次變更寫進既有 Deployment。既有資源不會因一次更新被拒絕就遭到刪除。

拒絕訊息應該說明哪個設定有問題。例如「todo-api 容器不允許啟用 privileged」,就比「不符合政策」更清楚。開發者看到這個訊息,才知道需要移除或停用哪個設定。

檢查 Deployment 和 Pod 有什麼差別?

Deployment 裡保存了建立 Pod 所需的設定,位置在 spec.template.spec。我們可以在提交 Deployment 時就檢查這些內容,提早拒絕不符合要求的設定。

如果規則只檢查 Pod,Deployment 可能先建立成功,之後 Kubernetes 根據它的設定建立 Pod 時,才被 Gatekeeper 拒絕。這時會出現「有 Deployment,卻無法建立 Pod」的情況,需要查看負責建立 Pod 的 ReplicaSet 事件,才能找到拒絕原因。

兩種檢查可以一起使用:檢查 Deployment,讓提交者提早知道問題;檢查 Pod,也能擋下不經 Deployment、直接建立的 Pod。規則需要分別讀取兩種資源的容器設定,並檢查每個容器。

對目前的 Todo 平台來說,開發者提交的 Microservice 自訂資源(Custom Resource,CR)只有 image 與 port,容器設定由 Operator 產生。因此,這條規則要檢查 Operator 建立的 Deployment 或後續的 Pod,不能只檢查 Microservice。

禁止 privileged 只處理這個設定,不代表其他設定都安全,也不會限制 BFF 能否呼叫 Todo API。

下一篇會沿用這個檢查流程,加入 limits 與 image 的要求,再看既有資源如何盤點,以及什麼時候適合開始拒絕違規請求。

參考資料


上一篇
Day 27 - Kubernetes RBAC 與 Namespace 能隔離什麼
系列文
寫完微服務然後呢?走向平台工程的黃金路徑 共 28 篇
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言