63
44

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

株式会社NucoAdvent Calendar 2022

Day 11

TerraformとCloudFormationで学ぶインフラ構築の自動化

Last updated at Posted at 2022-12-11

この記事はNuco Advent Calendar 2022の11日目の記事です。

インフラに関わるエンジニアにとって必須の知識であるIaCについて書こうと思います。
IaCは、Infrastructure as Codeの略であり、「インフラのコード化」と言われたりします。
ここ最近はクラウドを使った開発では、IaCが当たり前になっていると感じています。

この記事で得られること

  • IaCの基本知識(IaCとは? なぜ使うのか? どんなツールがあるか?)
  • CloudForamtionの全体像・使い方・サンプルコード・実務での応用例
  • Terraformの全体像・使い方・サンプルコード・実務での応用例
  • IaC導入に関するtips

1. Infrastructure as Code (IaC)とは?

1-1. 定義

WikipediaによるとIaCは下記のように定義されています。

Infrastructure as Code(IaC) はコンピューティング・インフラ(プロセス、ベアメタルサーバー、仮想サーバーなど)の構成管理・機械処理可能な定義ファイルの設定・プロビジョニングを自動化するプロセスである。

クラウドを利用した開発が普及している現代においては、
IaC =「クラウド上のサーバーや設定をコードで管理すること」という理解で十分です。

上記の「コード」は、「テンプレート」や「設定ファイル」と呼ばれることもあります。

2. なぜIaCが必要なのか

2-1. 環境構築における再利用性が上がる

ほとんどの開発現場では少なくとも2つは環境を用意しているのではないでしょうか?

  • prod環境(本番環境)
  • dev環境(開発環境)

サービスの性質や規模によっては、stg環境といった上記以外の環境を用意することもあります。
新しい環境が必要になった際に手作業で構築すると、ミスをする可能性が高くなりますが、IaC対応してあると、同一の環境を簡単に作成できるようになります。

2-2. コミュニケーションコストが下がる

設定内容はファイルに書いてあるので、書き方さえ覚えれば(or 調べられるようになれば)自分が構築作業をしていなくても内容把握が容易になります。
誰かに聞かないと解決しない、といったことが減ります。

2-3. 更新履歴を管理できる

テンプレートはアプリケーションのソースコードと同様にgitで管理することが多いです。
いつ・誰が・どんな変更をしたか、というのを簡単に遡ることができますし、レビューも実施しやすくなります。

3. 代表的なIaCのサービス

代表的なIaCのサービスを4つ紹介します。

名前 テンプレートの形式 対応しているクラウド 提供元
CloudFormation JSON, YAML AWSのみ AWS
Google Cloud Deployment Manager YAML, jinja GCPのみ GCP
Azure Resource Manager JSON Azureのみ Azure
Terraform HCL AWS, GCP, Azureなどの主要なパブリッククラウド HashiCorp

1つのクラウドにのみ対応しているものと、マルチクラウド対応のものがあります。
今回はCloudFormationとTerraformについて見ていきます。

4. CloudFormation(CFn)

4-1. 概要

CloudFormationは、AWSリソース(ex. Amazon S3, Amazon EC2, AWS lambda)の構築を、テンプレートを元に自動化するサービスです。

4-2. 全体像

CloudFormationの全体像は以下のようになっています。
iac_cfn_1.drawio (1).png

4-3. 概念

CloudFormationを理解する上で重要な概念が3つあります。

① テンプレート
② スタック
③ 変更セット

それぞれ見ていきます。

①テンプレート (Template)
  • 設定ファイル(AWS リソースを作成する際の設計図というイメージでokです)
  • 1つのテンプレートに複数のAWSリソースの設定を記述できる
  • JSON, YAML形式のテキストファイル
  • 拡張子は、.json、.yaml、.yml、.template、.txt

※コメントがかけるのでYAML形式での管理がおすすめです。

