[GKE] Workload Identity 試用小記

[GKE] Workload Identity 試用小記

Jul 20, 2019

Workload Identity 應該是 很多人期待很久的功能,最近終於 Public Beta 了! 介紹一下這個新服務,也筆記一下使用狀況。

前情提要

要如何在 Kubernetes 管理 IAM credential 一直是麻煩事!最常看過的就是幾種方法:

1. 使用 instance service account (對應到 AWS 就是類似 instance role)

不用管理 credential,但缺點是同個 node 上的所有 pod 都有一樣的權限,違反了 最小權限原則

2. 把 credential 變成 k8s secret 管理

也就是把 credential 檔案匯入 k8s secret。 優點是每個服務可以使用自己的 credential,但是當服務的數量很多的時候, key rotation 等等 housekeeping 就會變得很麻煩。

3. 使用別人寫的 token generation server

以前看到有人為了 AWS 寫了 kube2iam 以及 kiam 的時候就覺得概念很不錯!他們使用 assume role 的功能不但可以產生暫時用的 credential, 同時又去覆蓋 EC2 metadata server endpoint 來發 token,所以可以無痛相容 AWS SDK。 其實 GCP 的 IAM 也有 類似 assume role 的功能, 查了一下還真的有人 做類似的 project XD

雖然 kube2iam 以及 kiam 看起來有蠻多人用的,在 GKE 上面始終沒有這類比較熱門的解法。 同時要多管理一套框架,也會增加維運成本。而且 (有 workload identity 之前) 大部分 GKE 的官方文件還是建議使用 secret 方法。

GKE Workload Identity

終於,在 Google Next ‘19 中,GCP 發布了這個新功能,並且在最近 public beta 了! (至於 EKS 類似功能進度可以參考 這裡)。 Workload Identity 可以讓 pod 也透過 metadata server API 取得 token,也完全相容於 GCP SDK。 以下請看 VCR (?) 影片裡面有一個簡單的 demo,也有簡單的概念和原理介紹,不過等下也會提到~

基本上,Workload Identity 可以被理解成一個機制, 把 Kubernetes Service Account (以下簡稱 KSA) 對應到 GCP Service Account (以下簡稱 GSA)。 所以在同個 GKE cluster 上面,擁有同樣 KSA 的 pod,都會被對應到同個 GSA,因此就擁有一樣的 IAM 權限。 這個 mapping 是多對一的關係,也就是可以把多個 KSA 對應到同個 GSA 上。

另外,Workload Identity 也有些限制:GKE 版本需要至少 1.12,使用 host network 的 Pod 也無法使用。 其他所有限制可以看一下 [3]。

基本原理

我個人認為先了解他大概怎麼運作的話,會比較好理解 Workload Identity 的使用方法。 當然如果了解理論會讓人打瞌睡的話,直接快轉到 使用/設定方法 也可以啦XD

