0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

PRベースでTerraformを適用!Atlantis × Helm × GKEでCI/CD環境を構築するPart1

Last updated at Posted at 2025-02-01

記事の内容

本記事では、AtlantisのHelm チャートを使った Terraform のCI/CD 環境構築について説明する。

この記事の作成に至った動機付けと背景

現在、私の携わっている案件では、GCP 環境で Terraform を手動で適用しており、作業負担や適用ミスのリスクが課題となっている。
さらに、以下のような問題もある。

  • 商用環境では、適用当日にしか権限が付与されないため、事前に terraform plan の結果を確認できない
  • terraform planterraform apply の結果を手動でコピー&ペーストし、証跡管理を行っている(手間がかかる&証跡がPR内で完結しない)
  • Terraform の適用が個人のローカル環境で実行されるため、チーム全体の可視性が低い

そこで、Terraform の適用を自動化するツールを検討した結果、Atlantis を利用することで、PR ベースのワークフローによる安全な適用が可能になると考えた。

現行の手動運用の流れ(問題点)
 1. GitHub に Push
 2. GitHub からクローン
 3. ローカル環境で terraform plan を実行(手動ミスのリスク)
 4. 期待した結果が得られたら PR 作成
 5. ローカル環境で terraform apply を実行(ログ管理が手間)
 6. PR を main ブランチにマージ

Atlantis を導入することで、手動適用の負担やミスのリスクを軽減し、安全な Terraform の適用が可能になると考えた。

Atlantisとは

Atlantis は、GitHub や GitLab のプルリクエストをトリガーに Terraform の plan や apply を実行できるOSSツール。
特徴:

  • PR 作成時に terraform plan を自動実行し、結果を PR 上にコメントとして出力
  • 承認後に PR 上で atlantis apply のコメントを記入することで terraform apply を実行
  • 手動での terraform apply 実行を防ぎ、Terraform の適用の一貫性を確保
  • Terraform の状態管理は Google Cloud Storage(GCS) などに保存可能

本記事では、Atlantis のHelm チャートを使用する。Helmチャートとは、再利用が可能なKubernetesリソースの一式を、所定の仕様でパッケージングしたファイルである。Helm チャートを使うことで、Kubernetes クラスタ上に 簡単に Atlantis をデプロイ・管理 でき、アップグレードや設定変更も柔軟に行える。
デフォルトの設定値はArtifact Hubに記載されているが、より詳細な設定やカスタマイズの方法については、GitHub の values.yaml を実際に確認しながら構築を進めていく。
image.png

Artifact Hub のデフォルト設定値

image.png

GitHub の values.yaml

image.png

アーキテクチャ

全体像は以下の通り。
スクリーンショット 2025-02-07 044945.png

1. GitHub からGKEクラスター 上に構築した Atlantis に Webhook でリクエスト
2. Atlantis が Terraform を実行する
3. Terraform がGCP上のリソースを apply。状態ファイルはGoogle Cloud Storageバケットに保存。
Atlantis と Terraform は Helm チャートを利用しており、GKEクラスター上に構築している。

構築手順

⚠️ 注意:本記事の手順は検証目的の構成を想定している。本番環境での運用には、セキュリティ対策や可用性を考慮し、適切な設定変更が必要になる。
前提として、

  • GKEクラスターは、Workload Identity を有効化して構築済みであること
  • GCSへ状態ファイルを格納する権限を持つGSA(roles/storage.objectAdmin または最小権限 IAMロールが付与 )が作成済みであること
  • コマンドは、GCP のCloudShellを利用すること

参考:Atlantis導入ガイド

1.下記コマンドを実行し、RunAtlantis Helm チャートリポジトリを登録する。

helm repo add runatlantis https://runatlantis.github.io/helm-charts

このコマンドによって、Helm に runatlantis というリポジトリを追加し、runatlantis/atlantis という Helm チャートを利用できるようになる。

2.Helm チャートを設定するディレクトリに移動後、下記コマンドを実行し、設定ファイルvalues.yamlを作成する。

helm inspect values runatlantis/atlantis > values.yaml

