本ハンズオンではGitHub Codespacesにコンテナ(devcontainer)として検証環境を作成し、その環境を利用します。
ハンズオンで使用するコマンド等はあらかじめdevcontainerに含まれているため、以下の手順を実施することで必要な検証環境を用意することができます。
(今回devcontainerの定義はこちらのものを使用しています。)
左上のボタンをクリックし、「Codespaces」をクリックします。
「New codespace」をクリックします。
Repositoryにて
k8s-meetup-novice/gke-handson-20250508
を選択し、「Create codespace」をクリックします。
以下のように開発環境(VSCode)が表示されます。
codespaceからGoogle Cloudにアクセスできるようにするため、gcloud CLIの初期化を行います。
以下のコマンドを実行し、表示されたURLにWebブラウザからアクセスします。
gcloud init --no-launch-browserWelcome! This command will take you through the configuration of gcloud.
Your current configuration has been set to: [default]
You can skip diagnostics next time by using the following flag:
gcloud init --skip-diagnostics
Network diagnostic detects and fixes local network connection issues.
Checking network connection...done.
Reachability Check passed.
Network diagnostic passed (1/1 checks passed).
You must sign in to continue. Would you like to sign in (Y/n)? Y # <--- Yを入力してEnter
Go to the following link in your browser, and complete the sign-in prompts:
https://accounts.google.com/o/oauth2/auth?response_type=xxxxxxxxxx # <--- ここに表示されたURLをコピーしてWebブラウザからアクセス
Once finished, enter the verification code provided in your browser: ログイン画面が教示されるため、Gooleアカウントを入力し「次へ」を押下します。

認証コードが表示されるため、これをコピーしてターミナルに戻り、ペーストします。