②スタック (Stack)
  • 1つのテンプレートから作成されたAWSリソースの集合体
  • テンプレートをCloudFormationに読み込ませると作成される
③変更セット(Change set)
  • 変更差分データのこと
  • 既存のスタックで管理されているAWSリソースの更新時に生成される
  • 事前にどんな変更が反映されるかを確認することができる

4-4. リソース作成までの流れ

実際にS3バケットを構築します。
iac_cfn.drawio.png

① テンプレートを作成

今回はサンプルとしてnuco-advent-sample-bucketという名前のS3バケットを構築します。

sample.yml
AWSTemplateFormatVersion: "2010-09-09"
Description: template sample
Resources:
  SampleBucket:
      Type: AWS::S3::Bucket
      Properties:
        BucketName: nuco-advent-sample-bucket
② S3にアップロード

AWSのマネジメントコンソールからCloudFormationを選択し、スタックの作成に進みます。
ここで①のテンプレートをアップロードします。
マネジメントコンソールからテンプレートをアップロードすると、テンプレート管理用のS3バケットに配置されます。
スクリーンショット 2022-11-27 14.43.25.png

③ 差分チェック(更新時)

スタックの新規作成時は変更セットは作成されません。
更新時の挙動については③'の項目で扱います。

④, ⑤ スタックを作成・更新, AWSリソースを構築

スタックの作成・更新が完了するとテンプレートファイルに記述されたS3バケット(nuco-advent-sample-bucket)が構築されています。
スクリーンショット 2022-11-27 16.23.34.png

③' 更新時の挙動

スタックの更新時は、変更セットが作成されます。
以下のテンプレートを使い、作成済みのS3バケットを非公開にします。

sample.yml
AWSTemplateFormatVersion: "2010-09-09"
Description: template sample
Resources:
  SampleBucket:
      Type: AWS::S3::Bucket
      Properties:
        BucketName: nuco-advent-sample-bucket
        PublicAccessBlockConfiguration: # 追加
            BlockPublicAcls: true
            BlockPublicPolicy: true
            IgnorePublicAcls: true
            RestrictPublicBuckets: true

スタックの更新前に「変更セット」のプレビューが表示され、変更対象のAWSリソースが表示されています。
スクリーンショット 2022-11-27 16.17.42.png

そのまま更新すると、テンプレートに追加した設定が反映され、バケットが非公開になります。
スクリーンショット 2022-11-27 16.28.52.png

4-5. 実務での利用パターン

  • 作成・更新したテンプレートの反映作業自体を自動化する場合もあります
    • → CI/CD (継続的インテグレーション/継続的デリバリー)を実現
  • 具体的には、以下のサービスも使い、CFnの実行をパイプライン経由にします
    • AWS CodePipeline
    • AWS CodeBuild
      iac_cfn_pipeline.drawio.png

このようにしておくと、以下のようなヒューマンエラーを防ぐことができます。

  • 更新対象のスタックを間違える
  • 使用するテンプレートファイルを間違える

5. Terraform

5-1. 概要

Terraformは、HashiCorp社が提供するマルチクラウド対応のIaCツールです。

5-2. 全体像

Terrafromの全体像は以下のようになっています。
iac_terraform_1.drawio (2).png

5-3. 概念

Terraformを理解する上で重要な概念は以下の4つになります。
① tfファイル
② tfstateファイル (terraform.tfstate)
③ Terraform Core
④ Terraform Plugins

①tfファイル
  • 構築するリソースを定義する設定ファイルのこと
    • 開発者が作成するファイル
  • HCL (HashiCorp Configuration Language)という言語で記述する
  • 拡張子は.tf
②tfstateファイル
  • Terraformに認識されているリソースの状態が定義されたファイル
    • Terraformによって生成されるファイル
  • 拡張子は.tfstate
  • デフォルトのファイル名は、terraform.tfstate
