4
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

GKE の Pod で デフォルトの Service Account の Credential を変更する (Workload Identity)

Last updated at Posted at 2019-09-17

これまで

  • GKE で Pod から GCP の API をリクエストする場合には Secrets リソースに Google Service Account の Credential を作ってマウントしていた
  • そのため Credential を発行してダウンロードするという作業が必要となる
  • Google Service Account にはそのアプリケーションで必要となる API の各種権限を割り当てているのでセンシティブな情報と言える
  • それにも関わらず一度は作業者のローカルや作業環境などに保存する必要があるため管理が甘い (使用後即座に消さないとか) と作業者本人も含めてアプリケーション以外で使用されてしまう
  • Credential なんてダウンロードしないで Pod に Service Account を指定したい...

  • Workload Identity 登場
  • fin.

使ってみた (CronJob)

前提

  • 作業者に各種権限が付与されていること
    • 以下の権限が含まれていればいけそう (要らないのも混ざってるかも)
resourcemanager.projects.get
iam.serviceAccounts.get
iam.serviceAccounts.list
iam.serviceAccounts.create
iam.serviceAccounts.actAs
iam.serviceAccounts.setIamPolicy
iam.serviceAccounts.getIamPolicy
compute.projects.get
compute.regions.get
compute.regions.list
compute.zones.get
compute.zones.list
compute.networks.get
compute.networks.list
compute.networks.create
compute.networks.updatePolicy
compute.subnetworks.get
compute.subnetworks.list
compute.subnetworks.create
container.operations.get
container.clusters.get
container.clusters.create
  • 各種リソースの名前は以下で統一
Name Description
${my_pj} クラスタを作成する GCP のプロジェクト
${my_gsa} CronJob で使用したい Google Service Account 名
${k8s_ns} Kubernetes の Namespace 名
${k8s_ksa} Kubernetes の Namespace 内の Service Account 名
${my_clstr} クラスタ名
${my_nw} GCP の VPC ネットワーク名
${my_subnw} クラスタ用のサブネットワーク名
${my_region} サブネットワークのリージョン
${my_zone} クラスタのゾーン (リージョンで作るとノード数多いので)

作業

$ docker run --rm -it --name gcp-cli -w /opt google/cloud-sdk:latest

% gcloud auth login
% gcloud config set project ${my_pj}

% : Step01. ${my_gsa} の作成
% gcloud beta iam service-accounts create\
    ${my_gsa}\
    --project ${my_pj}\
    --display-name "My Google Service Account"\
    --description "Qiita Example"

% : Step02. ${my_gsa} への権限設定
% gcloud projects add-iam-policy-binding\
    ${my_pj}\
    --member ${my_gsa}@${my_pj}.iam.gserviceaccount.com\
    --role resourcemanager.projects.get

% : Step03. クラスタ用のネットワーク作成
% gcloud compute networks create\
    ${my_nw}\
    --project ${my_pj}\
    --bgp-routing-mode regional\
    --subnet-mode custom
% gcloud compute networks subnets create\
    ${my_subnw}\
    --project ${my_pj}\
    --network ${my_nw}\
    --region ${my_region}\
    --range xxx.xxx.xxx.xxx/xx\
    --enable-private-ip-google-access

% : Step04. クラスタ作成
% gcloud beta container clusters create\
    ${my_clstr}\
    --project ${my_pj}\
    --zone ${my_zone}\
    --identity-namespace ${my_pj}.svc.id.goog\
    --network ${my_nw}\
    --subnetwork ${my_subnw}\
    --machine-type n1-standard-1\
    --preemptible\
    --disk-size 100\
    --disk-type pd-standard\
    --image-type cos\
    --enable-ip-alias\
    --enable-private-nodes\
    --master-ipv4-cidr yyy.yyy.yyy.yyy/yy\
    --enable-master-authorized-networks\
    --master-authorized-networks zzz.zzz.zzz.zzz/zz\
    --num-nodes 1\
    --no-enable-legacy-authorization\
    --no-enable-basic-auth\
    --no-issue-client-certificate\
    --metadata 'disable-legacy-endpoints=true'

% : Step05. Workload Identity からの ${my_gsa} へのアクセスを許可
% gcloud iam service-accounts add-iam-policy-binding\
    ${my_gsa}@${my_pj}.iam.gserviceaccount.com\
    --role "roles/iam.workloadIdentityUser"\
    --member "serviceAccount:${my_pj}.svc.id.goog[${k8s_ns}/${k8s_ksa}]"

% : Step06. クラスタに Namespace と Service Account を作成
% cat <<EOS | kubectl apply -f -
apiVersion: v1
kind: Namespace
metadata:
  name: ${k8s_ns}
---
apiVersion: v1
kind: ServiceAccount
metadata:
  namespace: ${k8s_ns}
  name: ${k8s_ksa}
  annotations:
    iam.gke.io/gcp-service-account: ${my_gsa}@${my_pj}.iam.gserviceaccount.com
EOS

% : Step07. Pod 作ってテスト
% kubectl run\
    -it\
    --rm\
    --generator=run-pod/v1\
    --image google/cloud-sdk\
    --namespace ${k8s_ns}\
    --serviceaccount ${k8s_ksa}\
    workload-identity-test\
    -- gcloud auth list
% kubectl run\
    -it\
    --rm\
    --generator=run-pod/v1\
    --image google/cloud-sdk\
    --namespace ${k8s_ns}\
    --serviceaccount ${k8s_ksa}\
    workload-identity-test\
    -- gcloud projects describe ${my_pj}

% : Step08. CronJob を作成
% cat <<EOS | kubectl apply -f -
apiVersion: batch/v1beta1
kind: CronJob
metadata:
  namespace: ${k8s_ns}
  name: workload-identity-test
spec:
  schedule: "*/1 * * * *"
  successfulJobsHistoryLimit: 1
  failedJobsHistoryLimit: 1
  jobTemplate:
    spec:
      template:
        spec:
          restartPolicy: Never
          serviceAccountName: ${k8s_ksa}
          containers:
            - name: batch
              image: google/cloud-sdk
              imagePullPolicy: Always
              command: ["gcloud", "projects", "describe", "${my_pj}"]
EOS
% kubectl get cronjob --namespace ${k8s_ns}
% kubectl pod cronjob --namespace ${k8s_ns}
% kubectl get pod --namespace ${k8s_ns} --field-selector status.phase==Succeeded -o name\
  | kubectl logs $(cat) --namespace ${k8s_ns}

調査

Pod 内で gcloud auth list がエラー

こんなの

ERROR: gcloud crashed (MetadataServerException): HTTP Error 403: Forbidden
  • Stack Driver で以下のようなフィルターでログ調査
resource.type="container"
resource.labels.cluster_name="${my_clstr}"
resource.labels.namespace_id="kube-system"
resource.labels.project_id="${my_pj}"
resource.labels.zone:"${my_zone}"
resource.labels.container_name="gke-metadata-server"
resource.labels.pod_id:"gke-metadata-server-"
  • IAM とかの API を enable にしてなかったり権限が足りてなかったり

参考

4
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?