排解應用程式層 Secret 加密問題

應用程式層 Secret 加密可為 Google Kubernetes Engine (GKE) 中的機密資料 (例如憑證和金鑰) 增添可設定的保護層。如果這項設定有問題,這層額外的安全防護機制可能無法正常運作。

本文說明如何檢查 GKE API 叢集物件中的可用偵錯欄位,排解應用程式層 Secret 加密問題。這些欄位可協助您診斷常見錯誤的根本原因,例如更新失敗或 Cloud KMS 金鑰發生問題。

這項資訊對於平台管理員和操作員,以及負責保護 GKE 叢集中儲存的機密資訊的資安工程師來說非常重要。如要進一步瞭解 Google Cloud 內容中提及的常見角色和工作範例,請參閱「常見的 GKE 使用者角色和工作」。

更新失敗

更新應用程式層 Secret 加密設定時,GKE 必須重寫 Kubernetes 叢集中的所有 Secret 物件。GKE 這麼做是為了確保所有 Secret 都由新的 Cloud KMS 金鑰加密,或按照您的設定以未加密的形式寫入。

如果發生下列任一情況,這項更新作業可能會失敗:

  • 更新期間,Kubernetes 控制層會暫時無法使用。
  • 使用者定義的 AdmissionWebhook 會導致 GKE 無法更新 Secret 物件。
  • 更新作業完成前,更新或先前的 Cloud KMS 金鑰已停用。

在更新作業成功之前,請勿與更新後的 Cloud KMS 金鑰或先前的 Cloud KMS 金鑰互動。

偵錯欄位

新 GKE 叢集 (1.29 以上版本) 包含額外欄位,可協助您追蹤 Cluster.DatabaseEncryption 的更新,並從故障中復原。

下列步驟僅適用於 DatabaseEncryption.CurrentState 欄位不為空的叢集。如果 CurrentState 欄位空白,表示這個叢集版本尚未啟用這項功能。

這些欄位有以下限制:

  • 為僅限輸出,也就是說,您無法在叢集建立或更新要求期間設定這些欄位。

CurrentState 欄位

您可以檢查 Cluster.DatabaseEncryption 中的 CurrentState 欄位,查看 DatabaseEncryption 更新作業的目前狀態。

CurrentState 的值 說明

CURRENT_STATE_ENCRYPTED

CURRENT_STATE_ALL_OBJECTS_ENCRYPTION_ENABLED

CURRENT_STATE_DECRYPTED

最近一次的更新作業已成功。你無需採取進一步行動。您可以丟棄先前使用過的金鑰。

CURRENT_STATE_ENCRYPTION_PENDING

CURRENT_STATE_ALL_OBJECTS_ENCRYPTION_PENDING

CURRENT_STATE_DECRYPTION_PENDING

更新中。

CURRENT_STATE_ENCRYPTION_ERROR

CURRENT_STATE_ALL_OBJECTS_ENCRYPTION_ERROR

CURRENT_STATE_DECRYPTION_ERROR

最近一次更新發生錯誤。請勿停用或銷毀先前使用的任何 Cloud KMS 金鑰,因為 GKE 可能仍在使用這些金鑰。

詳情請參閱 LastOperationErrors 欄位。

LastOperationErrors 欄位

如果更新作業失敗,gcloud container clusters update 的輸出內容會顯示 GKE 控制層的基礎錯誤。

Cluster.DatabaseEncryption.LastOperationErrors 也會顯示最近兩次更新作業失敗的錯誤訊息。

DecryptionKeys 欄位

用於新加密作業的 Cloud KMS 金鑰會顯示在 DatabaseEncryption.KeyName 中。通常這是叢集使用的唯一金鑰。

不過,如果更新正在進行或失敗,DatabaseEncryption.DecryptionKeys 會包含叢集也會使用的其他金鑰。

從更新失敗中復原

如要從失敗的更新中復原,請按照下列步驟操作:

  1. 檢查錯誤訊息,並解決當中指出的問題。
  2. 執行失敗的指令 (例如 gcloud container clusters update ... --database-encryption-key),重新嘗試更新要求。建議您使用原本發出的相同更新要求重試,或將叢集更新回先前的狀態。如果 GKE 無法讀取一或多個 Secret,可能就無法轉換為其他金鑰或加密狀態。

以下各節列出錯誤的常見原因。

Cloud KMS 金鑰錯誤

如果錯誤訊息包含一或多個 Cloud KMS 金鑰的參照,請檢查 Cloud KMS 金鑰設定,確保相關金鑰版本可供使用。

如果錯誤訊息指出 Cloud KMS 金鑰已遭停用或刪除,請重新啟用金鑰或金鑰版本。

錯誤:無法使用為應用程式層級加密設定的 CloudKMS 金鑰

如果 GKE 的預設服務帳戶無法存取 Cloud KMS 金鑰,就會出現下列錯誤訊息:

Cluster problem detected (Kubernetes Engine Service Agent account unable to use CloudKMS key configured for Application Level encryption).

如要解決這個問題,請重新啟用已停用的金鑰。

無法更新 Secret

如果 Kubernetes API 因准入 Webhook 而拒絕更新要求,可能會發生下列錯誤:

error admission webhook WEBHOOK_NAME denied the request

如要解決這項錯誤,請移除或修改 Webhook,讓 GKE 在更新金鑰時,可以更新所有命名空間中的密鑰。

錯誤:命名空間為代管

如果您嘗試在 Autopilot 叢集中重新加密 GKE 代管命名空間 (例如 kube-system) 中的 Secret,就會發生下列錯誤。錯誤訊息如下:

Error from server (Forbidden): secrets "alertmanager" is
forbidden: User cannot patch resource "secrets" in API group "" in the namespace "gke-gmp-system":
GKE Warden authz [denied by managed-namespaces-limitation]: the namespace "gke-gmp-system"
is managed and the request's verb "patch" is denied'

GKE Autopilot 叢集不允許您修改代管命名空間中的 Kubernetes 資源,包括 Secret。

如要解決這項錯誤,請按照下列步驟操作:

  • 如果您使用 kubectl 指令重新加密 Secret,請使用 --namespace 旗標,將指令範圍限定在您管理的命名空間。
  • 如果您使用 CronJob 重新加密 Secret,請只在您管理的命名空間中部署。

停用加密後,控制層沒有回應

啟用應用程式層 Secret 加密功能後,如果太快停用,可能會中斷初始加密作業,導致叢集的kube-apiserver控制層沒有回應。

這個問題的現象有:

  • 叢集作業 (例如 list node、list pods 和 get apiserver readiness) 會失敗,並顯示錯誤代碼 13 和 Internal Server Error 訊息。
  • Kube 控制器無法運作,且系統不會重新建立從 StatefulSet 或 ReplicaSet 刪除的 Pod。
  • 連線遭拒,因此 Webhook 呼叫失敗。

如要緩解這個問題,請按照下列步驟操作:

  • 使用先前啟用加密功能時所用的 Cloud KMS 金鑰,重新啟用應用程式層 Secret 加密功能。

如要避免這個問題,請確認下列事項:

  • 啟用應用程式層 Secret 加密功能後,請先確認叢集穩定運作數小時,再停用加密功能。

後續步驟