③Terraform Core
  • Go言語で書かれたCLI
  • tfファイルの作成後にterraformコマンドを使うことで実行される
  • tfファイルとtfstateファイルを受け取り、差分を確認し、構築・変更するリソースの状態を決める
  • Terraform Pluginsに対して、リソースに関する操作をリクエストする
    • Terraform v0.12からプロトコルv5になり、gRPCを採用
④Terraform Plugins
  • Terraform Coreから呼び出されるプログラム
  • AWSやGCPといった個別のプロバイダに対してリソースの構築や破棄に関する操作を行う
  • Pluginsを構成する要素として、ProviderとProvisinoerがある
    • Provider
      • AWSやGCPのリソースの作成, 更新, 削除に関する操作をするためのプラグイン
    • Provisinoer
      • 作成したリソースを操作(ex. サーバーの設定)するためのプラグイン

5-4. リソース作成までの流れ

CFnのサンプル同様、AWS環境にnuco-advent-sample-bucketという名前のS3バケットを構築します。
iac_terraform.drawio.png

環境設定

Terraform Coreからローカル環境のPluginが実行されるので環境構築が必要になります。

terraformのインストール(Macユーザーを想定)
% brew install tfenv
% tfenv install 1.3.5
% tfenv use 1.3.5
①tfファイルを作成

ディレクトリ構成は下記になります。

作業ディレクトリ/
 ├ providers.tf    # providerの情報を設定
 ├ sample.tf       # 後ほどS3のリソースを定義

今回はAWS環境にリソースを構築するので、「provider: "aws"」を設定します。

providers.tf

terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "= 4.40.0"
    }
  }
  required_version = "1.3.5"
}


provider "aws" {
  region = "ap-northeast-1"
  profile = "xxxx" # awsの認証情報を設定
}
sample.tf
resource "aws_s3_bucket" "nuco-advent-sample-bucket-tf" {
  bucket = "nuco-advent-sample-bucket-tf"
}

resource "aws_s3_bucket_public_access_block" "nuco-advent-sample-bucket-tf" {
  bucket = aws_s3_bucket.nuco-advent-sample-bucket-tf.id

  block_public_acls       = true
  block_public_policy     = true
  ignore_public_acls      = true
  restrict_public_buckets = true
}
②terraformコマンド実行
init
  • terraformの設定を初期化するためのコマンド
  • terraform init を実行すると、providers.tf で設定している plugin(aws provider)がダウンロードされる
  • ダウンロードされたファイルは、コマンドを実行したディレクトリの .terraform内に配置される
AWS_PROFILE=xxxx terraform init
plan
  • 作成予定のリソースを確認するためのコマンド
  • planを実行すると、Terraform Core側でtfファイルとtfstateファイルが比較され、更新対象のリソースが決まる
AWS_PROFILE=xxxx terraform plan

