GKE cluster作成時にも指定できるアクセススコープはレガシー扱いになっている https://cloud.google.com/kubernetes-engine/docs/how-to/access-scopes#what_are_access_scopes
とはいえチュートリアルには--scopeを利用したものも見受けられる
アクセススコープは手軽だが細かい設定ができない。ServiceAccountを使うと必要最低限の権限のみ付与する事ができるので、セキュリティの品質が保たれるためGoogleとしてはServiceAccountを推している。という認識でいいのかな.
GKEの権限関係で迷わないよう、サービス アカウントを使用した Google Cloud への認証を題材にやり方を整理する
- アクセススコープを用いた認証
- ServiceAccountを用いた認証
- (おまけ) ServiceAccount認証にWorkload Identityを用いる
事前準備
題材に則りpubsub topicを作成し、publishとsubscribeができるか検証する
pubsub topicの作成
gcloud pubsub topics create echo
gcloud pubsub subscriptions create echo-read --topic=echo
ソースコード取得
git clone https://github.com/GoogleCloudPlatform/kubernetes-engine-samples
cd kubernetes-engine-samples
cloud-pubsub/deployment以下のyamlファイルを実際に適応していく
1. アクセススコープを用いた認証
クラスタ作成
gcloud container clusters create pubsub-test --scopes=gke-default,https://www.googleapis.com/auth/pubsub --zone
asia-northeast1-a
scope オプションについて
--scopesオプションをつけることでクラスタに権限を付与できる
gke-defaultは下記のscopeをまとめたエイリアスになる
Alias URI
gke-default https://www.googleapis.com/auth/devstorage.read_only
https://www.googleapis.com/auth/logging.write
https://www.googleapis.com/auth/monitoring
https://www.googleapis.com/auth/service.management.readonly
https://www.googleapis.com/auth/servicecontrol
https://www.googleapis.com/auth/trace.append
gcloud container clusters create --helpをすると他のエイリアスもあるのでみてみると良い
(webのmanにも載っている)
また複数指定したいのでカンマ区切りで指定している scopeの一覧から選んで付与していく.
(権限を追加する)
後から権限を追加したくなるケースはどうするか? scopeを変えたいならば、node-poolsを作り変える事しかできない
# 新規作成
gcloud container node-pools create new-pools --cluster pubsub-test --scopes=gke-default,https://www.googleapis.com/auth/pubsub,https://www.googleapis.com/auth/something
# 古いnodeを削除
gcloud container node-pools delete old-pools --cluster pubsub-test
デプロイ
kubectl apply -f cloud-pubsub/deployment/pubsub.yaml
kubectl get po
NAME READY STATUS RESTARTS AGE
pubsub-8cb8475c8-tvxwv 1/1 Running 0 95s
確認
Publish
gcloud pubsub topics publish echo --message="Hello, world\!"
messageIds:
- '3909513331830980'
Subscribe
kubectl logs -f pubsub-8cb8475c8-tvxwv
Pulling messages from Pub/Sub subscription...
[2022-03-21 06:37:27.265195] Received message: ID=3909513331830980 Data=b'Hello, world!'
[2022-03-21 06:37:27.265294] Processing: 3909513331830980
[2022-03-21 06:37:30.267957] Processed: 3909513331830980
2. ServiceAccountを用いた認証
Googleが推奨しているのはこちら サービス アカウントを使用した Google Cloud への認証と同じ事をしているだけなので説明は省く
クラスタ作成
gcloud container clusters create pubsub-test
Service Accountの作成
gcloud iam service-accounts create pubsub \
--description="PUBSUB" \
--display-name="pubsub"
gcloud projects add-iam-policy-binding $PROJECT_ID \
--member="serviceAccount:pubsub@$PROJECT_ID.iam.gserviceaccount.com" \
--role="roles/pubsub.admin"
鍵の取得
ServiceAccountのページにアクセスする 作成したサービスアカウントの右にある3点リーダーから「鍵を管理」を選択 「鍵を追加」>「新しい鍵を作成」>「JSON」>「作成」を選択 json形式の鍵がDLされる
クラスタに登録
kubectl create secret generic dns-key --from-file=key.json=secret.json
登録後、secret.jsonはローカルから削除する
デプロイ
kubectl apply -f cloud-pubsub/deployment/pubsub-with-secret.yaml # scopeの例とは違うファイル
kubectl get po
NAME READY STATUS RESTARTS AGE
pubsub-57ff86f846-6k455 1/1 Running 0 5s
疎通確認
Publish
$ gcloud pubsub topics publish echo --message="Hello, world\!"
messageIds:
- '3909437272511327'
Subscribe
$ kubectl logs -f pubsub-57ff86f846-6k455
Pulling messages from Pub/Sub subscription...
[2022-03-21 06:21:01.512711] Received message: ID=3909437272511327 Data=b'Hello, world!'
[2022-03-21 06:21:01.512785] Processing: 3909437272511327
[2022-03-21 06:21:04.515914] Processed: 3909437272511327
3. (おまけ) ServiceAccount認証にWorkload Identityを用いる
ServiceAccount認証では鍵の管理で難易度が上がる予想ができる、そこでWorkload Identityを試してみる
Workload Identityとはなにか
Google Cloudによると下記のようなことができるらしい
GKE クラスタ内のワークロードが Identity and Access Management(IAM)サービス アカウントに代わって Google Cloud サービスにアクセスできます
こちらの解説にある下記の説明がストレートでわかりやすかった
Kubernetes の Service account と GCP の Service account を紐づけられるようにする機能
とはいえ、試してしてわかったこともあるので実際に流れを記載しておく この章ではGCPとk8sのServiceAccountを見分けられるようにGSA, KSAと用語統一する
クラスター作成
$ gcloud container clusters create pubsub-wi \
--zone=asia-northeast1-a \
--workload-pool=$PROJECT_ID.svc.id.goog
クラスター認証情報を取得
$ gcloud container clusters get-credentials pubsub-wi --zone asia-northeast1-a
Fetching cluster endpoint and auth data.
kubeconfig entry generated for pubsub-wi.
KSAの作成
$ kubectl create namespace workloadidentity
apiVersion: v1
kind: ServiceAccount
metadata:
name: k8s-pubsub-sa
namespace: workloadidentity
pubsubの権限を持つGSAを作成
gcloud iam service-accounts create gcp-pubsub-sa --project=$PROJECT_ID
gcloud projects add-iam-policy-binding $PROJECT_ID \
--member="serviceAccount:gcp-pubsub-sa@$PROJECT_ID.iam.gserviceaccount.com" \
--role="roles/pubsub.admin"
KSA(k8s-pubsub-sa)とGSA(gcp-pubsub-sa)を連携する.
その結果、KSAがGSAの権限を借用できるようになる
これが当初述べていた「Kubernetes の Service account と GCP の Service account を紐づけられるようにする機能」のコア作業になる(と思う)
gcloud iam service-accounts add-iam-policy-binding gcp-pubsub-sa@$PROJECT_ID.iam.gserviceaccount.com \
--role roles/iam.workloadIdentityUser \
--member "serviceAccount:$PROJECT_ID.svc.id.goog[workloadidentity/k8s-pubsub-sa]"
デプロイ
KSAの設定にGSAの情報を付与
上のyamlからannotation部を追加した
apiVersion: v1
kind: ServiceAccount
metadata:
annotations:
iam.gke.io/gcp-service-account: gcp-pubsub-sa@$PROJECT_ID.iam.gserviceaccount.com
name: k8s-pubsub-sa
namespace: workloadidentity
Podにnodeを指定
WorkloadIdentityが有効なnodeでKSAを利用するようにPodの設定を更新する
apiVersion: apps/v1
kind: Deployment
metadata:
name: pubsub
namespace: workloadidentity
spec:
selector:
matchLabels:
app: pubsub
template:
metadata:
labels:
app: pubsub
spec:
containers:
- name: subscriber
image: us-docker.pkg.dev/google-samples/containers/gke/pubsub-sample:v1
serviceAccountName: k8s-pubsub-sa
nodeSelector:
iam.gke.io/gke-metadata-server-enabled: "true"
疎通確認
Publish
$ gcloud pubsub topics publish echo --message="Hello, world\!"
messageIds:
- '3910950575108654'
Subscribe
$ kubectl logs -f pubsub-6f88675785-bfp2x -n workloadidentity
Pulling messages from Pub/Sub subscription...
[2022-03-21 10:47:58.059249] Received message: ID=3910950575108654 Data=b'Hello, world!'
[2022-03-21 10:47:58.059274] Processing: 3910950575108654
[2022-03-21 10:48:01.060928] Processed: 3910950575108654
まとめ
GKEにおける権限付与のやり方をscopeとServiceAccount(gcloudコマンド利用、workload identity)の3つを整理した 検証用にクラスタを一時的に建てるならばscopeでもいいかもしれないが、セキュリティや後からの追加のしやすさから運用し続けるクラスタにはServiceAccountを用いた方が楽だろう. gcloudの場合は鍵の管理でセキュリティ面や運用面で難易度が上がる恐れがあるが、workload identityを利用する事でその不安点も回避できる。
こちらの記事ではterraformでのworkload identityのやり方も記載されているので、別PJへの展開もスムーズに行えそうだ.
また、今回は検証していないがConfig Connectorを利用するとServiceAccountの発行もYAMLで記載できそうなので、terraform以外の選択肢になるかもしれない