這邊的內容都出自於影片,不過加上我的理解和簡化(有錯誤的話也歡迎指教(汗) 影片對於原理說得比較詳細,也可以 從 35:42 開始看~

(圖片出自於在 Google Next ‘19 的影片 [3]) Identity namespace components

首先,在一個 GKE cluster 開啟 workload identity 之後,會有幾個新的零件

  • master 多了一個設定: identity namespace 目前只能是 [PROJECT_ID].svc.id.goog (btw 我發現文件 [2] 寫的是 project name 但其實是 project ID…),用途下述。
  • 多了一個 DaemonSet: gke-metadata-server 可以跟 master 中的 OIDC Provider 以及 GCP IAM 互動,負責認證以及取得 token 等等。

簡單來說,metadata server (MDS) 從 KSA identity 取得 GSA 的過程中,大概有以下幾個階段

  1. MDS 跟 OIDC provider 合作,在 GCP IAM 中驗證為 identity namespace 中的 KSA 基本上這一步包含 不只一次的驗證行為: 從 OIDC provider 取得 signed token 以及 IAM 也會向 OIDC provider 驗證 token 等等。 影片裡面有比較詳細的細節。不過最終 KSA 會在 IAM 中認證為一個 service account: [PROJECT_ID].svc.id.goog[[K8S_NAMESPACE]/[KSA_NAME]]。 例如說,k8s namespace some_ns 中的 KSA myapp_sa 認證後,在 IAM 中可以表示為 [PROJECT_ID].svc.id.goog[some_ns/myapp_sa]
  2. MDS 使用上一步取得的 KSA credential,產生目標 GSA 的 credential (token) 產生的 token 就會有目標 GSA 的權限。 至於 MDS 要怎麼知道目標 GSA? 在 KSA 上會使用 annotation 標記,底下會有範例。
  3. MDS 回傳 GSA token 給 Pod

使用/設定方法

1. 準備好目標 GSA,以及設定 GSA 權限

GSA 只需要設定服務需要的最小權限。

2. 準備好 KSA

設定和開好目標 k8s service account (要的話也可以建立新的 namespace),並且在 k8s artifact 中 指定使用新的 KSA (當然如果已經有現成的 KSA 就可以跳過)。

新的 KSA 不用加上額外的 k8s role binding。

3. 讓 KSA 可以存取 GSA

如果基於他的運作的原理的話,可以想像,要讓上面兩階段可以驗證成功, 中間就需要設定 serviceAccount:[PROJECT_ID].svc.id.goog[[K8S_NAMESPACE]/[KSA_NAME]] 對於 GSA 的 權限(像是產生 token 等等)。這邊 GCP 已經準備好一個 role roles/iam.workloadIdentityUser 可以 直接套用~

gcloud iam service-accounts add-iam-policy-binding \
  --role roles/iam.workloadIdentityUser \
  --member "serviceAccount:[PROJECT_ID].svc.id.goog[[K8S_NAMESPACE]/[KSA_NAME]]" \
    [GSA_NAME]@[PROJECT_ID].iam.gserviceaccount.com

4. 在 KSA 上面加上 annotation,指到 GSA

這樣 MDS 才知道目標要取得 credential 的 GSA。

kubectl annotate serviceaccount \
  -namespace [K8S_NAMESPACE] \
  [KSA_NAME] \
  iam.gke.io/gcp-service-account=[GSA_NAME]@[PROJECT_ID].iam.gserviceaccount.com

疑難排除

如果看到 GCP SDK 抱怨 MDS 回 4xx、5xx 之類的話,個人目前經驗是 使用 stackdriver 或是 kubectl -n kube-system logs -l k8s-app=gke-metadata-server 指令, 去看 kube-system namespace 中 gke-metadata-server DaemonSet 的 container log, 通常可以看到一些線索。

之前在玩的時候碰過 IAM 設錯、KSA annotation 設錯等等(像是打錯字之類XD)。另外,project 當中 的 IAM Service Account Credentials API 也需要事先打開。

討論

在官方文件上[2],由於有 identity namespace 這一層設計,讓 workload identity 具有讓權限管理可以 跨 cluster 的能力。在影片中的 live demo 中,同一個 deployment 可以放在不同 region 中 不同的 cluster。只要他們在兩個 cluster 使用有相同的 KSA,都可以共用同一個 GSA。 權限就可以重複使用,方便管理。

但是相反來說,佈署 app 的時候就需要多一些 IAM 物件以及 binding,也可能多一些管理上的 overhead。

目前在公司裡面少數程式開始使用 workload identity,目前反應還算正面XD

小結

Workload Identity 其實解決了自己困擾了蠻久的 GKE Pod IAM 問題,目前用起來也覺得是個好東西。 當然使用量目前也沒有很大,可能也只是還沒碰到很雷的部分而已XD 感覺這類設計可能也會越來越常見成熟, 之後會不會有更厲害的應用也很值得期待!

參考文件

  1. Introducing Workload Identity: Better authentication for your GKE applications https://cloud.google.com/blog/products/containers-kubernetes/introducing-workload-identity-better-authentication-for-your-gke-applications
  2. Workload Identity https://cloud.google.com/kubernetes-engine/docs/how-to/workload-identity
  3. Keyless Entry: Securely Access GCP Services From Kubernetes (Cloud Next ‘19) https://www.youtube.com/watch?v=s4NYEJDFc0M

comments powered by Disqus