plan結果として、作成・更新・削除予定のリソースの情報を確認することができます。

Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

  # aws_s3_bucket.nuco-advent-sample-bucket-tf will be created
  + resource "aws_s3_bucket" "nuco-advent-sample-bucket-tf" {
      + acceleration_status         = (known after apply)
      + acl                         = (known after apply)
      + arn                         = (known after apply)
      + bucket                      = "nuco-advent-sample-bucket-tf"
      + bucket_domain_name          = (known after apply)
      
      (中略)

  # aws_s3_bucket_public_access_block.nuco-advent-sample-bucket-tf will be created
  + resource "aws_s3_bucket_public_access_block" "nuco-advent-sample-bucket-tf" {
      + block_public_acls       = true
      + block_public_policy     = true
      + bucket                  = (known after apply)
      + id                      = (known after apply)
      + ignore_public_acls      = true
      + restrict_public_buckets = true
    }

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

実務だと、planが通った段階でレビューを実施することもあります。

apply
  • リソースを作成するためのコマンド
  • applyを実行するとTerrafomr CoreからProviderに対して、リソース操作のリクエストがされる
AWS_PROFILE=xxxx terraform apply

下記のように聞かれるので、yesを入力します。

Do you want to perform these actions?
  Terraform will perform the actions described above.
  Only 'yes' will be accepted to approve.

  Enter a value: 

apply結果

aws_s3_bucket.nuco-advent-sample-bucket-tf: Creating...
aws_s3_bucket.nuco-advent-sample-bucket-tf: Creation complete after 3s [id=nuco-advent-sample-bucket-tf]
aws_s3_bucket_public_access_block.nuco-advent-sample-bucket-tf: Creating...
aws_s3_bucket_public_access_block.nuco-advent-sample-bucket-tf: Creation complete after 0s [id=nuco-advent-sample-bucket-tf]

Apply complete! Resources: 2 added, 0 changed, 0 destroyed.

このタイミングでローカル環境にはterraform.tfstateが作成されます。

terrafrom.tfstate
{
  "version": 4,
  "terraform_version": "1.3.5",
  "serial": 3,
  "lineage": "daa61021-d26d-a4ee-a299-9c6545780fff",
  "outputs": {},
  "resources": [
    {
      "mode": "managed",
      "type": "aws_s3_bucket",
      "name": "nuco-advent-sample-bucket-tf",
      "provider": "provider[\"registry.terraform.io/hashicorp/aws\"]",
      "instances": [
        {
          "schema_version": 0,
          "attributes": {
            "acceleration_status": "",
            "acl": null,
            "arn": "arn:aws:s3:::nuco-advent-sample-bucket-tf",
            "bucket": "nuco-advent-sample-bucket-tf",

5-5. 実務での利用パターン

terraform.tfstateをリアルタイムで共有するため、backendという機能を使い、terraform.tfstateをS3バケットで管理します。
その場合、providers.tfは下記のようにします。

providers.tf
terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "= 4.40.0"
    }
  }
  required_version = "1.3.5"
  backend "s3" { # 追加
    bucket  = "nuco-advent-terraform-state"
    region  = "ap-northeast-1"
    key     = "sample/terraform.tfstate"
    encrypt = true
  }
}

※上記の設定をしても手元からterraformコマンドを実行する必要があります。
※CI/CD化(コマンドの実行も自動化)する場合、以下のようなアーキテクチャになります。
※CodeBuild内でTerraformのSDKを実行します
iac_terraform_pipeline.drawio (1).png

6. IaC導入に関する注意点

IaCには、もちろんデメリットもあります。

6-1. 学習コストがかかる

サンプルからも分かる通り、同じ設定のS3バケットでも、テンプレートの書き方や構築手順はサービスによって異なります。
「今のプロジェクトがAWS環境だから、CFn一択!」とはならず、「インフラ担当全員がTerraformを扱える方が、今後のアサインがしやすくなる」という判断もアリだと思います。

6-2. 既存のシステムをどうするか?

IaC対応されていないシステムは、いまからでもIaC対応した方が良いのでしょうか?
検証期間を十分に確保でき、長期的にIaC対応による恩恵を受けられる場合は対応しても良いかと思います。

6-3. IaCは常に効率的ではない

例えば、下記のようなケースでは、意図的にIaC対応をしないで進めるケースもあります。

  • 新しいAWSサービスをちょっと試してみたい
  • PoC開発(コンセプト検証)のためのサンプルを作りたい

AWS環境であれば、検証時はマネジメントコンソールからリソースを作成し、その後CFnなどでIaC化することがあります。

まとめ

CloudFormationとTerraformのサンプルを使いつつ、IaCについて解説してみました。
初めのうちは、面倒だなと感じるかもしれませんが、管理するリソース数が増えてくると「ああ、IaC化しておいて良かった」思えると思います。この記事が最初のハードルを乗り越える一助になれば幸いです。

最後に

弊社では、経験の有無を問わず、社員やインターン生の採用を行っています。

興味のある方はこちらをご覧ください。

63
44
2

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
63
44

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?