本記事について
terraformを初心者がこなすためにつまづく点やどうするべきかといったポイントのメモ
対象
- UdemyでAWSについて学んだことのあるレベルを想定
- terraformは使ったことないけど、なんとなく概要はわかる。
本記事でやること
環境構築
STEP1 S3作る
STEP2 S3とCloudFront作る
環境
Mac OS 12.5 M2
terraformとは?
AWSに関しては、
AWSの設定書いて、terraform apply したら反映されるやつ。
インストール
dockerで構築するって手もあるが、tfenvのほうが楽そうだったのでtfenvを選択。
$ brew install tfenv
# バージョン確認
$ tfenv list-remote
# インストールでバージョン指定しなかったら失敗した。指定したら成功した。
$ tfenv install 1.2.8
$ terraform -v
AWSCLIもインストール
IAMでユーザー作ってaccess_keyを発行し、登録しておく。
以下のようにファイル作られていればOK
~$ cat .aws/config
[default]
region = ap-northeast-1
output = json
~$ cat .aws/credentials
[default]
aws_access_key_id = hogehoge
aws_secret_access_key = hogehoge
作業フォルダ作成
いろいろベストプラクティスなフォルダ構成の記事は探したが、
初学者に求められるフォルダ構成はシンプルさだけかなと思うので、めっちゃシンプルな構成にする。
共通化は考えない。
first-terraform(master)$ tree .
.
├── README.md
├── dev
│ ├── main.tf
│ ├── terraform.tfstate
│ └── terraform.tfstate.backup
└── docs
├── 00_command.md
├── 10_s3.md
└── 11_cloudfront.md
README.md このリポジトリでなにをする?とかをメモ
dev 作業フォルダ。prodを作る気はないが直下に作るのが嫌だったので。
dev/main.tf ここにterraformの中身書いていく。ファイル分割は必要に思えるまでしない。
docs 残しておくべきメモの量が多く、issueやPRだと管理しづらかったためドキュメントフォルダを作った。
git管理は作業ディレクトリ直下。
# Local .terraform directories
**/.terraform/*
# .tfstate files
*.tfstate
*.tfstate.*
# .tfvars files
*.tfvars
このgitignoreはどこかで拾った。
初期化
# devフォルダ内で実行する
# lockファイルとかができる。
terraform init
STEP1 S3作る
こうなった。
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "4.29.0"
}
}
required_version = "1.2.8"
}
provider "aws" {
profile = "default"
}
resource "aws_s3_bucket" "b" {
bucket = "teach-tf-test-bucket"
tags = {
Name = "teach-tf-test-bucket"
Environment = "Dev"
}
}
resource "aws_s3_bucket_ownership_controls" "b" {
bucket = aws_s3_bucket.b.id
rule {
object_ownership = "BucketOwnerEnforced"
}
}
resource "aws_s3_bucket_public_access_block" "b" {
bucket = aws_s3_bucket.b.id
block_public_acls = true
block_public_policy = true
ignore_public_acls = true
restrict_public_buckets = true
}
$ terraform fmt
$ terraform validate
Success! The configuration is valid.
# 確認
$ terraform plan
# 反映
$ terraform apply
公式のaws-get-startedを参考に書き換えている。
required_providersのawsのversionはterraform registryを見て最新を取得
https://registry.terraform.io/providers/hashicorp/aws/latest
required_versionはterraform -v
で出たやつ
providerの設定はローカルであればprofileに書いてあるやつそのまま使えばいいかなということで、profileから情報取得するようにした。
https://registry.terraform.io/providers/hashicorp/aws/latest/docs#shared-configuration-and-credentials-files
regionはprofileに記載されているので省略。
resourceの書き方
https://www.terraform.io/language/resources/syntax#resource-syntax
s3の設定は主にドキュメントを見ている。
ただしここに載っているサンプルの設定はコンソールで手動で設定するときの「推奨」の設定にはなっていない。
そこで推奨の設定になるようにサンプルとは一部を変更して設定した。
具体的には
- aws_s3_bucket_ownership_controls
- aws_s3_bucket_public_access_block
の2つ
terraform.tfstateについて
いろんな記事でterraform.tfstateはS3に配置することが推奨されている。
しかし、本記事においては環境は、「作ったら削除する」使い捨て環境なのでtfstateを管理する必要がない。そこでS3にアップロードしないようにしている。
STEP2 S3とCloudFront作る
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "4.29.0"
}
}
required_version = "1.2.8"
}
provider "aws" {
profile = "default"
}
resource "aws_s3_bucket" "b" {
bucket = "teach-tf-test-bucket"
tags = {
Name = "teach-tf-test-bucket"
Environment = "Dev"
}
}
resource "aws_s3_bucket_ownership_controls" "b" {
bucket = aws_s3_bucket.b.id
rule {
object_ownership = "BucketOwnerEnforced"
}
}
resource "aws_s3_bucket_public_access_block" "b" {
bucket = aws_s3_bucket.b.id
block_public_acls = true
block_public_policy = true
ignore_public_acls = true
restrict_public_buckets = true
}
resource "aws_s3_bucket_policy" "b" {
bucket = aws_s3_bucket.b.id
policy = data.aws_iam_policy_document.s3_cf_policy.json
}
data "aws_iam_policy_document" "s3_cf_policy" {
statement {
sid = "AllowCloudFrontServicePrincipalReadOnly"
effect = "Allow"
principals {
type = "Service"
identifiers = ["cloudfront.amazonaws.com"]
}
actions = ["s3:GetObject"]
resources = ["${aws_s3_bucket.b.arn}/*"]
condition {
test = "StringEquals"
variable = "aws:SourceArn"
values = [aws_cloudfront_distribution.s3_distribution.arn]
}
}
}
resource "aws_cloudfront_distribution" "s3_distribution" {
origin {
domain_name = aws_s3_bucket.b.bucket_regional_domain_name
origin_id = aws_s3_bucket.b.id
origin_access_control_id = aws_cloudfront_origin_access_control.s3_oac.id
}
default_cache_behavior {
viewer_protocol_policy = "redirect-to-https"
allowed_methods = ["GET", "HEAD"]
cached_methods = ["GET", "HEAD"]
target_origin_id = aws_s3_bucket.b.id
cache_policy_id = data.aws_cloudfront_cache_policy.default.id
compress = true
}
restrictions {
geo_restriction {
restriction_type = "whitelist"
locations = ["JP"]
}
}
enabled = true
is_ipv6_enabled = true
viewer_certificate {
cloudfront_default_certificate = true
}
}
data "aws_cloudfront_cache_policy" "default" {
name = "Managed-CachingOptimized"
}
resource "aws_cloudfront_origin_access_control" "s3_oac" {
name = "teach-tf-test-oac"
origin_access_control_origin_type = "s3"
signing_behavior = "always"
signing_protocol = "sigv4"
}
こちらもS3と同様にterraformのサンプルを参考にしつつ、手動でコンソールでCloudFrontを一度作成してみて、それと同一になるようにterraform側で設定した。
ポイントは以下
■ default_cache_behaviorのcache_policy_id
サンプルと同様の方法でやるとLegacyになるのでcache_policy_idを使う
設定の仕方
■ aws_cloudfront_origin_access_control
OAIはLegacyなのでOACを使う。
参考
descriptionはRequiredって書いてあるけどなくても大丈夫そうな。
aws_s3_bucket_policyは[Developer Guide]とterraformのドキュメント見て同じになるように設定
これをapplyしてS3にオブジェクトアップロードするとcloudfront経由で取得できる。