ถ้าเราต้องการให้ permission gcloud กับ container ที่รันใน GKE ปัจจุบันเราสามารถทำได้ง่าย ๆ 2 วิธี คือ
ให้ permission กับ node ใน GKE ที่รัน container, container ทุกตัวที่รันใน node นั้นจะมี permission ของ node ที่มันรันอยู่
ข้อเสียคือถ้าเรารัน container ที่เราไม่รู้จัก container นั้นก็จะมี permission เดียวกับ node ที่รัน
สร้าง service account ใน gcloud แล้วเอา private key มาเก็บใน secret ใน kubernetes แล้วก็ mount เข้าไปเป็น volumn ใน container
ข้อเสียคือ private key มีวันหมดอายุ ถ้าเราลืม rotate key ก่อนหมดอายุ ระบบอาจจะ down ได้เลย อีกอย่างคือ container ที่มี permission ในการอ่าน secret ใน kubernetes ก็สามารถอ่าน private key ของเราออกมาได้ เช่น ingress controller ที่ต้องอ่าน tls cert/key จากใน secret จะขอ permission ในการอ่าน secret ทั้งหมดใน cluster เช่น nginx-ingress-controller
Workload Identity คือ feature ใหม่ที่จะมาช่วย binding service account ใน kubernetes กับ service account ใน gcloud ทำให้เราไม่ต้องใช้ private key
เมื่อเราเปิด Workload Identity ใน GKE แล้ว จะมี Daemon Set ถูกรันขึ้นมาเพิ่ม 2 ตัว คือ
เมื่อ container ของเราจะเรียก api ที่ gcloud netd จะ route traffic ไปที่ gke-metadata-server เพื่อให้ metadata-service inject access token (อายุสั้น ๆ) ที่ header ของ request ของเราก่อนส่งไปหา api ที่ gcloud
สร้าง namespace ใน kubernetes ถ้ายังไม่มี
$ kubectl create ns my-namespace
สร้าง service account ใน kubernetes (KSA) ถ้ายังไม่มี หรือจะใช้ default ของแต่ละ namespace ก็ได้
$ kubectl create sa my-ksa
สร้าง service account ใน gcloud (GSA)
$ gcloud iam service-accounts create my-gsa
ให้ permission กับ gke-metadata-server ให้สามารถสร้าง access token ของ service account ของเราได้
$ gcloud iam service-accounts add-iam-policy-binding \
--role roles/iam.workloadIdentityUser \
--member "serviceAccount:[PROJECT_ID].svc.id.goog[my-namespace/my-ksa]" \
my-gsa@[PROJECT_ID].iam.gserviceaccount.com
บอก gke-metadata-server ว่า KSA ของเราให้ใช้ GSA อันไหน
$ kubectl annotate sa \
--namespace my-namespace \
my-ksa \
iam.gke.io/gcp-service-account=my-gsa@[PROJECT_ID].iam.gserviceaccount.com
เวลาสร้าง pod ก็แค่บอก kubernetes ว่าจะใช้ service account (KSA) อันไหน
apiVersion: apps/v1
kind: Deployment
...
spec:
...
template:
...
spec:
...
serviceAccountName: my-ksa
แค่นี้ container ของเรา ก็จะมี permission เดียวกับ GSA ที่เราสร้างแล้ว โดยที่ไม่ต้องคอยกังวลว่า private key จะหมดอายุ หรือใครจะแอบอ่าน private key ของเรา