これによって、Helmチャートのデフォルトの設定値をvalues.yamlとして出力される。このファイルを編集していくことで、カスタマイズされたAtlantis の環境を構築できる。

3.Helm チャートの設定ファイルvalues.yamlを編集し、LoadBalancerを作成する。
Artifact Hub に記載されているデフォルトの設定値を確認すると、service.typeNodePort であることが確認できた。外部IPを作成し、そこにGitHub から Webhook リクエストを送信し、Terraform の適用を実行するため、service.typeLoadBalancer に変更する。
image.png

values.yaml
service:
  annotations: {}
  externalTrafficPolicy: null
  loadBalancerIP: null
  loadBalancerSourceRanges: []
  nodePort: null
  port: 80
  portName: atlantis
  targetPort: 4141
  type: LoadBalancer

4.下記コマンドを実行し、Helm で Atlantis の設定を適用する。

helm upgrade --install -f values.yaml atlantis runatlantis/atlantis

コマンドの内容としては、

helm upgrade --install -f <設定ファイルのパス> <リリース名> <Chart.yamlを格納するフォルダ>

helm upgrade --install は、指定したリリースが存在しない場合は新規作成し、すでに存在する場合は設定を更新する。つまり、初回は helm install と同じ動作になり、2回目以降は helm upgrade の動作になる。
そして、このコマンドによってrunatlantis/atlantis というHelmチャートからvalues.yamlの設定を適用したatlantis というリリースが作成される。
イメージとしては...

  • Helmチャート(runatlantis/atlantis)はClass
  • Helmリリース(atlantis)はClassから生成されたインスタンス
  • values.yamlはインスタンス作成時のコンストラクタ引数や設定ファイル

runatlantis/atlantisというClass をもとにvalues.yamlの設定を適用してatlantis というインスタンスが作成または更新される、というイメージですね。

5.下記コマンドを実行し、LoadBalancer の外部IP ( EXTERNAL-IP )を取得する。

kubectl get svc

image.png

6.GitHub Webhook の作成
image.png

入力内容は以下の通り。今回は簡単な検証のため、 SSL 通信は利用しない。

GitHub Webhookの設定内容
Payload URL:http://<LBの外部IP>/events
Content type:application/json
Secret:<Webhook 署名検証に使用する Secret>
SSL verification:Disable (not recommended)
Which events would you like to trigger this webhook?:
Let me select individual events.
  ・Pull requests:PR 作成時にPlan 実行
  ・Issue comment:atlantis apply などのコメントをトリガーに適用

