Skip to content

k8s-meetup-novice/gke-handson-20250508

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

ハンズオン内容

0. ハンズオン準備

本ハンズオンではGitHub Codespacesにコンテナ(devcontainer)として検証環境を作成し、その環境を利用します。
ハンズオンで使用するコマンド等はあらかじめdevcontainerに含まれているため、以下の手順を実施することで必要な検証環境を用意することができます。
(今回devcontainerの定義はこちらのものを使用しています。)

alt text

参考

0-1. codespaceの起動

左上のボタンをクリックし、「Codespaces」をクリックします。

alt text

New codespace」をクリックします。

alt text

Repositoryにて

k8s-meetup-novice/gke-handson-20250508

を選択し、「Create codespace」をクリックします。

alt text

以下のように開発環境(VSCode)が表示されます。

alt text

0-2. gcloud CLIの初期化

codespaceからGoogle Cloudにアクセスできるようにするため、gcloud CLIの初期化を行います。

以下のコマンドを実行し、表示されたURLにWebブラウザからアクセスします。

gcloud init --no-launch-browser
Welcome! 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アカウントを入力し「次へ」を押下します。 alt text

パスワードを入力し「次へ」を押下します。 alt text

「次へ」を押下します。 alt text

「許可」を押下します。 alt text

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

また、今回のハンズオン環境は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].

...

0-3. プロジェクトIDの確認

以下のコマンドを実行し、gcloudコマンドに設定されているプロジェクトを確認します。

gcloud config list
...
project = qwiklabs-gcp-xxxxxxx
...

以下のコマンドを実行し、ハンズオンに使用するプロジェクトのPROJECT_IDを確認します。
PROJECT_IDはプロジェクトを識別するためのグローバルに一意なIDです。(参考)

gcloud projects list
PROJECT_ID           NAME                   PROJECT_NUMBER
<PROJECT_ID>         qwiklabs-gcp-xxxxxxx   <PROJECT_NUMBER>
...

0-4. 環境変数の設定

以下のコマンドを用いて、環境変数に各種値を設定します。

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}
EOF
GCLOUD_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

0-5. サービスAPIの有効化

一般的に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 API

1. Google Cloudリソースの作成

Terraformを使用してGKEクラスタ、Artifact Registry Repository, Cloud Storageをはじめとした各種Google Cloudリソースを作成します。

1-1. Terraformが使用する認証情報の作成

以下のコマンドを実行し、TerraformからGoogle Cloudにアクセスするための認証情報を作成します。 コマンドを実行したら、「0-2. gcloud CLIの初期化」と同じ流れで認証を行います。

gcloud auth application-default login

以下のコマンドを実行し、Terraformを用いてGoogle Cloudリソースを作成します。(参考: Terraform CLI)

TerraformのIaCコードを含むtffilesディレクトリに移動します。

cd tffiles

Terraformワークスペースの初期化を行います。

terraform init

Terraformの実行計画を確認します。

terraform plan

Terraformでリソースを作成します。

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"

2. GKEへのアクセス

以下のコマンドを実行してGKEクラスタの認証情報を取得します。(参考)

gcloud container clusters get-credentials $CLUSTER_NAME --region=$GCLOUD_REGION

以下のコマンドを実行してクラスタ情報が取得できることを確認します。

kubectl cluster-info
Kubernetes 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 nodes
No resources found

3. アプリケーションのデプロイ及びLBを用いた外部公開

GKEクラスタにPodをデプロイし、LoadBalancerタイプのServiceを用いて外部に公開します。

3-1. Podのデプロイ

nginxPodを作成します。

kubectl run nginx --image nginx -n default

しばらくするとPodが正常に起動し、STATUSRunningであることを確認します。
※初回はPodが起動するまでに2分程度かかります。

kubectl get pods nginx
NAME    READY   STATUS    RESTARTS   AGE
nginx   1/1     Running   0          97s

またPodをデプロイしたことで、AutopilotによりNodeが1台起動していることが確認できます。

kubectl get nodes
NAME                                                  STATUS   ROLES    AGE   VERSION
gk3-gke-wakaran-handson-cluste-pool-x-xxxxxxxxxxxxx   Ready    <none>   97s   v1.32.2-gke.1182003

※Podを起動する際に時間を要したのは、初めてPodをデプロイしたことによりNodeの起動が発生したためです。

3-2. Serviceの作成と外部公開

