💭
Terraform初期設定の備忘録
新規開発でのTerraformの初期設定に手こずったのでまとめておきます。
目標
1. tfstateファイルをS3に保存する設定
2. 静的コンテンツ用のS3の作成
3. CloudFrontの作成
ディレクトリ構成
全ての設定を一つのファイルに書くことも可能ですが、可読性とメンテナンス性を考慮して、リソースごとにファイルを分けています。
terraform/
├── .gitignore/
├── common/
│ ├── cloudfront.tf
│ ├── s3.tf
│ └── variables.tf
└── envs/
├── dev/
│ └── main.tf
├── stg/
│ └── main.tf
└── prd/
└── main.tf
開発が進むにつれて、必要に応じて新たなAWSリソースの設定を追加していきますが、初期設定としては上記で問題なかったです。
1. tfstateファイルをS3に保存する設定
S3バケットを手動で作成
tfstateファイル(Terraformの状態ファイル)の保存先であるバケットは事前に存在する必要があるため、ここで使用するS3バケットはAWSのマネージメントコンソールから手動で作成します。
AWS Providerの設定
AWSをTerraformで使用するための設定です。
手動で作成したS3バケットはここで保存先に設定されます。
envs/dev/main.tf
# バックエンドとしてS3を選択。Terraformの状態管理ファイル(tfstate)がS3バケットに保存される。
terraform {
backend "s3" {
bucket = "手動で作成したS3バケット名"
key = "terraform.tfstate"
region = "ap-northeast-1"
}
}
# AWSをクラウドプロバイダとして指定。
provider "aws" {
region = "ap-northeast-1"
}
# commonモジュールを作成。設定は「../../common」に格納されたTerraform設定ファイルで定義される。
module "common" {
source = "../../common"
env_name = "dev" # 変数としてモジュール内部で利用できる。環境に合わせてstg,prdに変更。
}
※おまけ
.gitignore
.terraform # ローカルでの「terraform init」で生成されるファイル
terraform.tfstate.d # tfstateファイルは機密情報を含む可能性あり
2. 静的コンテンツ用のS3の作成
s3.tf
resource "aws_s3_bucket" "for_client" {
bucket_prefix = "何らかのプレフィックス" # 指定したプレフィックスで始まるユニークなバケット名を作成
}
# バケットに対するアクセスを制御するためのポリシーを定義
resource "aws_s3_bucket_policy" "for_client" {
bucket = aws_s3_bucket.for_client.id
policy = data.aws_iam_policy_document.for_client.json
}
# AWS IAMポリシーのJSONドキュメントを作成する
data "aws_iam_policy_document" "for_client" {
statement {
sid = "Allow CloudFront" # ポリシーステートメントの識別子
effect = "Allow" # ステートメントで許可されるアクション
# アクセス元の設定
principals {
type = "AWS"
identifiers = [aws_cloudfront_origin_access_identity.for_client.iam_arn] # CloudFrontに適用
}
# バケットに対して制御するアクションを設定
actions = ["s3:GetObject"] # オブジェクトの読み取りアクション。
# アクセス先の設定
resources = [
"${aws_s3_bucket.for_client.arn}/*" # 作成したバケット内のすべてのオブジェクトに適用
]
}
}
新しいS3バケットを作成し、そのバケットにCloudFrontを通じたオブジェクト取得のみを許可する設定をしています。
3. CloudFrontの作成
ちょっと長いです。
cloudfront.tf
resource "aws_cloudfront_distribution" "cf" {
# Route53でCloudFrontをエイリアス先に設定することで、既に管理しているドメインでCloudFrontにアクセスできる
# aliases = "ドメイン名" # 未設定なのでコメントアウト
# 配信のコンテンツ元(ここではS3バケット)を指定
origin {
domain_name = aws_s3_bucket.for_client.bucket_regional_domain_name
origin_id = aws_s3_bucket.for_client.id
s3_origin_config {
origin_access_identity = aws_cloudfront_origin_access_identity.for_client.cloudfront_access_identity_path
}
}
enabled = true # 配信を有効
is_ipv6_enabled = true # IPv6を有効
default_root_object = "index.html" # デフォルトのルートオブジェクト
# デフォルトのキャッシュ動作を定義
default_cache_behavior {
allowed_methods = ["GET", "HEAD"]
cached_methods = ["GET", "HEAD"]
target_origin_id = aws_s3_bucket.for_client.id
# リクエストと一緒にオリジンサーバー(S3バケット)に送る情報を指定
forwarded_values {
query_string = false
cookies {
forward = "none"
}
}
viewer_protocol_policy = "redirect-to-https" # HTTPS通信のみ許可する。
# キャッシュのTTL設定
min_ttl = 0 # 0s
default_ttl = 86400 # Cache-Control or Expires がリクエストのヘッダーに無い時のデフォルトのTTL。1日。
max_ttl = 31536000 # 365日
}
# 地理的な制限を設定。noneなので制限なし。
restrictions {
geo_restriction {
restriction_type = "none"
}
}
# SSL証明書の設定
viewer_certificate {
cloudfront_default_certificate = true # CloudFrontが提供するデフォルトのSSL証明書を使用
# ACMで作成した証明書を使用する。その場合cloudfront_default_certificateはfalseにする。
# acm_certificate_arn = aws_acm_certificate.cert.arn # 未設定なのでコメントアウト
ssl_support_method = "sni-only"
minimum_protocol_version = "TLSv1"
}
# カスタムエラーレスポンス("403: Forbidden"の時に"/"に200で飛ばす)
custom_error_response {
error_code = 403 # Cloudfront→S3の構成で存在しないファイルパスを叩くと403エラー
response_code = 200
response_page_path = "/"
}
}
# CloudFrontがオリジン(S3バケット)にアクセスするための特別なユーザーを作成
resource "aws_cloudfront_origin_access_identity" "for_client" {}
感想
Terraformはまだまだ設定することはありますが、とりあえず「デプロイできる環境を構築する」ことに必要な設定を今回深掘りできてよかったです。
参考
Discussion