7.Helm チャートの設定ファイルvalues.yamlにて、対象のGitHubリポジトリの認証情報とWebhook Secret を編集して追加する。また、対象の GitHubリポジトリをorgAllowlistに指定する。今回は、github.com/<org名>/*と指定することで、 GitHub の指定した org 内の全てのリポジトリに対して、Terraform の適用を許可する設定にする。

values.yaml
github:
  hostname: github.com
  secret: <Webhook 署名検証に使用する Secret(GitHub Webhook 設定と同じ値)>
  token: <GitHub認証トークン>
  user: <GitHubユーザー名>
values.yaml
orgAllowlist: github.com/<org名>/*

8 Helm チャートの設定ファイル values.yaml で、GSA のバインド設定を行う。annotations に roles/storage.objectAdmin を持つ GSA を指定する。

image.png
image.png
Artifact Hub と GitHub の values.yaml を確認し、適切な設定を行う。
Pod が GCP のサービスを利用できるようにするため、KSA と GSA をバインディングする設定に変更する。

values.yaml
serviceAccount:
  create: true
  mount: true
  name: atlantis-ksa
  annotations:
    iam.gke.io/gcp-service-account: "<roles/storage.objectAdminを付与したGSA名>"

9.下記コマンドを実行し、Helm で Atlantis の設定を適用する。

helm upgrade --install -f values.yaml atlantis runatlantis/atlantis

10.下記コマンドを実行し、 roles/storage.objectAdmin を付与した GSA を自動作成された KSA にバインディングする。

gcloud iam service-accounts add-iam-policy-binding \
    <roles/storage.objectAdminを付与したGSA> \
    --role roles/iam.workloadIdentityUser \
    --member "serviceAccount:<PROJECT>.svc.id.goog[atlantis/atlantis-ksa]"

⚠️ 注意
本手順では、Terraform の状態ファイルを保存するために GCS へのアクセス権限 (roles/storage.objectAdmin) を持つ GSA を KSA にバインディングする。

しかし、Terraform で GCP のリソースをデプロイするには、対象リソース(例: Compute Engine, Cloud SQL, GKEなど)への適切な IAMロールを持つ GSA が別途必要である。

Terraform 適用時に権限エラーが発生する場合は、デプロイ対象のリソースに適した権限を持つ GSA を作成し、同様に KSA にバインディングしてください。

11.下記コマンドを実行し、ポッドを再起動し、設定を確実に反映する。

kubectl delete po -l app=atlantis

Atlantis の動作を確認しながら PR を作成する

PR 作成時の Pod の挙動を確認するため、下記コマンドを実行し、 PR を作成してみる。

kubectl logs -f <atlantisのPod名>

PR を作成してみると、以下のようにTerraform の Plan 結果が PR のコメントとして出力された。変更リソースが色付きで表示され、見やすくなっている。
image.png
また、CloudShell上のPodのログでも、terraform planを実行していることが確認できた。

{"level":"info","ts":"2025-02-04T13:31:03.524Z","caller":"vcs/github_client.go:913","msg":"Updating GitHub Check status for 'atlantis/plan' to 'pending'","json":{"repo":"<リポジトリ名>","pull":"8"}

このログは、Atlantis が plan の結果を GitHub に送信し、PR 上の Checks に反映しようとしていることを示している。

その後、PR のコメントにatlantis apply -d .と入力すると、 apply が正常に実行されたことを確認できた。
image.png

構築を終えての感想

他の方のブログでは、多くが GCE インスタンス上に Atlantis を構築していた。
しかし、Helm チャートを活用することで、GKE 上に容易にデプロイできることが分かった。
また、GKE を採用することで、以下のような利点も得られる。

  • 可用性・冗長性の向上
    • マネージド Kubernetes による自動復旧・スケーリング
  • 運用負担の軽減
    • インスタンス管理不要
    • Helm チャートを使った容易なデプロイ

TerraformのCI/CD ツールにはTerraform Cloud やGitHub Actions も選択肢にあるが、実際の案件で活用する場合、それらと比較してAtlantis を導入することで、以下のような大きなメリットがあると感じた。

  • Terraform Cloud よりもコストを抑えられる(GKEクラスターが既に稼働している環境であれば追加コストが最小限)
  • GitHub Actions よりも環境構築が容易(Helm チャートを適用するだけで Atlantis をセットアップ可能)

実際の案件では、Terraform の適用を Atlantis で管理し、その後 ArgoCD でマニフェストを適用することで、Terraform と Kubernetes の運用を分離し、効率化を図る。
また、認証情報(GitHubトークンやWebhookシークレット)を Secrets で安全に管理し、Webhook のSSL通信 を適用することで、セキュリティを強化していく。
さらに、Atlantis の自動デプロイをさらに最適化し、Terraform と Kubernetes の統合運用をより安定させていく。


⚠️ 本番環境での考慮点
本記事の手順は 検証環境向け に作成しており、本番環境での運用には以下のような追加の設定が推奨される。

  • GitHubトークンや Webhookシークレットの Secret 化
    • values.yaml に認証情報を直接記載せず、Kubernetes Secret を利用する
  • SSL 対応
    • Webhook の SSL 設定を有効化し、HTTPS を使用することでセキュリティを強化する
  • IAM ロールの最小権限化
    • Workload Identity の IAM ロールを最小限に絞り、不要な権限を付与しない

本記事の内容をさらに発展させ、ArgoCD を活用して Helm チャートを自動適用する方法を以下の記事で解説しています。ぜひご覧ください!

PRベースでTerraformを適用!Atlantis × Helm × GKEでCI/CD環境を構築するPart2 HelmチャートをArgoCDで適用しよう!

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

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?