Contents
CTS の概要と役割
CTS は Consul エージェントが監視するサービスカタログの 変更イベント(追加・削除・タグ変化) をトリガーにし、事前に定義した Terraform タスクを自動的に apply します。これにより、ネットワーク機器やクラウドセキュリティグループといったインフラ資産が コードベースで即時更新 され、設定ドリフトの蓄積を防げます。
- シンプルなデータフロー:
Consul → CTS (watch) → Terraform (runbook) - リアルタイム性:Consul のブロッキングクエリを利用した pull 型 監視で、数秒以内に変更が反映。
- 汎用性:AWS SG、GCP ファイアウォール、オンプレススイッチ等、Terraform が管理できるすべてのリソースに適用可能。
ポイント – CTS は「サービス駆動型インフラ更新(Service‑Driven IaC)」を実現するハブであり、Day‑2 オペレーションの自動化基盤として位置付けられます。
前提条件とインストール手順
このセクションでは本番環境に CTS をデプロイするために必要な OS・バージョン要件から、各バイナリの取得・配置までをステップごとに解説します。
必須環境(導入前に確認すべきポイント)
| 項目 | 推奨条件 | 確認方法 |
|---|---|---|
| OS | Ubuntu 22.04 LTS、CentOS 8 以降、または macOS (Intel / Apple Silicon) | uname -a |
| Consul | 1.20 系列以上(最新はリリース API が返す latest_version) |
curl -s https://api.releases.hashicorp.com/v1/releases/consul | jq -r '.versions[] | select(.status=="stable") | .version' | sort -V | tail -n1 |
| CTS | 0.8 系列以上(最新は同上) | curl -s https://api.releases.hashicorp.com/v1/releases/consul-terraform-sync | jq -r '.versions[] | select(.status=="stable") | .version' | sort -V | tail -n1 |
| Terraform CLI | 1.7 系列以上(最新は同上) | curl -s https://api.releases.hashicorp.com/v1/releases/terraform | jq -r '.versions[] | select(.status=="stable") | .version' | sort -V | tail -n1 |
注記 – バージョン番号をハードコードせず、上記 API で取得した文字列をスクリプトに埋め込むことで常に最新リリースをインストールできます。
Consul クラスタの構築(最小構成例)
-
サーバーノードのバイナリ取得
bash
CONSUL_VER=$(curl -s https://api.releases.hashicorp.com/v1/releases/consul \
| jq -r '.versions[] | select(.status=="stable") | .version' \
| sort -V | tail -n1)
curl -fsSL "https://releases.hashicorp.com/consul/${CONSUL_VER}/consul_${CONSUL_VER}_linux_amd64.zip" -o consul.zip
unzip consul.zip && sudo mv consul /usr/local/bin/ -
サーバー設定(
server.hcl)
hcl
server = true
bootstrap_expect = 3
data_dir = "/opt/consul"
bind_addr = "0.0.0.0"
client_addr = "127.0.0.1"
ui = true -
systemd ユニット作成(
/etc/systemd/system/consul.service)
ini
[Unit]
Description=Consul Agent
After=network-online.target
[Service]
ExecStart=/usr/local/bin/consul agent -config-dir=/etc/consul.d
Restart=on-failure
LimitNOFILE=65536
[Install]
WantedBy=multi-user.target
- クライアントノードは
server = falseに変更し、retry_joinでサーバー IP を列挙すれば自動参加します。
詳細な構成例は HashiCorp 公式ドキュメント(Consul クラスタのセットアップ)をご参照ください。
Terraform CLI のインストール
|
1 2 3 4 5 6 7 |
TF_VER=$(curl -s https://api.releases.hashicorp.com/v1/releases/terraform \ | jq -r '.versions[] | select(.status=="stable") | .version' \ | sort -V | tail -n1) curl -fsSL "https://releases.hashicorp.com/terraform/${TF_VER}/terraform_${TF_VER}_linux_amd64.zip" -o terraform.zip unzip terraform.zip && sudo mv terraform /usr/local/bin/ terraform version # 例: Terraform v1.7.x |
CTS バイナリ取得と配置
|
1 2 3 4 5 6 7 8 |
CTS_VER=$(curl -s https://api.releases.hashicorp.com/v1/releases/consul-terraform-sync \ | jq -r '.versions[] | select(.status=="stable") | .version' \ | sort -V | tail -n1) curl -fsSL "https://releases.hashicorp.com/consul-terraform-sync/${CTS_VER}/consul-terraform-sync_${CTS_VER}_linux_amd64.zip" -o cts.zip unzip cts.zip && sudo mv consul-terraform-sync /usr/local/bin/ chmod +x /usr/local/bin/consul-terraform-sync cts version # インストール確認 |
cts.hcl 設定ファイルの解説
CTS は単一の HCL ファイルで Consul 接続情報・Terraform 実行環境・ロギング を一元管理します。以下は実務で推奨するベースラインです(各項目の意味と注意点を併記)。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
# /etc/cts/cts.hcl consul { address = "http://127.0.0.1:8500" token = "<CONSUL_ACL_TOKEN>" # 最小権限は `read` (サービスカタログ閲覧) namespace = "default" # 使用している場合は明示 } terraform { working_dir = "/opt/cts/tasks" # タスク(runbook)格納ディレクトリ binary_path = "/usr/local/bin/terraform" backend_config = { bucket = "my-cts-state" key = "global/cts.tfstate" region = "ap-northeast-1" } # S3 バックエンド例(ロックは DynamoDB が必須) } logging { level = "INFO" # 運用時は INFO、デバッグが必要なときだけ DEBUG format = "json" output = "/var/log/cts.log" } /* オプションパラメータ */ disable_telemetry = false # HashiCorp Telemetry の有効化 / 無効化 sync_interval = "30s" # カタログポーリング間隔(デフォルトは 10s) |
環境変数プレフィックスとサンプル
CTS が検知したサービス情報は CONSUL_SERVICE_ プレフィックス付きの環境変数として Terraform に渡されます。代表的な変数は以下の通りです(実際に使用できるキーは Consul のタグやメタデータに依存します)。
| 変数名 | 内容例 | 使用例 |
|---|---|---|
CONSUL_SERVICE_NAME |
payment-api |
${env.CONSUL_SERVICE_NAME} |
CONSUL_SERVICE_ID |
payment-api-1a2b3c |
${env.CONSUL_SERVICE_ID} |
CONSUL_SERVICE_ADDRESS |
10.0.12.34 |
${env.CONSUL_SERVICE_ADDRESS} |
CONSUL_SERVICE_PORT |
8080 |
${env.CONSUL_SERVICE_PORT} |
CONSUL_SERVICE_TAGS |
["v1","internal"] |
文字列操作で分解可能 |
Terraform 側の利用例(外部データソース)
|
1 2 3 4 5 6 7 8 |
data "external" "svc_info" { program = ["bash", "-c", <<EOT echo '{"name":"${env.CONSUL_SERVICE_NAME}","address":"${env.CONSUL_SERVICE_ADDRESS}","port":${env.CONSUL_SERVICE_PORT}}' EOT ] } |
ベストプラクティス – 環境変数は文字列として渡されるため、数値が必要な箇所は
tonumber()関数で型変換してください。
タスク(runbook)作成と実装例
CTS がトリガーした際に実行する Terraform コードを タスク と呼びます。以下では AWS Security Group のインバウンドルール自動更新を題材に、ディレクトリ構造・変数宣言・出力定義までを具体的に示します。
ディレクトリ構成とベストプラクティス(導入)
|
1 2 3 4 5 6 7 |
/opt/cts/tasks/ └─ aws_sg_sync/ ├─ main.tf # リソース本体 ├─ variables.tf # 外部入力パラメータ ├─ outputs.tf # 他タスクやログへ渡す情報 └─ README.md # タスクの概要・使用方法 |
- モジュール化:複数サービスが同一 SG を共有するケースは、
for_eachで動的にルールを生成すると管理が楽になります。 - 状態分離:
working_dir配下にタスクごとのサブディレクトリを作ることで、Terraform のロック競合を防げます。
variables.tf(必須変数)
|
1 2 3 4 5 |
variable "sg_id" { description = "対象の AWS Security Group ID" type = string } |
ポイント –
sg_idは Consul のサービスタグから自動抽出することも可能です。その場合は CTS 側で環境変数CONSUL_SERVICE_TAGSをパースし、-var 'sg_id=...'オプションで渡します。
main.tf(外部データとリソース定義)
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
# 外部データソースで Consul から注入された環境変数を取得 data "external" "svc" { program = ["bash", "-c", <<EOT echo '{"name":"${env.CONSUL_SERVICE_NAME}","address":"${env.CONSUL_SERVICE_ADDRESS}","port":${env.CONSUL_SERVICE_PORT}}' EOT ] } resource "aws_security_group_rule" "allow_service" { type = "ingress" from_port = data.external.svc.result.port to_port = data.external.svc.result.port protocol = "tcp" security_group_id = var.sg_id cidr_blocks = ["${data.external.svc.result.address}/32"] description = "Allow ${data.external.svc.result.name}" } |
outputs.tf(実行結果の可視化)
|
1 2 3 4 5 |
output "rule_id" { description = "作成された SG ルールの ID" value = aws_security_group_rule.allow_service.id } |
タスク登録と動作確認(導入)
cts.hclのterraform.working_dirに上記ディレクトリを配置。- CTS を再起動または
systemctl reload cts.serviceで設定反映。 - Consul に新規サービスが登録されると、CTS が環境変数を注入し Terraform が自動的に
applyを実行します。
実際のログは
/var/log/cts.log(JSON)に出力され、rule_idはoutputs.jsonとして保存されます。
運用・トラブルシューティング
CTS の安定運用には デーモン化・ロギング・状態管理 が鍵です。ここでは推奨の systemd ユニット、ログ監視ポイント、および典型的なエラーと対処法をまとめます。
Systemd でのデーモン化(導入)
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
# /etc/systemd/system/cts.service [Unit] Description=Consul Terraform Sync Service After=network-online.target consul.service Wants=consul.service [Service] ExecStart=/usr/local/bin/consul-terraform-sync -config /etc/cts/cts.hcl Restart=on-failure LimitNOFILE=65536 Environment="CONSUL_HTTP_TOKEN=<YOUR_ACL_TOKEN>" # 必要に応じて追加環境変数をここで定義 [Install] WantedBy=multi-user.target |
|
1 2 3 4 |
sudo systemctl daemon-reload sudo systemctl enable --now cts.service sudo journalctl -u cts -f # リアルタイムログ確認 |
ログのポイントと期待結果(導入)
| レベル | 代表的メッセージ | 正常時に見るべき情報 |
|---|---|---|
| INFO | Watching Consul catalog for changes... |
カタログ監視開始 |
| DEBUG (必要時) | Detected service change: payment-api |
変更検知 → Running Terraform apply が続く |
| ERROR | Failed to run terraform: exit status 1 |
エラー詳細はスタックトレースと terraform.log に出力 |
JSON ログ は Loki / Elasticsearch 等の集中管理ツールで検索しやすく、アラート設定も容易です。
典型的なエラーと解決策(導入)
| エラー | 原因例 | 修正手順 |
|---|---|---|
Consul 接続失敗 (dial tcp ...: connection refused) |
cts.hcl の address が誤っている、ACL トークンが無効 |
正しい IP・ポートを指定し、トークンに read 権限が付与されているか確認 |
Terraform state 競合 (Lock already held) |
複数 CTS インスタンスが同一 working_dir を共有 |
各インスタンスごとに固有のサブディレクトリを割り当て、または S3 + DynamoDB のロックバックエンドへ切替 |
モジュール互換性 (required_version 不一致) |
CTS が参照する Terraform バイナリが古い | cts.hcl の binary_path を最新バージョンに更新し、terraform -version で確認 |
外部データ取得失敗 (external data source returned non‑JSON) |
環境変数名ミスや値が空文字列 | CONSUL_SERVICE_* 系のプレフィックスと正しい大文字・アンダースコアを使用しているか再確認 |
| Telemetry 無効化エラー | disable_telemetry = true が古いバージョンで未サポート |
HashiCorp のリリースノートで該当フラグの有無を確認し、必要なら削除 |
カタログ監視と変更検知フロー(導入)
- CTS 起動 →
consulブロックのエンドポイントへ blocking query を送信。 - Consul がインデックス番号 (
X-Consul-Index) を返し、変更があるたびに新しいインデックスで再度リクエスト。 - 変更を検知すると CTS は対象タスクの
terraform applyを非同期で実行し、結果をログとoutputs.jsonに書き込み。
即時性向上 が必要な場合は、Consul の
watch機能 (consul watch -type=services) と組み合わせて CTS にシグナル送信する構成も検討してください。
ブランド・商標ガイドライン(必読)
- 商標表記:HashiCorp は登録商標です。文中で初めて登場させる際は「HashiCorp®」または「HashiCorp (registered trademark)」と明記してください。
- ロゴ使用:HashiCorp のロゴを記事や資料に掲載する場合は、公式スタイルガイド(Brand Guidelines)に従い、色・サイズ・余白を遵守します。商用利用の場合は事前に書面で許可を取得してください。
- リンク表記:外部リファレンスは必ずフル URL を添えて、クリック可能なハイパーリンク形式で提供します(例:
https://developer.hashicorp.com/consul/docs)。
参考情報・公式リンク
| 内容 | URL |
|---|---|
| Consul ダウンロード & リリース API | https://releases.hashicorp.com/consul/ |
| CTS (Consul Terraform Sync) ドキュメント | https://developer.hashicorp.com/consul/docs/sync |
| Terraform インストールガイド | https://developer.hashicorp.com/terraform/downloads |
| HashiCorp 製品のブランド・ロゴ規定 | https://www.hashicorp.com/brand |
| Consul の ACL & トークン管理 | https://developer.hashicorp.com/consul/docs/security/acl |
最終チェック – 本稿掲載時点(2026‑06‑20)以降にバージョンが更新された場合は、上記リリース API を再度実行し、
CONSUL_VER,CTS_VER,TF_VERの変数を最新に置き換えてください。
まとめ
- CTS は Consul と Terraform の橋渡しであり、サービスカタログの変化をコードベースで即時反映させることでインフラの一貫性と運用負荷低減を実現します。
- バージョン管理は公式リリース API で自動取得し、ハードコーディングを避けて常に最新状態を保ちましょう。
- 設定ファイル (
cts.hcl) とタスク構成はベストプラクティスに沿って整理し、環境変数CONSUL_SERVICE_*の利用例を明示することで実装ミスを防げます。 - 運用時は systemd デーモン化・JSON ログ出力・状態ロックの分離が必須です。典型的なエラーと対処法を把握しておくと障害復旧が迅速になります。
- HashiCorp の商標・ロゴ使用は公式ガイドラインに従うことがライセンス遵守の基本です。
以上で、CTS を安全かつ効果的に導入・運用するための情報は網羅しました。質問や実装上の課題があれば、HashiCorp Community Forum も併せて活用してください。