Atlantis
Atlantis 完全ガイド: Terraform Pull Request 自動化プラットフォーム
目次
- はじめに
- Atlantis の概要とアーキテクチャ
- サポートされる VCS プラットフォーム
- インストールとデプロイメント
- サーバー設定 (Server Configuration)
- リポジトリレベル設定 (atlantis.yaml)
- サーバーサイドリポジトリ設定 (repos.yaml)
- カスタムワークフロー
- Autoplan と Automerge
- ロック機構
- コマンドリファレンス
- Apply 要件とアクセス制御
- ポリシーチェック (Conftest 連携)
- Pre/Post ワークフローフック
- Terraform Cloud / Enterprise 連携
- API エンドポイント
- セキュリティ
- 高度な設定と運用パターン
- トラブルシューティング
- まとめ
1. はじめに
1.1 本ドキュメントの目的
本ドキュメントでは、Terraform Pull Request 自動化ツールである Atlantis (https://www.runatlantis.io) の機能、アーキテクチャ、設定方法について包括的に解説する。Atlantis は、Infrastructure as Code (IaC) のワークフローにおいて、Pull Request ベースの Terraform オペレーションを自動化するオープンソースツールであり、チームでの安全かつ効率的なインフラストラクチャ管理を実現する。
1.2 Atlantis が解決する課題
従来の Terraform 運用では、以下のような課題が存在していた:
- ローカル実行のリスク: 各開発者がローカル環境で
terraform plan/terraform applyを実行する場合、実行環境の差異や認証情報の管理が困難 - レビュープロセスの欠如: Terraform のコード変更に対して、plan 結果をレビューする標準的なプロセスが確立しにくい
- 並行変更の衝突: 複数のエンジニアが同じ State に対して同時に変更を加えると、State の破損や意図しない変更が発生する可能性がある
- 可視性の不足: 誰がいつどのような変更をインフラに加えたかの追跡が困難
- CI/CD パイプラインとの統合: 汎用 CI/CD ツールで Terraform を実行する場合の複雑なセットアップ
Atlantis はこれらの課題を、Pull Request 駆動のワークフローによって解決する。
1.3 Atlantis の基本哲学
Atlantis は以下の設計哲学に基づいている:
- Pull Request がすべての起点: インフラ変更は必ず Pull Request を通じて行う
- 自動化による一貫性: plan と apply のプロセスを自動化し、人為的ミスを削減
- コラボレーションの促進: plan 結果を Pull Request のコメントとして共有し、チームでのレビューを容易にする
- 最小権限の原則: 個人の開発者がクラウド認証情報を持つ必要をなくし、Atlantis サーバーが一元的に認証を管理する
2. Atlantis の概要とアーキテクチャ
2.1 Atlantis とは
Atlantis は、Go 言語で開発されたシングルバイナリのアプリケーションであり、VCS (Version Control System) プラットフォームからの Webhook を受信して Terraform コマンドを実行する。CNCF (Cloud Native Computing Foundation) のランドスケープにも含まれており、広く利用されている。
2.2 アーキテクチャ概要
Atlantis のアーキテクチャは以下のコンポーネントで構成される:
┌─────────────────────────────────────────────────────────┐
│ VCS プラットフォーム │
│ (GitHub / GitLab / Bitbucket / Azure DevOps / Gitea) │
│ │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ PR 作成 │ │ コメント │ │ Push │ │
│ └─────┬────┘ └─────┬────┘ └─────┬────┘ │
│ │ │ │ │
│ └───────────────┼───────────────┘ │
│ │ │
│ Webhook │
└────────────────────────┼─────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────┐
│ Atlantis サーバー │
│ │
│ ┌──────────────────────────────────────────────┐ │
│ │ Webhook ハンドラー │ │
│ │ - リクエスト検証 (Webhook Secret) │ │
│ │ - イベントパース │ │
│ └──────────────────┬───────────────────────────┘ │
│ │ │
│ ┌──────────────────▼───────────────────────────┐ │
│ │ コマンドルーター │ │
│ │ - plan / apply / unlock / import │ │
│ │ - approve_policies │ │
│ └──────────────────┬───────────────────────────┘ │
│ │ │
│ ┌──────────────────▼───────────────────────────┐ │
│ │ プロジェクトディスカバリー │ │
│ │ - atlantis.yaml パース │ │
│ │ - 変更ファイルの検出 │ │
│ │ - Terraform プロジェクトの特定 │ │
│ └──────────────────┬───────────────────────────┘ │
│ │ │
│ ┌──────────────────▼───────────────────────────┐ │
│ │ ロックマネージャー │ │
│ │ - BoltDB / Redis │ │
│ │ - ディレクトリ + ワークスペース単位 │ │
│ └──────────────────┬───────────────────────────┘ │
│ │ │
│ ┌──────────────────▼───────────────────────────┐ │
│ │ Terraform 実行エンジン │ │
│ │ - init → plan → (policy check) → apply │ │
│ │ - カスタムワークフローステップ │ │
│ └──────────────────┬───────────────────────────┘ │
│ │ │
│ ┌──────────────────▼───────────────────────────┐ │
│ │ VCS コメント投稿 │ │
│ │ - Plan 結果のフォーマット │ │
│ │ - ステータスチェックの更新 │ │
│ └──────────────────────────────────────────────┘ │
│ │
│ ┌──────────────┐ ┌──────────────┐ │
│ │ データディレクトリ │ │ Web UI │ │
│ │ (Plan ファイル) │ │ (ロック一覧) │ │
│ └──────────────┘ └──────────────┘ │
└─────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────┐
│ クラウドプロバイダー / State Backend │
│ (AWS / GCP / Azure / Terraform Cloud) │
└─────────────────────────────────────────────────────────┘
2.3 基本的なワークフロー
Atlantis を使用した標準的な Terraform ワークフローは以下の通り:
- 開発者が Pull Request を作成: Terraform コードの変更を含むブランチから PR を作成
- Atlantis が自動で plan を実行: Webhook 経由で PR の作成を検知し、自動的に
terraform planを実行 - plan 結果が PR にコメントとして投稿: チームメンバーがインフラ変更の内容をレビュー可能
- レビューと承認: コードレビューと plan 結果の確認後、PR を承認
atlantis applyの実行: PR のコメントでatlantis applyと入力して変更を適用- PR のマージ: apply が成功したら PR をマージ
開発者 VCS (GitHub 等) Atlantis Cloud Provider
│ │ │ │
│── PR 作成 ──────>│ │ │
│ │── Webhook ────────>│ │
│ │ │── git clone ──────>│
│ │ │── terraform init ─>│
│ │ │── terraform plan ─>│
│ │<── Plan 結果 ──────│ │
│<── Plan 表示 ────│ │ │
│ │ │ │
│── レビュー&承認 ->│ │ │
│ │ │ │
│── "atlantis │ │ │
│ apply" ──────>│── Webhook ────────>│ │
│ │ │── terraform apply >│
│ │<── Apply 結果 ─────│ │
│<── 結果表示 ─────│ │ │
│ │ │ │
│── PR マージ ─────>│ │ │
│ │── Webhook ────────>│ │
│ │ │── ロック解除 ──────│
2.4 データストレージ
Atlantis は外部データベースを必要としない。Plan ファイルとロック情報はローカルディスクに保存される:
- BoltDB (デフォルト): ロック情報の永続化に使用
- Redis (オプション): 分散環境でのロック管理に使用可能
- ファイルシステム: Terraform plan ファイルの保存
このため、Kubernetes にデプロイする場合は StatefulSet の使用が推奨される。Pod が再起動しても plan ファイルが失われないよう、永続ボリュームの設定が重要である。
3. サポートされる VCS プラットフォーム
Atlantis は以下の VCS プラットフォームをサポートしている:
| プラットフォーム | Webhook サポート | ステータスチェック | コメント投稿 | 備考 |
|---|---|---|---|---|
| GitHub (github.com) | 完全対応 | 対応 | 対応 | GitHub App にも対応 |
| GitHub Enterprise | 完全対応 | 対応 | 対応 | --gh-hostname で設定 |
| GitLab (gitlab.com) | 完全対応 | 対応 | 対応 | Merge Request ベース |
| GitLab Enterprise | 完全対応 | 対応 | 対応 | --gitlab-hostname で設定 |
| Bitbucket Cloud | 完全対応 | 対応 | 対応 | App Password 使用 |
| Bitbucket Server | 完全対応 | 対応 | 対応 | --bitbucket-base-url で設定 |
| Azure DevOps | 完全対応 | 対応 | 対応 | Basic 認証ベース |
| Gitea | 完全対応 | 対応 | 対応 | --gitea-base-url で設定 |
3.1 GitHub 設定例
atlantis server \
--gh-user="atlantis-bot" \
--gh-token="ghp_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
--gh-webhook-secret="your-random-secret-string" \
--repo-allowlist="github.com/myorg/*" \
--atlantis-url="https://atlantis.example.com"
GitHub App を使用する場合
atlantis server \
--gh-app-id="12345" \
--gh-app-key-file="/path/to/private-key.pem" \
--gh-app-slug="my-atlantis-app" \
--gh-webhook-secret="your-random-secret-string" \
--repo-allowlist="github.com/myorg/*"
3.2 GitLab 設定例
atlantis server \
--gitlab-user="atlantis-bot" \
--gitlab-token="glpat-xxxxxxxxxxxxxxxxxxxx" \
--gitlab-webhook-secret="your-random-secret-string" \
--repo-allowlist="gitlab.com/mygroup/*"
3.3 Azure DevOps 設定例
atlantis server \
--azuredevops-user="atlantis@myorg.com" \
--azuredevops-token="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
--azuredevops-webhook-user="webhook-user" \
--azuredevops-webhook-password="webhook-password" \
--repo-allowlist="dev.azure.com/myorg/*"
3.4 Gitea 設定例
atlantis server \
--gitea-user="atlantis-bot" \
--gitea-token="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
--gitea-webhook-secret="your-random-secret-string" \
--gitea-base-url="https://gitea.example.com" \
--repo-allowlist="gitea.example.com/myorg/*"
4. インストールとデプロイメント
4.1 デプロイメント方式の概要
| 方式 | 推奨度 | 特徴 |
|---|---|---|
| Kubernetes Helm Chart | 推奨 | 公式 Helm Chart。最も簡単 |
| Kubernetes Manifest | 推奨 | StatefulSet での永続化対応 |
| Docker | 高 | シンプルな単一コンテナ運用 |
| AWS Fargate | 高 | サーバーレスコンテナ |
| Google Cloud Run | 中 | サーバーレス対応 |
| GKE / GCE | 高 | Google Cloud 上の Kubernetes |
| Azure AKS / ACI | 高 | Azure 上のコンテナサービス |
| バイナリ直接実行 | 中 | 開発/テスト用途 |
4.2 Kubernetes Helm Chart によるデプロイ
helm repo add runatlantis https://runatlantis.github.io/helm-charts
helm inspect values runatlantis/atlantis > values.yaml
values.yaml の主要設定:
orgWhitelist: "github.com/myorg/*"
github:
user: "atlantis-bot"
token: "ghp_xxxxxxxxxxxxxxxxxxxx"
secret: "your-webhook-secret"
persistence:
enabled: true
storageClassName: "standard"
accessModes: ["ReadWriteOnce"]
size: 5Gi
resources:
requests:
memory: "256Mi"
cpu: "100m"
limits:
memory: "1Gi"
cpu: "1000m"
ingress:
enabled: true
annotations:
kubernetes.io/ingress.class: nginx
cert-manager.io/cluster-issuer: letsencrypt-prod
hosts:
- host: atlantis.example.com
paths: [/]
tls:
- secretName: atlantis-tls
hosts: [atlantis.example.com]
repoConfig: |
---
repos:
- id: /.*/
apply_requirements: [approved, mergeable]
allowed_overrides: [apply_requirements, workflow]
allow_custom_workflows: true
helm install atlantis runatlantis/atlantis -f values.yaml
4.3 Kubernetes StatefulSet によるデプロイ
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: atlantis
spec:
serviceName: atlantis
replicas: 1
selector:
matchLabels:
app: atlantis
template:
metadata:
labels:
app: atlantis
spec:
securityContext:
fsGroup: 1000
containers:
- name: atlantis
image: ghcr.io/runatlantis/atlantis:v0.28.0
env:
- name: ATLANTIS_REPO_ALLOWLIST
value: "github.com/myorg/*"
- name: ATLANTIS_GH_USER
valueFrom:
secretKeyRef:
name: atlantis-secrets
key: gh-user
- name: ATLANTIS_GH_TOKEN
valueFrom:
secretKeyRef:
name: atlantis-secrets
key: gh-token
- name: ATLANTIS_GH_WEBHOOK_SECRET
valueFrom:
secretKeyRef:
name: atlantis-secrets
key: gh-webhook-secret
- name: ATLANTIS_DATA_DIR
value: "/atlantis-data"
- name: ATLANTIS_PORT
value: "4141"
ports:
- name: atlantis
containerPort: 4141
resources:
requests: { memory: "256Mi", cpu: "100m" }
limits: { memory: "1Gi", cpu: "1000m" }
livenessProbe:
httpGet: { path: /healthz, port: 4141 }
periodSeconds: 60
readinessProbe:
httpGet: { path: /healthz, port: 4141 }
periodSeconds: 60
volumeMounts:
- name: atlantis-data
mountPath: /atlantis-data
volumeClaimTemplates:
- metadata:
name: atlantis-data
spec:
accessModes: ["ReadWriteOnce"]
storageClassName: "standard"
resources:
requests:
storage: 5Gi
4.4 Docker によるデプロイ
docker run -d --name atlantis -p 4141:4141 \
-v /var/atlantis-data:/atlantis-data \
ghcr.io/runatlantis/atlantis:v0.28.0 server \
--atlantis-url="https://atlantis.example.com" \
--gh-user="atlantis-bot" \
--gh-token="ghp_xxxxxxxxxxxxxxxxxxxx" \
--gh-webhook-secret="your-secret" \
--repo-allowlist="github.com/myorg/*" \
--data-dir="/atlantis-data"
カスタム Docker イメージ
FROM ghcr.io/runatlantis/atlantis:v0.28.0
USER root
ARG TERRAGRUNT_VERSION=0.55.0
RUN curl -Lo /usr/local/bin/terragrunt \
"https://github.com/gruntwork-io/terragrunt/releases/download/v${TERRAGRUNT_VERSION}/terragrunt_linux_amd64" \
&& chmod +x /usr/local/bin/terragrunt
USER atlantis
4.5 AWS Fargate によるデプロイ
module "atlantis" {
source = "terraform-aws-modules/atlantis/aws"
version = "~> 4.0"
name = "atlantis"
cidr = "10.20.0.0/16"
azs = ["ap-northeast-1a", "ap-northeast-1c"]
private_subnets = ["10.20.1.0/24", "10.20.2.0/24"]
public_subnets = ["10.20.101.0/24", "10.20.102.0/24"]
atlantis_github_user = "atlantis-bot"
atlantis_github_user_token = "ghp_xxxxxxxxxxxxxxxxxxxx"
atlantis_repo_allowlist = ["github.com/myorg/*"]
route53_zone_name = "example.com"
certificate_arn = "arn:aws:acm:..."
}
5. サーバー設定 (Server Configuration)
5.1 設定の優先順位
コマンドラインフラグ > 環境変数 > 設定ファイル (YAML)
環境変数の命名規則: --gh-user → ATLANTIS_GH_USER
YAML 設定ファイル例
# config.yaml
gh-user: "atlantis-bot"
gh-token: "ghp_xxxxxxxxxxxxxxxxxxxx"
gh-webhook-secret: "your-secret"
repo-allowlist: "github.com/myorg/*"
atlantis-url: "https://atlantis.example.com"
port: 4141
data-dir: "/var/atlantis"
log-level: "info"
5.2 コアサーバー設定
| フラグ | 環境変数 | デフォルト | 説明 |
|---|---|---|---|
--port | ATLANTIS_PORT | 4141 | リッスンポート |
--atlantis-url | ATLANTIS_ATLANTIS_URL | http://$(hostname):$port | 外部 URL |
--data-dir | ATLANTIS_DATA_DIR | ~/.atlantis | データディレクトリ |
--log-level | ATLANTIS_LOG_LEVEL | info | ログレベル |
--repo-allowlist | ATLANTIS_REPO_ALLOWLIST | なし (必須) | 許可リポジトリパターン |
--allow-fork-prs | ATLANTIS_ALLOW_FORK_PRS | false | フォーク PR への応答 |
--allow-draft-prs | ATLANTIS_ALLOW_DRAFT_PRS | false | ドラフト PR への応答 |
5.3 Plan / Apply 関連設定
| フラグ | デフォルト | 説明 |
|---|---|---|
--autoplan-file-list | **/*.tf,**/*.tfvars,**/*.tfvars.json | Autoplan トリガーパターン |
--autoplan-modules | false | モジュール依存関係トレース |
--disable-autoplan | false | 自動 plan 無効化 |
--disable-apply-all | false | プロジェクト指定必須化 |
--automerge | false | 自動マージ |
--parallel-plan | false | 並列 plan |
--parallel-apply | false | 並列 apply |
--parallel-pool-size | 15 | 並列最大数 |
5.4 Terraform 関連設定
| フラグ | デフォルト | 説明 |
|---|---|---|
--default-tf-version | なし | デフォルト Terraform バージョン |
--default-tf-distribution | terraform | terraform or opentofu |
--tf-download | true | 自動ダウンロード許可 |
--use-tf-plugin-cache | true | プラグインキャッシュ |
5.5 セキュリティ関連設定
| フラグ | デフォルト | 説明 |
|---|---|---|
--api-secret | なし | API 認証シークレット |
--web-basic-auth | false | Web UI Basic 認証 |
--ssl-cert-file | なし | SSL 証明書パス |
--ssl-key-file | なし | SSL 秘密鍵パス |
--var-file-allowlist | データディレクトリ | tfvars ディレクトリ制限 |
5.6 ロック管理設定
| フラグ | デフォルト | 説明 |
|---|---|---|
--locking-db-type | boltdb | ロックバックエンド |
--redis-host | なし | Redis ホスト |
--redis-port | 6379 | Redis ポート |
--redis-tls-enabled | false | Redis TLS |
--disable-repo-locking | false | ロック無効化 |
5.7 通知・UI 関連設定
| フラグ | デフォルト | 説明 |
|---|---|---|
--hide-prev-plan-comments | false | 以前の plan コメント非表示 |
--hide-unchanged-plan-comments | false | 変更なし plan 削除 |
--disable-markdown-folding | false | details タグ無効化 |
--enable-diff-markdown-format | false | diff カラーコーディング |
--slack-token | なし | Slack 通知トークン |
--enable-policy-checks | false | ポリシーチェック有効化 |
--enable-regexp-cmd | false | 正規表現コマンド許可 |
--markdown-template-overrides-dir | ~/.markdown_templates/ | テンプレートディレクトリ |
6. リポジトリレベル設定 (atlantis.yaml)
6.1 概要
atlantis.yaml はリポジトリのルートに配置する設定ファイル。オプションであり、デフォルト設定で多くのケースに対応可能。
重要: Atlantis は PR ブランチ の atlantis.yaml を使用する。カスタムワークフローが許可されている場合、PR を作成できる人が Atlantis サーバー上で任意のコードを実行できる可能性がある。
6.2 基本構造
version: 3 # 必須
automerge: false
delete_source_branch_on_merge: false
parallel_plan: false
parallel_apply: false
abort_on_execution_order_fail: false
projects: []
workflows: {}
allowed_regexp_prefixes: []
6.3 プロジェクト設定
version: 3
projects:
- name: networking
dir: infrastructure/networking
workspace: default
terraform_version: "1.7.0"
terraform_distribution: terraform
workflow: custom-workflow
execution_order_group: 1
autoplan:
enabled: true
when_modified:
- "*.tf"
- "*.tfvars"
- ".terraform.lock.hcl"
- "../modules/networking/**/*.tf"
apply_requirements:
- approved
- mergeable
plan_requirements:
- undiverged
- name: compute
dir: infrastructure/compute
workspace: default
execution_order_group: 2
depends_on:
- networking
6.4 プロジェクトフィールド
| フィールド | 型 | デフォルト | 説明 |
|---|---|---|---|
name | string | - | プロジェクト名 |
dir | string | 必須 | ディレクトリパス |
workspace | string | default | ワークスペース名 |
terraform_version | string | - | Terraform バージョン |
terraform_distribution | string | terraform | terraform or opentofu |
workflow | string | - | ワークフロー名 |
execution_order_group | int | 0 | 実行順序 |
depends_on | array | - | 依存プロジェクト |
branch | string | - | ベースブランチ正規表現 |
6.5 Autodiscovery
version: 3
autodiscover:
mode: auto # auto / enabled / disabled
ignore_paths:
- "test/**"
- "examples/**"
6.6 リポジトリロック
version: 3
repo_locks:
mode: on_plan # on_plan / on_apply / disabled
6.7 完全な設定例 (マルチ環境)
version: 3
automerge: false
parallel_plan: true
abort_on_execution_order_fail: true
projects:
- name: dev-networking
dir: environments/dev/networking
terraform_version: "1.7.0"
workflow: dev
execution_order_group: 1
autoplan:
enabled: true
when_modified: ["*.tf", "*.tfvars", "../../../modules/networking/**/*.tf"]
- name: dev-compute
dir: environments/dev/compute
terraform_version: "1.7.0"
workflow: dev
execution_order_group: 2
depends_on: [dev-networking]
- name: prod-networking
dir: environments/prod/networking
terraform_version: "1.7.0"
workflow: production
execution_order_group: 1
apply_requirements: [approved, mergeable]
- name: prod-compute
dir: environments/prod/compute
terraform_version: "1.7.0"
workflow: production
execution_order_group: 2
depends_on: [prod-networking]
apply_requirements: [approved, mergeable]
workflows:
dev:
plan:
steps:
- init
- plan:
extra_args: ["-var-file", "dev.tfvars"]
apply:
steps: [apply]
production:
plan:
steps:
- init
- plan:
extra_args: ["-var-file", "prod.tfvars"]
apply:
steps:
- run: ./scripts/notify-slack.sh "Production deployment starting"
- apply
- run: ./scripts/notify-slack.sh "Production deployment completed"
7. サーバーサイドリポジトリ設定 (repos.yaml)
7.1 概要
repos.yaml はサーバーサイド設定ファイルで、リポジトリごとの動作を中央集権的に制御する。
atlantis server --repo-config=/etc/atlantis/repos.yaml
7.2 トップレベル構造
repos:
- id: /.*/
# リポジトリ設定
workflows:
custom:
plan:
steps: [init, plan]
apply:
steps: [apply]
policies:
owners:
users: ["admin-user"]
policy_sets:
- name: security-policy
path: /policies/security/
source: local
7.3 リポジトリ設定の詳細
repos:
- id: /.*/
branch: /.*/
plan_requirements: [approved]
apply_requirements: [approved, mergeable]
import_requirements: [approved]
workflow: default
allowed_overrides: [apply_requirements, workflow]
allowed_workflows: [default, custom-plan]
allow_custom_workflows: false
delete_source_branch_on_merge: false
repo_locks:
mode: on_plan
policy_check: true
autodiscover:
mode: auto
- id: github.com/myorg/infrastructure-prod
apply_requirements: [approved, mergeable, undiverged]
allowed_overrides: []
allow_custom_workflows: false
- id: /github.com\/myorg\/infra-.*/
workflow: infra-team
allowed_overrides: [workflow]
allowed_workflows: [infra-team, infra-team-with-validation]
7.4 マッチング規則
複数パターンがマッチする場合、後に定義されたものが優先。未定義キーは以前のマッチから継承。
7.5 Pre/Post ワークフローフック
repos:
- id: /.*/
pre_workflow_hooks:
- run: ./scripts/generate-atlantis-config.sh
description: "Dynamic config generation"
commands: plan
post_workflow_hooks:
- run: ./scripts/cleanup.sh
description: "Post-workflow cleanup"
commands: plan, apply
8. カスタムワークフロー
8.1 ワークフロー構造
workflows:
my-workflow:
plan:
steps: [...]
apply:
steps: [...]
import:
steps: [...]
state_rm:
steps: [...]
8.2 ステップの種類
ビルトインコマンド
steps:
- init
- plan
- apply
ビルトインコマンド + 追加引数
steps:
- init:
extra_args: ["-upgrade"]
- plan:
extra_args: ["-lock=false", "-var-file", "production.tfvars"]
カスタム run コマンド
steps:
- run: echo "Hello, World!"
- run:
command: terraform plan -out=$PLANFILE
shell: bash
shellArgs: ["-eo", "pipefail", "-c"]
output: show # show / hide / strip_refreshing / filter_regex
環境変数設定
steps:
- env:
name: AWS_REGION
value: "ap-northeast-1"
- env:
name: ENVIRONMENT
command: 'basename $(pwd)'
- multienv:
command: ./scripts/generate-vars.sh
output: hide
8.3 組み込み環境変数
| 変数名 | 説明 |
|---|---|
WORKSPACE | Terraform ワークスペース名 |
DIR | プロジェクトディレクトリ絶対パス |
PLANFILE | plan ファイル出力パス |
SHOWFILE | show ファイル出力パス |
BASE_REPO_NAME / BASE_REPO_OWNER | ベースリポジトリ情報 |
HEAD_REPO_NAME / HEAD_REPO_OWNER | ヘッドリポジトリ情報 |
HEAD_BRANCH_NAME / BASE_BRANCH_NAME | ブランチ情報 |
HEAD_COMMIT | コミット SHA |
PROJECT_NAME | プロジェクト名 |
PULL_NUM / PULL_URL / PULL_AUTHOR | PR 情報 |
USER_NAME | コマンド実行者 |
COMMENT_ARGS | 追加引数 |
ATLANTIS_TERRAFORM_VERSION | Terraform バージョン |
8.4 実践的なワークフロー例
Terragrunt 連携
workflows:
terragrunt:
plan:
steps:
- env:
name: TERRAGRUNT_TFPATH
command: 'echo "terraform${ATLANTIS_TERRAFORM_VERSION}"'
- run: terragrunt plan -input=false -out=$PLANFILE
apply:
steps:
- env:
name: TERRAGRUNT_TFPATH
command: 'echo "terraform${ATLANTIS_TERRAFORM_VERSION}"'
- run: terragrunt apply $PLANFILE
tflint バリデーション
workflows:
validated-plan:
plan:
steps:
- init
- run:
command: tflint --init && tflint
output: show
- plan
Infracost コスト見積もり
workflows:
with-cost-estimate:
plan:
steps:
- init
- plan
- run:
command: |
infracost breakdown --path=$PLANFILE \
--format=json --out-file=/tmp/infracost.json
infracost output --path=/tmp/infracost.json \
--format=github-comment --out-file=/tmp/infracost-comment.md
cat /tmp/infracost-comment.md
output: show
9. Autoplan と Automerge
9.1 Autoplan
Autoplan は PR 作成時・コミットプッシュ時に自動で terraform plan を実行する。
アルゴリズム:
- 変更ファイルを検出
.tfファイルをフィルタ- 該当ディレクトリを特定
modules/配下でなければ plan 実行modules/配下の場合、親ディレクトリにmain.tfがあれば親で plan
# サーバーレベル制御
atlantis server --autoplan-file-list="**/*.tf,**/*.tfvars"
atlantis server --disable-autoplan
atlantis server --disable-autoplan-label="no-autoplan"
atlantis server --autoplan-modules=true
9.2 Automerge
全プロジェクトの apply 成功後に PR を自動マージ:
version: 3
automerge: true
delete_source_branch_on_merge: true
10. ロック機構
10.1 目的
- State 一貫性保護: apply は PR マージ前に実行されるため、ロックで他の PR からの変更を防止
- Plan 有効性保証: 他の PR の apply による plan 無効化を防止
10.2 粒度
ロックは ディレクトリ + ワークスペース 単位。リポジトリ全体ではない。
10.3 ライフサイクル
- PR マージ/クローズ → 自動解除
atlantis unlockコメント → 手動解除- Web UI → "Discard Plan and Unlock"
10.4 Terraform State ロックとの関係
| 項目 | Atlantis ロック | Terraform State ロック |
|---|---|---|
| 粒度 | ディレクトリ + ワークスペース | State ファイル |
| 目的 | PR 間の競合防止 | 同時実行防止 |
| スコープ | PR ライフサイクル | コマンド実行中 |
| 保存先 | BoltDB / Redis | State Backend |
10.5 Redis 分散ロック
atlantis server \
--locking-db-type=redis \
--redis-host="redis.example.com" \
--redis-port=6379 \
--redis-password="your-redis-password" \
--redis-tls-enabled=true
11. コマンドリファレンス
| コマンド | 説明 |
|---|---|
atlantis plan | 全プロジェクトの plan |
atlantis plan -d <dir> | 特定ディレクトリの plan |
atlantis plan -p <project> | 特定プロジェクトの plan |
atlantis plan -w <workspace> | 特定ワークスペースの plan |
atlantis plan -- -var="key=value" | 追加引数付き plan |
atlantis apply | 全プロジェクトの apply |
atlantis apply -d <dir> | 特定ディレクトリの apply |
atlantis apply -p <project> | 特定プロジェクトの apply |
atlantis unlock | 全ロック解除 |
atlantis import <addr> <id> | リソースインポート |
atlantis state rm <addr> | State からリソース削除 |
atlantis approve_policies | ポリシー違反承認 |
atlantis version | バージョン表示 |
チームベースの制限
atlantis server --gh-team-allowlist="platform-team:plan,platform-team:apply,dev-team:plan"
12. Apply 要件とアクセス制御
12.1 要件の種類
| 要件 | 説明 |
|---|---|
| approved | PR が承認済み |
| mergeable | PR がマージ可能 |
| undiverged | ベースブランチから分岐なし |
12.2 設定方法
# repos.yaml
repos:
- id: /.*/
plan_requirements: [approved]
apply_requirements: [approved, mergeable]
import_requirements: [approved]
# atlantis.yaml (repos.yaml で allowed_overrides に含まれている場合のみ)
version: 3
projects:
- dir: .
apply_requirements: [approved, mergeable, undiverged]
12.3 重要な注意点
apply 要件が満たされると、PR にコメントできる全ユーザーが atlantis apply を実行可能。 より厳格な制御には:
atlantis server --gh-team-allowlist="infra-team:apply,dev-team:plan"
13. ポリシーチェック (Conftest 連携)
13.1 概要
Conftest (OPA ベース) と統合して plan 結果をポリシーチェック。セキュリティリスクや非準拠リソースを plan 段階で検出・ブロック。
13.2 セットアップ
atlantis server --enable-policy-checks
# repos.yaml
policies:
owners:
users: [policy-admin]
teams: [security-team]
approve_count: 1
policy_sets:
- name: security-policies
path: /opt/atlantis/policies/security/
source: local
owners:
users: [security-lead]
teams: [security-team]
- name: cost-policies
path: /opt/atlantis/policies/cost/
source: local
approve_count: 2
prevent_self_approve: true
13.3 Rego ポリシー例
null_resource 使用禁止:
package main
deny[msg] {
resource := input.resource_changes[_]
resource.type == "null_resource"
resource.change.actions[_] == "create"
msg := sprintf("null_resource の作成は禁止: %s", [resource.address])
}
必須タグの強制:
package main
required_tags := {"Environment", "Team", "CostCenter"}
deny[msg] {
resource := input.resource_changes[_]
resource.change.actions[_] == "create"
tags := object.get(resource.change.after, "tags", {})
missing := required_tags - {key | tags[key]}
count(missing) > 0
msg := sprintf("リソース %s に必須タグがありません: %v", [resource.address, missing])
}
インスタンスタイプ制限:
package main
allowed_instance_types := {"t3.micro", "t3.small", "t3.medium", "t3.large", "m5.large", "m5.xlarge"}
deny[msg] {
resource := input.resource_changes[_]
resource.type == "aws_instance"
resource.change.actions[_] == "create"
not allowed_instance_types[resource.change.after.instance_type]
msg := sprintf("インスタンスタイプ '%s' は許可されていません", [resource.change.after.instance_type])
}
13.4 違反時のワークフロー
- plan 完了後に自動ポリシーチェック
- 違反がある場合、PR コメントで報告
- 違反がある限り apply 不可
- コード修正 or
atlantis approve_policiesで承認
14. Pre/Post ワークフローフック
14.1 概要
メインワークフロー前後に実行されるスクリプト。出力は PR コメントに非表示。
repos:
- id: /.*/
pre_workflow_hooks:
- run: ./scripts/generate-atlantis-config.sh
description: "Dynamic config generation"
commands: plan
post_workflow_hooks:
- run: ./scripts/notify-completion.sh
commands: apply
14.2 利用可能な環境変数
BASE_REPO_NAME, BASE_REPO_OWNER, HEAD_BRANCH_NAME, HEAD_COMMIT, PULL_NUM, PULL_URL, PULL_AUTHOR, DIR, USER_NAME, COMMAND_NAME, OUTPUT_STATUS_FILE 等
14.3 フック失敗時
atlantis server --fail-on-pre-workflow-hook-error # 失敗時にワークフロー停止
15. Terraform Cloud / Enterprise 連携
15.1 モード
- リモート State ストレージ (無料): TFC を State 保存先として使用
- リモート実行 (有料): plan/apply を TFC/TFE で実行
15.2 設定
atlantis server \
--tfe-token="your-terraform-cloud-token" \
--gh-user="atlantis-bot" \
--gh-token="ghp_xxxxxxxxxxxxxxxxxxxx" \
--repo-allowlist="github.com/myorg/*"
# プライベート TFE
atlantis server --tfe-hostname="tfe.internal.example.com"
# ローカル実行モード
atlantis server --tfe-local-execution-mode
15.3 制限事項
- カスタム
runステップで plan/apply を置き換え不可 - Team Token に "Manage Workspaces" 権限が必要
16. API エンドポイント
16.1 認証付きエンドポイント
atlantis server --api-secret="your-api-secret"
# Plan
curl -X POST https://atlantis.example.com/api/plan \
-H "X-Atlantis-Token: your-api-secret" \
-H "Content-Type: application/json" \
-d '{"Repository":"myorg/myrepo","Ref":"feature","Type":"Github","PR":42}'
# Apply
curl -X POST https://atlantis.example.com/api/apply \
-H "X-Atlantis-Token: your-api-secret" \
-H "Content-Type: application/json" \
-d '{"Repository":"myorg/myrepo","Ref":"feature","Type":"Github","PR":42}'
16.2 パブリックエンドポイント
| エンドポイント | 説明 |
|---|---|
GET /api/locks | アクティブロック一覧 |
GET /status | サーバーステータス |
GET /healthz | ヘルスチェック |
GET /debug/pprof | プロファイリング |
17. セキュリティ
17.1 主要な脅威
- 悪意のある Terraform コード:
externalデータソース等で plan 時に任意コード実行 - Local-exec プロビジョナー: 認証情報の外部送信
- atlantis.yaml の悪用: カスタムワークフロー経由の任意コマンド実行
- 未認証 Webhook: 偽リクエストによる plan/apply トリガー
17.2 推奨対策
# repos.yaml - セキュアな設定
repos:
- id: /.*/
allow_custom_workflows: false
allowed_overrides: []
apply_requirements: [approved, mergeable]
policy_check: true
# 必須セキュリティ設定
atlantis server \
--gh-webhook-secret="$SECRET" \
--allow-fork-prs=false \
--web-basic-auth=true \
--web-username="admin" \
--web-password="$(openssl rand -base64 32)" \
--ssl-cert-file="/path/to/cert.pem" \
--ssl-key-file="/path/to/key.pem" \
--var-file-allowlist="/allowed/path"
17.3 セキュリティチェックリスト
| 項目 | 優先度 |
|---|---|
| Webhook Secret 設定 | 必須 |
--repo-allowlist 設定 (* 禁止) | 必須 |
--allow-fork-prs=false | 必須 |
allow_custom_workflows: false | 高 |
| SSL/TLS 有効化 | 高 |
| Web UI 認証 | 高 |
| Egress 制限 | 高 |
| ポリシーチェック有効化 | 中 |
18. 高度な設定と運用パターン
18.1 実行順序の制御
version: 3
abort_on_execution_order_fail: true
projects:
- name: vpc
dir: infrastructure/vpc
execution_order_group: 0
- name: subnets
dir: infrastructure/subnets
execution_order_group: 1
depends_on: [vpc]
- name: ecs-cluster
dir: infrastructure/ecs
execution_order_group: 2
depends_on: [subnets]
18.2 正規表現コマンド
atlantis server --enable-regexp-cmd
# PR コメント例:
# atlantis plan -p "networking-.*"
# atlantis apply -p "dev-.*"
18.3 複数 Atlantis サーバー構成
# Server A (開発用)
atlantis server --vcs-status-name="atlantis/dev"
# Server B (本番用)
atlantis server --vcs-status-name="atlantis/prod"
18.4 OpenTofu サポート
atlantis server --default-tf-distribution=opentofu
version: 3
projects:
- dir: .
terraform_distribution: opentofu
terraform_version: "1.6.0"
18.5 Markdown テンプレートカスタマイズ
atlantis server --markdown-template-overrides-dir="/etc/atlantis/templates/"
18.6 メトリクス
atlantis server --stats-namespace="atlantis"
19. トラブルシューティング
19.1 よくある問題
| 問題 | 確認事項 |
|---|---|
| Webhook が届かない | サーバーアクセス可能性、URL、Secret 一致、ファイアウォール |
| Plan が自動実行されない | --repo-allowlist、--autoplan-file-list、--disable-autoplan |
| Apply が拒否される | PR 承認状態、マージ可能性、ポリシー違反 |
| ロック競合 | atlantis unlock または Web UI で解除 |
| バージョン不一致 | terraform_version、--tf-download=true |
| 認証エラー | トークン有効期限、権限スコープ |
19.2 デバッグ
atlantis server --log-level=debug
atlantis server --enable-profiling-api # http://atlantis:4141/debug/pprof
19.3 ヘルスチェック
curl https://atlantis.example.com/healthz
curl https://atlantis.example.com/status
# {"shutting_down":false,"in_progress_operations":2,"version":"v0.28.0"}
20. まとめ
20.1 主要な利点
| 利点 | 説明 |
|---|---|
| PR ベースのワークフロー | 変更の可視性とトレーサビリティ向上 |
| 自動化 | plan 自動実行で即座に確認 |
| セキュリティ | 認証情報の一元管理 |
| コラボレーション | plan 結果の PR コメント共有 |
| ロック機構 | 並行変更による State 破損防止 |
| ポリシー強制 | Conftest でガバナンス確保 |
| 柔軟性 | カスタムワークフロー対応 |
| マルチ VCS | GitHub/GitLab/Bitbucket/Azure DevOps/Gitea |
20.2 ベストプラクティス
- Webhook Secret を必ず設定
--repo-allowlistを適切に設定 (*禁止)- カスタムワークフロー許可を制限
- apply 要件に最低
approvedを設定 - 永続ストレージ確保 (StatefulSet + PVC)
- ポリシーチェックを活用
- VCS トークンの定期ローテーション
/healthzと Prometheus メトリクスでモニタリング- Docker イメージバージョン固定 (
:latest禁止)
20.3 参考リンク
| リソース | URL |
|---|---|
| 公式サイト | https://www.runatlantis.io |
| GitHub リポジトリ | https://github.com/runatlantis/atlantis |
| Helm Chart | https://github.com/runatlantis/helm-charts |
| CNCF Slack (#atlantis) | https://cloud-native.slack.com |
| Terraform Module (AWS) | https://registry.terraform.io/modules/terraform-aws-modules/atlantis/aws |
本ドキュメントは Atlantis v0.28.x 時点の情報に基づいている。最新の情報は公式ドキュメント (https://www.runatlantis.io/docs) を参照のこと。