また、今回のハンズオン環境はQwiklabを使用しておりあらかじめプロジェクトが作成されているため、以下のように作成済のプロジェクトを選択します。 (Qwiklab以外の環境を使用してハンズオンを実施する場合はこちらを参考にハンズオン用のプロジェクトを作成してください。)
Go to the following link in your browser, and complete the sign-in prompts:
https://accounts.google.com/o/oauth2/auth?response_type=xxxxxxxxxx
Once finished, enter the verification code provided in your browser: xxxxxxx # <--- ここに認証コードをペーストしてEnter
You are signed in as: [<Googleアカウント名>].
Pick cloud project to use:
[1] qwiklabs-gcp-xxxxxxx
[2] qwiklabs-resources
[3] Enter a project ID
[4] Create a new project
Please enter numeric choice or text value (must exactly match list item): 1 # <--- 1を入力してEnter
Your current project has been set to: [qwiklabs-gcp-xxxxxxx].
Your project default Compute Engine zone has been set to [asia-northeast1-a].
You can change it by running [gcloud config set compute/zone NAME].
...以下のコマンドを実行し、gcloudコマンドに設定されているプロジェクトを確認します。
gcloud config list...
project = qwiklabs-gcp-xxxxxxx
...以下のコマンドを実行し、ハンズオンに使用するプロジェクトのPROJECT_IDを確認します。
※PROJECT_IDはプロジェクトを識別するためのグローバルに一意なIDです。(参考)
gcloud projects listPROJECT_ID NAME PROJECT_NUMBER
<PROJECT_ID> qwiklabs-gcp-xxxxxxx <PROJECT_NUMBER>
...以下のコマンドを用いて、環境変数に各種値を設定します。
export GCLOUD_PROJECT_ID=<PROJECT_ID>
export GCLOUD_PROJECT_NUMBER=`gcloud projects describe $GCLOUD_PROJECT_ID --format='value(projectNumber)'`
export GCLOUD_REGION=asia-northeast1
export CLUSTER_NAME=gke-wakaran-handson-cluster
export REPOSITORY_ID=gke-wakaran-handson-repository
export TF_VAR_project_id="${GCLOUD_PROJECT_ID}"
export TF_VAR_region="${GCLOUD_REGION}"
export TF_VAR_cluster_name="${CLUSTER_NAME}"
export TF_VAR_repository_id="${REPOSITORY_ID}"以下のコマンドを実行し、正しく環境変数が設定されていることを確認します。
cat << EOF
GCLOUD_PROJECT_ID: ${GCLOUD_PROJECT_ID}
GCLOUD_PROJECT_NUMBER ${GCLOUD_PROJECT_NUMBER}
GCLOUD_REGION: ${GCLOUD_REGION}
CLUSTER_NAME: ${CLUSTER_NAME}
REPOSITORY_ID: ${REPOSITORY_ID}
TF_VAR_project_id: ${TF_VAR_project_id}
TF_VAR_region: ${TF_VAR_region}
TF_VAR_cluster_name: ${TF_VAR_cluster_name}
TF_VAR_repository_id: ${TF_VAR_repository_id}
EOFGCLOUD_PROJECT_ID: <PROJECT_ID>
GCLOUD_PROJECT_NUMBER <PROJECT_NUMBER>
GCLOUD_REGION: asia-northeast1
CLUSTER_NAME: gke-wakaran-handson-cluster
REPOSITORY_ID: gke-wakaran-handson-repository
TF_VAR_project_id: <PROJECT_ID>
TF_VAR_region: asia-northeast1
TF_VAR_cluster_name: gke-wakaran-handson-cluster
TF_VAR_repository_id: gke-wakaran-handson-repository一般的にGoogle Cloudの各種サービスを利用する際は、あらかじめ請求先アカウントをプロジェクトにリンクした上で、利用するサービスのAPIを有効化する必要があります。
今回ハンズオンに使用するQwiklabでは、上記について既に実施済のため、改めて実施する必要はありません。
Qwiklab以外の環境で実施する場合の手順はこちらを参照してください。
現在有効化されているサービスAPIの一覧はgcloud services listコマンドで確認できます。
以下のコマンドを実行し、今回使用する各サービスAPIが有効化されていることを確認します。
gcloud services list | grep -Ew \
'compute.googleapis.com|'\
'container.googleapis.com|'\
'iamcredentials.googleapis.com|'\
'artifactregistry.googleapis.com|'\
'storage.googleapis.com'artifactregistry.googleapis.com Artifact Registry API
compute.googleapis.com Compute Engine API
container.googleapis.com Kubernetes Engine API
iamcredentials.googleapis.com IAM Service Account Credentials API
storage.googleapis.com Cloud Storage APITerraformを使用してGKEクラスタ、Artifact Registry Repository, Cloud Storageをはじめとした各種Google Cloudリソースを作成します。
以下のコマンドを実行し、TerraformからGoogle Cloudにアクセスするための認証情報を作成します。
コマンドを実行したら、「0-2. gcloud CLIの初期化」と同じ流れで認証を行います。
gcloud auth application-default login以下のコマンドを実行し、Terraformを用いてGoogle Cloudリソースを作成します。(参考: Terraform CLI)
TerraformのIaCコードを含むtffilesディレクトリに移動します。
cd tffilesTerraformワークスペースの初期化を行います。
terraform initTerraformの実行計画を確認します。
terraform planTerraformでリソースを作成します。
terraform apply以下のように確認が求められるのでyesと入力します。
Do you want to perform these actions?
Terraform will perform the actions described above.
Only 'yes' will be accepted to approve.
Enter a value: yes # <--- yesと入力してEnterコマンドの実行が正常に完了すると、以下のような結果が表示されます。(コマンドの実行には約10~15分程度要します。)
Apply complete! Resources: 8 added, 0 changed, 0 destroyed.
Outputs:
gke_cluster_endpoint = "X.X.X.X"以下のコマンドを実行してGKEクラスタの認証情報を取得します。(参考)
gcloud container clusters get-credentials $CLUSTER_NAME --region=$GCLOUD_REGION以下のコマンドを実行してクラスタ情報が取得できることを確認します。
kubectl cluster-infoKubernetes control plane is running at https://X.X.X.X
GLBCDefaultBackend is running at https://X.X.X.X/api/v1/namespaces/kube-system/services/default-http-backend:http/proxy
KubeDNS is running at https://X.X.X.X/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy
Metrics-server is running at https://X.X.X.X/api/v1/namespaces/kube-system/services/https:metrics-server:/proxy
To further debug and diagnose cluster problems, use 'kubectl cluster-info dump'.なお、今回構築したGKEクラスタではAutopilotモードを使用しています。
AutopilotモードではクラスタにデプロイされたPodなどのワークロードに応じて、ワークロードの実行環境であるNodeの数やインスタンスタイプを最適化するため、現時点でNode数は0になっています。(Nodeがあらかじめ作成されていることもあります。)
kubectl get nodesNo resources found
GKEクラスタにPodをデプロイし、LoadBalancerタイプのServiceを用いて外部に公開します。
nginxのPodを作成します。
kubectl run nginx --image nginx -n defaultしばらくするとPodが正常に起動し、STATUSがRunningであることを確認します。
※初回はPodが起動するまでに2分程度かかります。
kubectl get pods nginxNAME READY STATUS RESTARTS AGE
nginx 1/1 Running 0 97s
またPodをデプロイしたことで、AutopilotによりNodeが1台起動していることが確認できます。
kubectl get nodesNAME STATUS ROLES AGE VERSION
gk3-gke-wakaran-handson-cluste-pool-x-xxxxxxxxxxxxx Ready <none> 97s v1.32.2-gke.1182003※Podを起動する際に時間を要したのは、初めてPodをデプロイしたことによりNodeの起動が発生したためです。
次に作成したnginxのPodに対して外部からアクセスするためのServiceを作成します。
ここではGKEクラスタ外部にPodを公開するため、LoadBalancerタイプを指定することでServiceに対応したLoadBalancerが作成されるように設定を行っています。
scriptsディレクトリに格納されているservice.yamlマニフェストファイルを確認します。
scripts/service.yaml
apiVersion: v1
kind: Service
metadata:
name: nginx
spec:
ports:
- protocol: TCP
port: 80
targetPort: 80
selector:
run: nginx
type: LoadBalancerこのマニフェストを適用すると、KubernetesのServiceが作成され、それに紐付くLoadBalancer(Network Load Balancer)が作成されます。
kubectl apply -f scripts/service.yamlkubectlを用いてServiceリソースを参照し、EXTERNAL-IPに表示されているIPアドレスを確認します。
このIPアドレスが、Serviceを経由して外部からPodにアクセスするためのLoadBalancerのエンドポイントとなります。
※EXTERNAL-IPが設定されるまでには少し時間がかかります。
kubectl get svc nginxNAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
nginx LoadBalancer X.X.X.X <EXTERNAL_IP> 80:32500/TCP 54sGoogle Cloudのコンソールから、Load Balancerが作成されていることを確認します。