次に作成したnginxPodに対して外部からアクセスするためのServiceを作成します。
ここではGKEクラスタ外部にPodを公開するため、LoadBalancerタイプを指定することでServiceに対応したLoadBalancerが作成されるように設定を行っています。

alt text

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.yaml

kubectlを用いてServiceリソースを参照し、EXTERNAL-IPに表示されているIPアドレスを確認します。
このIPアドレスが、Serviceを経由して外部からPodにアクセスするためのLoadBalancerのエンドポイントとなります。
EXTERNAL-IPが設定されるまでには少し時間がかかります。

kubectl get svc nginx
NAME    TYPE           CLUSTER-IP       EXTERNAL-IP      PORT(S)        AGE
nginx   LoadBalancer   X.X.X.X          <EXTERNAL_IP>    80:32500/TCP   54s

Google Cloudのコンソールから、Load Balancerが作成されていることを確認します。 alt text

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

参考

4. Artifact Registryに格納したコンテナイメージの使用

Google Cloudが提供するパッケージマネージャーサービスArtifact Registryは、DockerHubのようなコンテナレジストリとして使用することができます。
ここではArtifact Registryに作成したリポジトリにコンテナイメージをアップロードし、GKEクラスタから利用します。

4-1. コンテナイメージのアップロード

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-repository

Pullしたコンテナイメージにイメージタグを付与します。

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」を選択することで行えます。 alt text

4-2. GKEクラスタからのコンテナイメージの利用

Artifact Registryのリポジトリにアップロードしたコンテナイメージから、GKEクラスタにPodをデプロイします。(参考)

以下のコマンド実行し、Artifact Registryのリポジトリにアップロードしたコンテナイメージを指定してPodをデプロイします。

kubectl run nginx-from-artifact-registry --image ${REPOSITORY_PATH}/gke-wakaran-handson-nginx:gke-waiwai

Podが正しくデプロイできたことを確認します。

kubectl get pod nginx-from-artifact-registry
NAME                           READY   STATUS    RESTARTS   AGE
nginx-from-artifact-registry   1/1     Running   0          2m20s

5. Workload Identity連携

GKEではWorkload Identity連携と呼ばれる仕組みにより、KubernetesのServiceAccountにGoogle CloudのIAMロールを紐付けることで、PodからGoogle Cloudのサービスにアクセスすることができます。
ここではこの仕組みを利用して、GKEにデプロイしたPodからCloud Storageのバケットにアクセスします。
なお、GKE AutopilotモードではWorkload Identity連携自体はデフォルトで有効化されているため、事前設定不要でServiceAccountへのロールの紐付けを行うことができます。

alt text

参考

5-1. Cloud Storageのバケットにファイルをアップロード

今回検証に用いる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

5-2. ServiceAccountにロールを紐付けない場合

はじめにServiceAccountにCloud Storageのオブジェクト参照権限を含むロールを紐付けない場合、Podからバケットにアップロードしたファイルが参照できないことを確認します。

scriptsディレクトリに含まれているpod-before.yamlというマニフェストを適用し、Podをデプロイします。

kubectl apply -f scripts/pod-before.yaml 

Podがデプロイされたことを確認します。

kubectl get pod pod-before
NAME         READY   STATUS    RESTARTS   AGE
pod-before   1/1     Running   0          47s

Pod内で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

5-3. ServiceAccountにロールを紐付けた場合

次にServiceAccountにCloud Storageのオブジェクト参照権限を含むロール(storage.objectViewer)を紐付けた場合、Podからバケットにアップロードしたファイルが参照できるようになることを確認します。

以下のコマンドを実行し、ServiceAccountを作成します。

kubectl create serviceaccount gke-wakaran-handson-sa

ServiceAccountが作成されたことを確認します。

kubectl get serviceaccount gke-wakaran-handson-sa
NAME                     SECRETS   AGE
gke-wakaran-handson-sa   0         48s

storage.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=None
bindings:
- 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: 1

scriptsディレクトリに含まれているpod-after.yamlというマニフェストを適用し、Podをデプロイします。
このPodには先ほどstorage.objectViewerというロールを付与したServiceAccountが紐付けられています。

kubectl apply -f scripts/pod-after.yaml 

Podがデプロイされたことを確認します。

kubectl get pod pod-after
NAME        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

6. クリーンアップ

※本手順は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と入力してEnter
Destroy complete! Resources: 8 destroyed.

ハンズオン用に作成したプロジェクトを削除します。

gcloud projects delete $GCLOUD_PROJECT_ID

Releases

No releases published

Packages

No packages published

Languages