はじめに
こんにちは、こちらはラクスパートナーズ AdventCalender 2025 10日目の記事です。
タイトルの通り、インターネットに出られない環境下でTerraformを動かす環境を構築しましたが、初めての経験だったため記事として残しておこうと思います。
同じような要件が求められている方にとって、少しでも参考になれば嬉しいです。
求められた要件と制約
-
インターネット非接続環境でTerraformを実行する必要がある
最重要の要件として、Terraformの実行環境をインターネットに一切接続してはならないことが求められた。- NATGatewayなし
- InternetGatewayなし
- 外部サイトへのoutobound通信禁止
- TerraformRegistryへのアクセスも禁止
そのため、通常の
terraform init/terraform applyで前提となる外部通信がほとんど封じられることになる。 -
Terraformで管理するのは、AWS QuickSightのリソースとSnowflakeのリソース
Quicksightのユーザー、SnowflakenoロールやユーザーなどをTerraformで管理する必要があった。そのため、Terraformの実行環境からAWSおよびSnowflakeへの接続が必要となる。
最終的に構築したアーキテクチャ
最終的には、TerraformをAWS VPCのプライベートサブネット内のCodeBuild上で実行し、外部には一切インターネット接続しない構成に落ち着いた。
採用した構成のポイント
- CodeBuildはPrivatelinkが構築されているVPC上のサブネットで動かす
- 実行環境は完全にプライベートサブネット内
- NATGatewayやインターネットアクセスは配置しない
- Terraformプロバイダはオフラインでインストール
- providerのバイナリはインターネットアクセスが可能な環境で事前にダウンロードし、それをS3バケットにアップロード
- CodeBuild環境にコピーし、設定ファイルにおいて
provider_installationを変更することでローカルファイルからインストール(参考)
- Provider APIへの通信はすべてVPC Endpoint経由
- QuickSight用のVPCE、snowflake用のVPCE(Privatelink)を利用することで、実行時にパブリックインターネットに出ることなくセキュアにapplyが可能
- CodePipeline + CodeBuildで閉域内CI/CDを構築
- インターネットに依存せずVPC内でパイプラインが完結
候補となったアプローチ
-
CI/CD環境にGitHub Actionsを利用する
Code/Pipelineを用いなくとも、GitHub ActionsでTerraform applyをしようという選択肢。
勿論技術的には容易なのだが、Terraformのコードを管理しているGitHubリポジトリがオンプレミスのサーバーにホスティングしているGithub Enterprise Serverであり、Terraform適用環境(AWS VPCやSnowflake)へのポート解放などがすぐには準備ができなかったために、不採用とした。 -
プロバイダのインストールはインターネット経由で行う
Snowflakeへの接続はPrivatelink経由だが、プロバイダのインストール(terraform init)時のみ、インターネット経由で行うという選択肢。(要件を一部見直す択)
CodeBuildをNATGateway+InternetGatewayが設置してあるサブネット上で実行すれば可能であるが、SnowflakeへのPrivatelinkが構築してあるVPCへの接続設定をする必要があり、その手間を考え不採用とした。(PrivatelinkのVPCはすでに構築済みで、新たにNGWをアタッチすることはできない)
ハマったポイントと対処法
CodePipelineのソースをどう取得するか
CodePipelineの実行のソースコードをどこから取得するかという問題。
ソースコード自体はGitHubで管理しているが、前述したようにGitHub Enterprise Severで運用しており、CodePipelineとGitHubを直接接続するのにはかなりの越えるべき障壁があった。
GitHubの変更をキャッチしてCodeCommitにリポジトリをクローンすることも考えたが、それをするためには結局GitHubActionsを利用する必要があり、GitHubActions実行環境からAWSへの通信の開通、ランナーの用意に手間取ると判断し断念。
ワークアラウンドとして、ローカルからコードをzip化してS3にコピー → S3のPutObjectイベントをトリガーとしてCodePipelineを起動するという方式を採った。
(もちろん、GitHubとAWSとの通信が開通した際にはアップデートする予定)
context deadline exceeded
Terraform plan, apply時にはcontext deadline exceededというエラーが発生した。
Snowflakeコンソールからクエリ履歴を確認したところ、正常にクエリは発行されているようだったので、
実行環境からSnowflakeへの接続時のタイムアウトが原因だろうと仮説を立て試行錯誤した。
結果、providerブロックのtimeoutの設定を引き伸ばすことで解消した。
provider "snowflake" {
...
..
.
client_timeout = 300
}
雑記
これまで経験してこなかった環境下での構築でしたが、不便な中で試行錯誤することで学べることがかなり多く、貴重な経験となりました。特にTerraformの各コマンドの動作原理を理解できたのはなかなか得難い知識だったかと思います。
今回の構築の中で幸運だったのは、QuickSight用のエンドポイントが用意されていたこと。これがなければQuicksightのAPIを叩くためにパブリックインターネットに出る必要があったが、QuickSight用のVPCエンドポイントはどうやら最近まで用意されていなかったらしい。。