Webブラウザから<EXTERNAL_IP>にアクセスし、nginxの画面が表示されることを確認します。

Google Cloudが提供するパッケージマネージャーサービスArtifact Registryは、DockerHubのようなコンテナレジストリとして使用することができます。
ここではArtifact Registryに作成したリポジトリにコンテナイメージをアップロードし、GKEクラスタから利用します。
Docker Hubからnginxのコンテナイメージを取得します。
docker pull nginx環境変数にリポジトリパスを設定します。
export REPOSITORY_PATH="${GCLOUD_REGION}-docker.pkg.dev/${GCLOUD_PROJECT_ID}/${REPOSITORY_ID}"正しく環境変数が設定されたことを確認します。
echo REPOSITORY_PATH: ${REPOSITORY_PATH}asia-northeast1-docker.pkg.dev/<PROJECT_ID>/gke-wakaran-handson-repositoryPullしたコンテナイメージにイメージタグを付与します。
docker tag nginx ${REPOSITORY_PATH}/gke-wakaran-handson-nginx:gke-waiwai以下のコマンドを実行して、リポジトリに対する認証を行います。
gcloud auth configure-docker ${GCLOUD_REGION}-docker.pkg.dev以下のように確認が求められるのでYと入力します。
Adding credentials for: asia-northeast1-docker.pkg.dev
After update, the following will be written to your Docker config file located at [/home/vscode/.docker/config.json]:
{
"credHelpers": {
"asia-northeast1-docker.pkg.dev": "gcloud"
}
}
Do you want to continue (Y/n)? Y # <--- Yと入力してEnter
Docker configuration file updated.リポジトリにコンテナイメージをPushします。
docker push ${REPOSITORY_PATH}/gke-wakaran-handson-nginx:gke-waiwaiここまででArtifact Registryに作成したリポジトリへのコンテナイメージがアップロード完了しました。
Google Cloudのコンソールから、リポジトリにコンテナイメージが格納されていることを確認します。
※Artifact Registryの確認は、検索ウィンドウで「Artifact Registry」を検索し、「Artifact Registry」を選択することで行えます。

