0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Terraformに入門してみる

Posted at

Terraformの門を叩く

私は以前、AWS SAMとgithub ActionsでCD環境を構築しました。
その時に、「AWS SAMはある程度理解したから、次はCloudFormationやな...」
と思っていましたが、上司からTerraformはAWSだけじゃなくほかのクラウドでも使えるから使ってみたらと勧められまして、今に至ります。

Terraformとは

HashiCorpという会社が作成したIaaCサービスです
HCLという独自の言語で記述するようですが、習得が難しいという全くなかったです。
ブロック引数で記述する感じでした。

ブロックとは

provider "aws" {
  region     = "us-east-1"
  access_key = "hogehoge"
  secret_key = "fugafuga"
}
resource "aws_s3_bucket" "hoge" {
  bucket = "my-unique-bucket-name-12345"
  acl    = "private"
}
module "vpc" {
  source = "./vpc"
}

ブロックはあらかじめ定義されており、いくつか存在します。上記の例は
resourceブロック
providerブロック
moduleブロック
を使用しています。
ブロックごとに宣言したときの意味が違います。例に挙げた三つは下記のとおりです

  • resourceブロック
    resourceブロックで宣言されたリソースを作成します。
    上記の例だとs3バケットが作成されます。
  • providerブロック
    どのクラウドにリソースを作成するかを決めます
  • moduleブロック
    分割したファイルを読み込んだり、公式が用意したファイルをそのまま使用したりできます。

ブロックの後に記述している文字列はファイル内で参照するときに使用される名前です。
変数名に近いです。

module "vpc" {#この"vpc"が参照される名前
  source = "./vpc"
}

resourceブロックでは"hoge"が参照されます。
"aws_s3_bucket"はどのリソースを作成するか決めています。

resource "aws_s3_bucket" "hoge" {#hogeが参照される名前
}

引数とは

HCLでいう引数とはブロック内で宣言されている変数みたいなやつです。
ここで渡した値を使用してリソース作ったり、モジュールを使用したりしてくれるわけです。

provider "aws" {
  region     = "us-east-1"#これ
  access_key = "hogehoge"#これ
  secret_key = "fugafuga"#これ
}
resource "aws_s3_bucket" "hoge" {
  bucket = "my-unique-bucket-name-12345"#これ
  acl    = "private"#これ
}
module "vpc" {
  source = "./vpc"#これ
}

基本的な三つのファイル

HCLでメインで記述するファイルは3つに分ける慣習があるようです。

  • main.tf
    リソースの定義やプロバイダーの宣言などメインの記述はココ
  • variables.tf
    main.tfで使用する変数を定義する。
  • outputs.tf
    main.tfではなく別のtfファイルで変数を参照する際に記述する

全て一つのファイルに書いても問題なく動作する。
またファイル名も適当でよく、決まったものはない。
基本的にterraformコマンドを使用すると、そのディレクトリのtfファイルはすべて読み込まれるため、ファイル名は上記以外でも問題ない

iam/main.tf
terraform {
  required_version = ">= 0.12"
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = ">= 4.0.0"
    }
  }
}
provider "aws" {
  region     = var.region
  access_key = var.aws_access_key
  secret_key = var.aws_secret_key
}
#GitHub Actions用のIAMロールを作成
resource "aws_iam_role" "github_actions_deploy_role" {
  name = "github-actions-deploy-role"

  assume_role_policy = jsonencode({
    Version = "2012-10-17",
    Statement = [
      {
        Effect = "Allow",
        Principal = {
          Federated = "arn:aws:iam::${var.aws_account_id}:oidc-provider/token.actions.githubusercontent.com"
        },
        Action = "sts:AssumeRoleWithWebIdentity",
        Condition = {
          StringLike = {
            "token.actions.githubusercontent.com:sub" : [
              "repo:${var.deploy-repository[0]}",
              "repo:${var.deploy-repository[1]}"
            ]
          }
        }
      }
    ]
  })
}
iam/variables.tf
variable "aws_access_key" {}

variable "aws_secret_key" {}

variable "region" {}


variable "aws_account_id" {
  default = 940723107657
}
variable "deploy-repository" {
  description = "GitHub repository for deployment"
  default     = ["sugiYutaka/utinoko:ref:refs/heads/stage", "sugiYutaka/utinoko:ref:refs/heads/prod"]
}

variables.tfで定義した変数はvar.変数名で参照できる。
variables.tfではデフォルト値を設定できるほか、親のtfファイルから引数として受け取ることも可能
また同じ階層に.auto.tfvarsを作成することで変数を渡すことも可能。

.auto.tfvars
// ステージ環境用の変数
aws_access_key = "******"
aws_secret_key = "******"
region = "us-east-1"

tfvarsファイルは.gitignoreに設定しておくことを推奨する

構成

今回のディレクトリ構成はこんな感じになっており

project/
├── frontend/          # Next.js (React) フロントエンド
├── backend/           # PHP Laravel バックエンドAPI
|
└── terraform/         # AWS インフラ構成管理
    ├── vpc/           # VPC・ネットワーク設定
    ├── rds/           # RDS MySQL データベース
    ├── rdsProxy/      # RDS Proxy(コネクション管理)
    ├── lambda/        # Lambda関数(Laravel API)
    ├── apiGateway/    # API Gateway(REST API)
    ├── s3/            # S3(フロントエンドホスティング)
    ├── cloudfront/    # CloudFront(CDN)
    └── main.tf        # メインの構成定義

今回はすべてモジュールを使用して構築しました
使用したモジュールはこれです
https://github.com/terraform-aws-modules
最初はすべて手書きでやっていたんですが、moduleが便利そうだったので、乗り換えました。
モジュールを簡単に使用、作成したりできるのはCloudFormationにはない良い点だと思います。

デプロイ

まずはterraformディレクトリで下記のコマンドを実行します。
実行することで.terraformディレクトリが作成され、ここにmoduleなどがダウンロードされます。

bash
terraform init

つぎは今回のデプロイで何が作成されるのかを確認します。

bash
terraform plan

...

Plan: 1 to add, 2 to change, 1 to destroy.

1つのリソースの追加と
2ふたつのリソースの変更
1つのリソースの削除があることが確認できます。

問題ないのでデプロイします。

bash
#.auto.tfvarsファイルを読み込む場合
terraform apply

#任意の.tfvarsファイルを読み込む場合
terraform apply -vars-file=./stage.tfvars

使ってみた感想

ファイルの分割が簡単で、きれいにコードが書けるので、気持ちよく記述できました。
再利用もしやすいモジュールを作成することもできて、別のプロジェクトでもつかえそうな感じがします。

いいところのほうが多いように感じましたが、
めんどくさいと思うことがありました。
s3にNextJsのbuildしたディレクトリをアップロードしようと思ったのですが、for文でループしてアップロードするような方法しかありませんでした。リソースのプロビジョニングには適していますが、CDはCloudFormationのほうが構築しやすいです。とはいえS3でホスティングするならAmplifyを使うようにAWS公式が言っているので、Amplifyを使いましょう。
再利用しやすいですし、私はCloufFormationよりTerraformを推していきたいです

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?