G-gen の佐々木です。当記事では、GitHub Actions で GKE クラスタにリソースをデプロイする際に、DNS エンドポイントを使用する方法を解説します。
- DNS エンドポイントとは
- GitHub Actions を使用した GKE へのデプロイ
- DNS エンドポイントを使用する GKE クラスタの作成
- Direct Workload Identity の構成
- GitHub Actions によるリソースのデプロイ
DNS エンドポイントとは
DNS エンドポイントとは、GKE のコントロールプレーンにアクセスする方法として従来からサポートされていた IP アドレスベースのアクセス元制御ではなく、DNS ベースのアクセス元制御を提供する機能です。
DNS エンドポイントが有効化されている場合、たとえコントロールプレーンにパブリック IP アドレスが割り当てられていなくても、IAM で許可されているユーザーはコントロールプレーンに接続することができます。
DNS エンドポイントの詳細、および IP アドレスベースのエンドポイントとの比較については、以下の記事をご一読ください。
GitHub Actions を使用した GKE へのデプロイ
従来の方法
DNS エンドポイントがリリースされる前は、コントロールプレーンのパブリックエンドポイントを無効化している場合、GitHub Actions からコントロールプレーンに直接接続することはできませんでした。
そのため、プライベートエンドポイント経由でコントロールプレーンに到達できる GKE ノード側の VPC 内に GitHub Actions の Self-Hosted Runner を構成し、Runner 上でワークフローを実行する方法などが用いられます。
Self-Hosted Runner は Compute Engine 仮想マシンや GKE クラスタ内の Pod で実行することになるため、GitHub Actions でデプロイパイプラインを構築したい場合、これらのリソースの運用管理も考慮していく必要があります。
DNS エンドポイントを使用する方法(当記事で解説)
DNS エンドポイントを使用する場合、GitHub Actions ワークフローから Google Cloud API にアクセスすることができれば、パブリック IP アドレスを持たないコントロールプレーンであっても直接接続することができます。
したがって、Self-Hosted Runner の運用を考えることなく、シンプルなパイプライン構成で GKE クラスタにリソースをデプロイできます。
GitHub Actions からコントロールプレーンに接続する際の IAM 認証については Workload Identity を使用します。
Workload Identity では Google Cloud プロジェクトに GitHub リポジトリを プロバイダ として登録し、プロバイダに対して IAM 権限を紐付けることで Google Cloud リソースへのアクセス権を与えることができます。
Workload Identity 連携の詳細については、以下のドキュメントをご一読ください。
- 参考1 : Workload Identity Federation
- 参考2 : Configure Workload Identity Federation with deployment pipelines
当記事では Workload Identity の方式のひとつである Direct Workload Identity を使用することで、IAM サービスアカウントの情報を GitHub Actions ワークフロー側に渡すことなく、プロバイダに対してコントロールプレーンに接続するための IAM 権限を直接付与します。
DNS エンドポイントを使用する GKE クラスタの作成
シェル変数の設定
まずは GitHub Actions のデプロイ先となる GKE クラスタを作成します。
当記事では gcloud CLI を使用してリソースを作成していきます。リソース作成時に何度か使用する値をシェル変数として設定しておきます。
PROJECT_ID={プロジェクトID} # ex: gha-demo-prj LOCATION={GKEを作成するロケーション} # ex: asia-northeast1 CLUSTER_NAME={任意のGKEクラスタの名前} # ex: mycluster
ネットワークリソースの作成
GKE クラスタを配置する VPC とサブネットを作成していきます。
以下のコマンドで VPC を作成します。
# VPC を作成する $ gcloud compute networks create vpc-${CLUSTER_NAME} \ --project=${PROJECT_ID} \ --subnet-mode=custom
作成した VPC の中にサブネットを作成します。当記事ではサブネットの IP 範囲として 192.168.11.0/24
を設定しています。
# サブネットを作成する $ gcloud compute networks subnets create subnet-${CLUSTER_NAME} \ --project=${PROJECT_ID} \ --network=vpc-${CLUSTER_NAME} \ --region=${LOCATION} \ --range=192.168.11.0/24
GKE クラスタの作成
--enable-dns-access
フラグを使用し、DNS エンドポイントを有効化した GKE クラスタを作成します。
以下のコマンドで、DNS エンドポイントを有効化した Autopilot モードの GKE クラスタを作成します。--no-enable-ip-access
フラグを使用することで IP アドレスベースの接続を無効化します。これで、Google Cloud API にアクセスでき、かつ IAM 権限を持つユーザーのみがコントロールプレーンに接続することができます。
# DNS エンドポイントを有効化した Autopilot クラスタを作成する(10分ほどかかるので注意) $ gcloud container clusters create-auto ${CLUSTER_NAME} \ --project=${PROJECT_ID} \ --network=vpc-${CLUSTER_NAME} \ --subnetwork=subnet-${CLUSTER_NAME} \ --enable-private-nodes \ --enable-dns-access \ --no-enable-ip-access
Direct Workload Identity の構成
シェル変数の設定
ここからは、GitHub Actions からコントロールプレーンに接続する際に認証を行うための Workload Identity の設定を行っていきます。
まずは、繰り返し使用する値をシェル変数として設定しておきます。
PROJECT_ID={プロジェクトID} # ex: gha-demo-prj PROJECT_NUMBER={プロジェクト番号} # ex: 1234567890 WORKLOAD_IDENTITY_POOL={任意のWorkload Identityプール名} # ex: my-gha-pool WORKLOAD_IDENTITY_PROVIDER={任意のWorkload Identityプロバイダ名} # ex: my-gha-provider GITHUB_REPO={GitHubリポジトリ名} # ex: my-org/my-repo
Workload Identity の設定
以下のコマンドで Workload Identity プールを作成します。
# Workload Identity プールの作成 $ gcloud iam workload-identity-pools create ${WORKLOAD_IDENTITY_POOL} \ --project=${PROJECT_ID} \ --location=global \ --display-name=${WORKLOAD_IDENTITY_POOL}
作成したプールに、Workload Identity プロバイダを作成します。
--attribute-condition
フラグで、この Workload Identity を使用する GitHub Actions ワークフローがある GitHub リポジトリをここで指定します。
# Workload Identity プロバイダの作成 $ gcloud iam workload-identity-pools providers create-oidc ${WORKLOAD_IDENTITY_PROVIDER} \ --project=${PROJECT_ID} \ --location=global \ --workload-identity-pool=${WORKLOAD_IDENTITY_POOL} \ --display-name=${WORKLOAD_IDENTITY_PROVIDER} \ --issuer-uri="https://token.actions.githubusercontent.com" \ --attribute-mapping="google.subject=assertion.sub,attribute.actor=assertion.actor,attribute.repository=assertion.repository" \ --attribute-condition="assertion.repository=='${GITHUB_REPO}'"
最後に、Workload Identity プロバイダに対して GKE クラスタにリソースをデプロイするための権限(roles/container.developer
)を付与します。
これにより、GitHub Actions ワークフローが DNS エンドポイント(Google Cloud API の認証)を通して GKE のコントロールプレーンに接続することができます。
# Workload Identity プロバイダに権限を付与する $ gcloud projects add-iam-policy-binding ${PROJECT_ID} \ --member="principalSet://iam.googleapis.com/projects/${PROJECT_NUMBER}/locations/global/workloadIdentityPools/${WORKLOAD_IDENTITY_POOL}/attribute.repository/${GITHUB_REPO}" \ --role="roles/container.developer"
GitHub Actions によるリソースのデプロイ
GitHub リポジトリのディレクトリ構成
Workload Identity プロバイダの作成時に指定した GitHub リポジトリに、GitHub Actions のワークフローと、GKE クラスタにデプロイする Kubernetes リソースのマニフェストファイルを配置します。
リポジトリ内のディレクトリ構成は以下のようにして進めていきます。
. ├── .github │ └── workflows │ └── demo-actions.yaml # GitHub Actions ワークフロー └── manifests └── sample-deployment.yaml # Kubernetes リソース(deployment)のマニフェストファイル
使用するファイル
GitHub Actions ワークフロー
Workload Identity を使用して GKE クラスタにリソースをデプロイする GitHub Actions ワークフローを作成します。
ワークフローファイル内の以下の箇所を、実際の値に置き換えてください。
行 | 置き換える箇所 | 値 |
---|---|---|
14行目 | {プロジェクトID} | GKE クラスタを作成したプロジェクトの ID |
15行目 | {プロジェクト番号} | GKE クラスタを作成したプロジェクトのプロジェクト番号 |
16行目 | {GKEクラスタ名} | GKE クラスタの名前 |
17行目 | {GKEクラスタのロケーション} | GKE クラスタを作成したロケーション |
18行目 | {Workload Identityプール名} | Workload Idenity プールの名前 |
19行目 | {Workload Identityプロバイダ名} | Workload Identity プロバイダの名前 |
# demo-actions.yaml name: apply k8s manifest to GKE # main ブランチへの Pull Request / Push で実行 on: pull_request: branches: - main push: branches: - main # 環境変数に GKE クラスタの情報を設定 env: PROJECT_ID: {プロジェクトID} # Google Cloud プロジェクト ID PROJECT_NUM: {プロジェクト番号} # Google Cloud プロジェクト番号 GKE_CLUSTER: {GKEクラスタ名} # GKE クラスタ名 GKE_LOCATION: {GKEクラスタのロケーション} # GKE クラスタのロケーション WID_POOL: {Workload Identityプール名} # Workload Identity プール名 WID_PROVIDER: {Workload Identityプロバイダ名} # Workload Identity プロバイダ名 # ジョブ (GitHUb runners で実行) jobs: setup-apply: runs-on: ubuntu-latest permissions: id-token: write contents: read pull-requests: write steps: - id: checkout name: Checkout uses: actions/checkout@v4 # Workload Identity 連携 # https://cloud.google.com/iam/docs/using-workload-identity-federation#generate-automatic - id: auth name: Authenticate to Google Cloud uses: google-github-actions/auth@v2 with: workload_identity_provider: 'projects/${{ env.PROJECT_NUM }}/locations/global/workloadIdentityPools/${{ env.WID_POOL }}/providers/${{ env.WID_PROVIDER }}' # Workload Identity Pool のプロバイダー # https://github.com/google-github-actions/setup-gcloud - id: setup-gcloud name: Setup gcloud uses: google-github-actions/setup-gcloud@v2 with: project_id: ${{ env.PROJECT_ID }} # GKE の認証プラグイン # https://cloud.google.com/kubernetes-engine/docs/deprecations/auth-plugin?hl=ja - id: install-gke-gcloud-auth-plugin name: Install gke-gcloud-auth-plugin run: | gcloud components install gke-gcloud-auth-plugin # GKE クラスタの認証情報を取得 (DNS エンドポイントを使用) - id: get-gke-credentials name: Get GKE credentials run: | gcloud container clusters get-credentials ${{ env.GKE_CLUSTER }} --region ${{ env.GKE_LOCATION }} --dns-endpoint # マニフェストファイルの適用 - id: apply name: Apply run: | kubectl apply -f ./manifests
Kubernetes マニフェストファイル
GKE クラスタにデプロイするリソースのマニフェストファイルを作成します。
当記事では、nginx コンテナを実行する Pod を3つ作成する Deployment リソースを作成します。
# sample-deployment.yaml apiVersion: apps/v1 kind: Deployment metadata: name: sample-deployment spec: replicas: 3 selector: matchLabels: app: sample-app template: metadata: labels: app: sample-app spec: containers: - name: sample-app image: nginx:1.27
GitHub Actions の実行
作成したワークフローファイルとマニフェストファイルをリモートリポジトリに push し、GitHub Actions ワークフローを実行します。
ワークフローが実行され、GitHub Actions から GKE クラスタに対してマニフェストファイルが適用されます。Deployment リソースが作成されていることが GitHub Actions のログからわかります。
ローカルから GKE クラスタのコントロールプレーンに接続し、デプロイしたリソースの状態を確認します。
# DNS エンドポイントでコントロールプレーンに接続する $ gcloud container clusters get-credentials ${CLUSTER_NAME} --dns-endpoint # Deployment リソースを表示 $ kubectl get deployments
マニフェストファイルの記述通り、3つの Pod を実行する Deployment リソースが作成されています。
# Deployment リソースを表示(出力例) $ kubectl get deployments NAME READY UP-TO-DATE AVAILABLE AGE sample-deployment 3/3 3 3 2m7s
修正したマニフェストファイルの反映
マニフェストファイルの修正
マニフェストファイルを修正してからリモートリポジトリに push し、GitHub Actions ワークフローによるデプロイを再度行います。
マニフェストファイル内の spec.replicas
の値を 1
にして、Pod 数をスケールインするように修正します。
# sample-deployment.yaml apiVersion: apps/v1 kind: Deployment metadata: name: sample-deployment spec: replicas: 1 # ここを修正する selector: matchLabels: app: sample-app template: metadata: labels: app: sample-app spec: containers: - name: sample-app image: nginx:1.27
GitHub Actions の再実行
再度、リモートリポジトリへの push を行い、GitHub Actions ワークフローを実行します。
ワークフローの実行後、Deployment の状態を確認します。push したマニフェストファイルが GitHub Actions から適用され、Pod の数が1になりました。
# Deployment リソースを確認(出力例) $ kubectl get deployments NAME READY UP-TO-DATE AVAILABLE AGE sample-deployment 1/1 1 1 7m5s
佐々木 駿太 (記事一覧)
G-gen最北端、北海道在住のクラウドソリューション部エンジニア
2022年6月にG-genにジョイン。Google Cloud Partner Top Engineer 2025 Fellowに選出。好きなGoogle CloudプロダクトはCloud Run。
趣味はコーヒー、小説(SF、ミステリ)、カラオケなど。
Follow @sasashun0805