Artifact Registryのリポジトリにアップロードしたコンテナイメージから、GKEクラスタにPodをデプロイします。(参考)
以下のコマンド実行し、Artifact Registryのリポジトリにアップロードしたコンテナイメージを指定してPodをデプロイします。
kubectl run nginx-from-artifact-registry --image ${REPOSITORY_PATH}/gke-wakaran-handson-nginx:gke-waiwaiPodが正しくデプロイできたことを確認します。
kubectl get pod nginx-from-artifact-registryNAME READY STATUS RESTARTS AGE
nginx-from-artifact-registry 1/1 Running 0 2m20sGKEではWorkload Identity連携と呼ばれる仕組みにより、KubernetesのServiceAccountにGoogle CloudのIAMロールを紐付けることで、PodからGoogle Cloudのサービスにアクセスすることができます。
ここではこの仕組みを利用して、GKEにデプロイしたPodからCloud Storageのバケットにアクセスします。
なお、GKE AutopilotモードではWorkload Identity連携自体はデフォルトで有効化されているため、事前設定不要でServiceAccountへのロールの紐付けを行うことができます。
今回検証に用いるCloud Storageのバケットにテスト用ファイルをアップロードします。
Cloud Storageのバケット名を取得します。
STORAGE_BUCKET_NAME=$(gcloud storage buckets list --format="value(name)" | grep gke-wakaran-handson-bucket)バケット名が環境変数に設定されていることを確認します。
echo STORAGE_BUCKET_NAME: ${STORAGE_BUCKET_NAME}STORAGE_BUCKET_NAME: gke-wakaran-handson-bucket-xxxxx以下のコマンドを実行し、バケットにファイルをアップロードします。
touch test.txt
gcloud storage cp test.txt gs://${STORAGE_BUCKET_NAME}Copying file://test.txt to gs://gke-wakaran-handson-bucket-bqfce/test.txt
Completed files 1/1 | 0B 以下のコマンドを実行し、バケットにファイルがアップロードできたことを確認します。
gcloud storage ls gs://${STORAGE_BUCKET_NAME}gs://gke-wakaran-handson-bucket-bqfce/test.txtはじめにServiceAccountにCloud Storageのオブジェクト参照権限を含むロールを紐付けない場合、Podからバケットにアップロードしたファイルが参照できないことを確認します。
scriptsディレクトリに含まれているpod-before.yamlというマニフェストを適用し、Podをデプロイします。
kubectl apply -f scripts/pod-before.yaml Podがデプロイされたことを確認します。
kubectl get pod pod-beforeNAME READY STATUS RESTARTS AGE
pod-before 1/1 Running 0 47sPod内でgcloud storage lsコマンドを実行してバケット内のオブジェクトを参照しようとすると、権限エラーによりオブジェクトの参照が行えないことが確認できます。
kubectl exec -it pod-before -- gcloud storage ls gs://${STORAGE_BUCKET_NAME}ERROR: (gcloud.storage.ls) [<PROJECT_ID>.svc.id.goog] does not have permission to access b instance [gke-wakaran-handson-bucket-xxxxx] (or it may not exist): Caller does not have storage.objects.list access to the Google Cloud Storage bucket. Permission 'storage.objects.list' denied on resource (or it may not exist). This command is authenticated as <PROJECT_ID>.svc.id.goog which is the active account specified by the [core/account] property.
command terminated with exit code 1
次にServiceAccountにCloud Storageのオブジェクト参照権限を含むロール(storage.objectViewer)を紐付けた場合、Podからバケットにアップロードしたファイルが参照できるようになることを確認します。
以下のコマンドを実行し、ServiceAccountを作成します。
kubectl create serviceaccount gke-wakaran-handson-saServiceAccountが作成されたことを確認します。
kubectl get serviceaccount gke-wakaran-handson-saNAME SECRETS AGE
gke-wakaran-handson-sa 0 48sstorage.objectViewer(Storage オブジェクト閲覧者)というロールをServiceAccount(gke-wakaran-handson-sa)に紐付けます。
gcloud storage buckets add-iam-policy-binding gs://${STORAGE_BUCKET_NAME} \
--role=roles/storage.objectViewer \
--member=principal://iam.googleapis.com/projects/${GCLOUD_PROJECT_NUMBER}/locations/global/workloadIdentityPools/${GCLOUD_PROJECT_ID}.svc.id.goog/subject/ns/default/sa/gke-wakaran-handson-sa \
--condition=Nonebindings:
- members:
- projectEditor:<PROJECT_ID>
- projectOwner:<PROJECT_ID>
role: roles/storage.legacyBucketOwner
- members:
- projectViewer:<PROJECT_ID>
role: roles/storage.legacyBucketReader
- members:
- projectEditor:<PROJECT_ID>
- projectOwner:<PROJECT_ID>
role: roles/storage.legacyObjectOwner
- members:
- projectViewer:<PROJECT_ID>
role: roles/storage.legacyObjectReader
- members:
- principal://iam.googleapis.com/projects/<PROJECT_NUMBER>/locations/global/workloadIdentityPools/<PROJECT_ID>.svc.id.goog/subject/ns/default/sa/gke-wakaran-handson-sa
role: roles/storage.objectViewer
etag: CAM=
kind: storage#policy
resourceId: projects/_/buckets/gke-wakaran-handson-bucket-xxxxx
version: 1scriptsディレクトリに含まれているpod-after.yamlというマニフェストを適用し、Podをデプロイします。
このPodには先ほどstorage.objectViewerというロールを付与したServiceAccountが紐付けられています。
kubectl apply -f scripts/pod-after.yaml Podがデプロイされたことを確認します。
kubectl get pod pod-afterNAME READY STATUS RESTARTS AGE
pod-after 1/1 Running 0 105s先ほどと同様にPod内でgcloud storage lsコマンドを実行すると、今回はバケット内のオブジェクトが参照できることが確認できます。
kubectl exec -it pod-after -- gcloud storage ls gs://${STORAGE_BUCKET_NAME}gs://gke-wakaran-handson-bucket-xxxxx/test.txt
※本手順はQwiklabを使用している場合は実施不要です。
以下のコマンドを実行し、Terraformで作成した各種Google Cloudのリソースを削除します。
cd tffiles
terraform destroy以下のように確認が求められるのでyesと入力します。
...
Do you really want to destroy all resources?
Terraform will destroy all your managed infrastructure, as shown above.
There is no undo. Only 'yes' will be accepted to confirm.
Enter a value: yes # <--- yesと入力してEnterDestroy complete! Resources: 8 destroyed.ハンズオン用に作成したプロジェクトを削除します。
gcloud projects delete $GCLOUD_PROJECT_ID








