272
252

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

and factoryAdvent Calendar 2020

Day 7

図解『実践Terraform』

Last updated at Posted at 2020-12-06

はじめに

インフラ構成をコード化するIaC(Infrastructure as Code)の代表的サービスであるTerraform。
このTerraformを学ぶ上で書籍『実践Terraform AWSにおけるシステム設計とベストプラクティス』がよく参考にされています。
本記事ではこの書籍をこれから読む方向けに、書籍内で紹介されているサンプルプロジェクトを構成するリソースを図にして紹介します。

『実践Terraform』

7GUzk7Hj.jpg

タイトル:『実践Terraform AWSにおけるシステム設計とベストプラクティス』
著者:野村友樹(@tmknom)氏
発行:株式会社インプレスR&D

@tmknomさん、インプレスR&Dさん、書影掲載許可いただきありがとうございます!

『実践Terraform AWSにおけるシステム設計とベストプラクティス』(以下『実践Terraform』とします)は、著者が技術書展やBOOTHなどで頒布されていた『Pragmatic Terraform on AWS』という同人誌を元にした内容となっています。
出版にあたり、同人誌時代から、100ページ近くページ追記・改定した内容になっており、Terraform界隈では神本として多くの人に認知されているようです。

Terraformの環境整備から、サンプルプロジェクトでのアーキテクチャ構築ハンズオン、Tipsまで幅広く掲載されており、初心者向けの参考書籍として最適です。

紹介記事(一部)

書籍を利用してみて

Terraformに初めて触れる初心者の私でも、この本の通りにイチから順序立てて作業することで、立派なAWSのアーキテクチャを構築することができました!
※なお、AWS SAAの学習をしている時期でもあったため、AWSの超基礎的な知識は持っていました。

ただ、正直に言うと、組み上げているものの全体像が把握できず、とりあえず写経をしている、という状況になっていたのも事実です。
著者のサンプルコードリポジトリにコード等も載っているのですが、章ごとに追記する内容のみがまとめられているため、Terraform初心者の私としては全体の構造の把握に苦労してしまいました。

そこで、実際にTerraformで構築するリソースを図式化してみて、理解を深めようと考えました。
ここでは、その成果物とともに振り返り、同じ思いをする人を少しでも減らせられれば良いかなと思っています。

全体図

今回は「第5章 権限管理」から「第16章 ロギング」までを対象として説明させていただきます。
1章から4章はTerraformの使い方や基本的な構文の説明で、17章以降はベストプラクティスとか継続的Applyとか、オプショナルな感じなので、図解はあまり有効ではないと判断しました。

早速ですが下記が全体のイメージです。
※結構細かいのでクリックして拡大すると見やすいと思います。

uml_全体.png

作成するリソースは種類も数もとても多いため、大きくAWSサービスと、汎用的に用いるモジュールという分類で下記の形でレイヤーとして分割をしています。
レイヤー種類.png

さらに、具体的に作成するリソースやデータも下記のような形、色にて分類をしてみました。
リソース種類.jpg

リソース(青)は下記のような構造で表現しています。
上から順に「リソースの説明」「リソース種類名」「リソースに付けた名前」を表記しました。
リソースサンプル.png
書籍内ではリソースに名前をつけていない場合もあるのですが、そのような場合はとりあえずexampleと名付けています。(多分)
また、データ(黄)も同様の構造なので、同じルールにて記載しています。
モジュール(緑)は「リソース種類名」が必要ないため、除外しています。
その他、outputproviderといった記載も書籍内では紹介されますが、アーキテクチャの理解にはそれほど影響を与えないため、除外しています。

矢印.png
矢印はリソース間の関係を示しています。
ただし、VPC等多くのリソースから依存されているものの関係性をすべて記載すると矢印の量がすごいことになるので、理解をする上でそれほど重要ではなさそうな部分は除外しています。

上記の前提で図を見ていただければと思います。
なんとなく、作ろうとしているシステムの全体像が見えてくるのではないでしょうか。

各章ごとの対応箇所

ざっと全体のイメージをご紹介しました。
ここからは、各章ごとに生成したリソースを抽出して見ていこうと思います。

第5章 権限管理

uml_5.dio.png
第5章では権限管理のためのIAMロールを作成します。
一通りのIAMロール説明が完了したところで、作成するサンプルプロジェクトで多様されるIAMロールモジュールを作成します。
図は最終的なIAMロールモジュールの構成です。

作成したIAMロールモジュール用のリソースは下記です。

種別 リソース種類 名前 備考
resource aws_iam_role default IAMロール
data aws_iam_policy_document assume_role 信頼ポリシー(ポリシードキュメント)
resource aws_iam_policy default IAMポリシー
resource aws_iam_role_policy_attachment default IAMポリシーのアタッチ(IAMロールにIAMポリシーをアタッチする)

第6章 ストレージ

uml_6.dio.png
第6章ではストレージとして用いるS3バケットを作成します。
サンプルとしてパブリックバケット、プライベートバケット、ALBログ用バケットを作成しますが、ALBログ用バケットは第7章 ネットワークでも利用されます。

作成したS3用のリソースは下記です。

種別 リソース種類 名前 備考
resource aws_s3_bucket private プライベートバケット
resource aws_s3_bucket_public_access_block private プライベートバケットのパブリックアクセス定義
resource aws_s3_bucket public パブリックバケット
resource aws_s3_bucket alb_log ログバケット(後に定義するALB用のログを格納する)
data aws_iam_policy_document alb_log ALBログを書き込むためのIAMポリシー

なお、リスト6.5identifiersを直接記載する箇所がありますが、ソース管理上アカウントIDを直接記載したくないため、aws_elb_service_accountのデータを参照する形に調整を行いました。

# ログの書き込みに使用されるアカウントIDを自動的にフェッチできる
data "aws_elb_service_account" "alb_log" {}

# リスト6.5 ALBログを書き込むためのIAMポリシー
data "aws_iam_policy_document" "alb_log" {
  statement {
    effect    = "Allow"
    actions   = ["s3:PutObject"]
    resources = ["arn:aws:s3:::${aws_s3_bucket.alb_log.id}/*"]

    principals {
      type        = "AWS"
      identifiers = ["${data.aws_elb_service_account.alb_log.id}"] # 参照
    }
  }
}

追加したサービスアカウント取得用のリソースは下記です。

種別 リソース種類 名前 備考
data aws_elb_service_account alb_log ログの書き込みに使用されるアカウントIDを自動的にフェッチする

第7章 ネットワーク

uml_7.dio.png
第7章ではネットワーク(VPC)とセキュリティグループを作成します。
章内の7.1パブリックネットワーク7.2 プライベートネットワークで構築された下記リソースは、7.3マルチAZ以降でマルチAZ化に伴って細分化変更されます。
上図は7章完了状態の図のため、マルチAZ前のリソースは図中には存在しません。

調整前リストNo. 名称 調整後リストNo.
リスト7.2 パブリックサブネット リスト7.12
リスト7.6 パブリックサブネット用ルートテーブルの関連付け リスト7.13
リスト7.7 プライベートサブネット リスト7.14
リスト7.8 プライベートサブネット用ルートテーブルと関連付け リスト7.16
リスト7.9 プライベートサブネット用のEIP リスト7.15
リスト7.10 プライベートサブネット用のNATゲートウェイ リスト7.15
リスト7.11 プライベートサブネット用のルート リスト7.16

また、セキュリティグループ第5章 権限管理で作成したIAMモジュールと同様に、他の章で生成するリソースからも多用されるため、モジュールとして生成されています。

作成したマルチAZのVPC用のリソースは下記です。

種別 リソース種類 名前 備考
resource aws_vpc example VPC
resource aws_internet_gateway example インターネットゲートウェイ
resource aws_subnet public_0 AZ0のパブリックサブネット
resource aws_subnet public_1 AZ1のパブリックサブネット
resource aws_route_table public パブリックサブネット用ルートテーブル
resource aws_route public パブリックサブネット用ルート(ルートテーブルのレコード)
resource aws_route_table_association public_0 AZ0のパブリックサブネットとルートテーブルの関連付け
resource aws_route_table_association public_1 AZ1のパブリックサブネットとルートテーブルの関連付け
resource aws_subnet private_0 AZ0のプライベートサブネット
resource aws_subnet private_1 AZ1のプライベートサブネット
resource aws_eip nat_gateway_0 AZ0のNATゲートウェイ用EIP
resource aws_eip nat_gateway_1 AZ1のNATゲートウェイ用EIP
resource aws_nat_gateway nat_gateway_0 AZ0のNATゲートウェイ
resource aws_nat_gateway nat_gateway_1 AZ1のNATゲートウェイ
resource aws_route_table private_0 AZ0のプライベートサブネットのルートテーブル
resource aws_route_table private_1 AZ1のプライベートサブネットのルートテーブル
resource aws_route private_0 AZ0のプライベートサブネットのルート
resource aws_route private_1 AZ1のプライベートサブネットのルート
resource aws_route_table_association private_0 AZ0のプライベートサブネットのルートテーブルの関連付け
resource aws_route_table_association private_1 AZ1のプライベートサブネットのルートテーブルの関連付け

作成したセキュリティグループモジュール用のリソースは下記です。

種別 リソース種類 名前 備考
resource aws_security_group default セキュリティグループ
resource aws_security_group_rule ingress セキュリティグループルール(インバウンド)
resource aws_security_group_rule egress セキュリティグループルール(アウトバウンド)

第8章 ロードバランサーとDNS

uml_8.dio.png
第8章ではロードバランサー(ALB)を作成し、Route53でDNSを設定します。また、SSL化のためにACMを利用します。
学習を行う上で、ドメインとSSLを入れない選択を取ることもできます。
その場合は、Route53、ACMを設定せずにELBのみ作成して試すことが可能なので、図内ELBのHTTPS化を行わない場合の構成を作成すれば良いです。

図中にsgというモジュールがありますが、これは第7章 ネットワークで作成したセキュリティグループモジュールを示しています。
また、図中のALBログ用バケット第6章 ストレージで作成済みのリソースを利用するため、この章で追加で作る必要はありません。

作成したELB用のリソースは下記です。
HTTPS化を行う場合と行わない場合、両方に関して記載しています。

種別 リソース種類 名前 備考
resource aws_lb example ALB
module - http_sg HTTP用セキュリティグループ
module - https_sg HTTPS用セキュリティグループ
module - http_redirect_sg HTTPからHTTPSへのリダイレクト用セキュリティグループ
resource aws_lb_listener http HTTPリスナーの定義(HTTPS化を行わない場合)
resource aws_lb_listener https HTTPSリスナーの定義(HTTPS化を行う場合)
resource aws_lb_listener redirect_http_to_https HTTPからHTTPSへのリダイレクトリスナーの定義(HTTPS化を行う場合)
resource aws_lb_target_group example ターゲットグループ
resource aws_lb_listener_rule example リスナールール(HTTPS化を行う場合と行わない場合でlistener_arnの設定値が異なる)

作成したRoute53用のリソースは下記です。
図はホストゾーンが既にある状態を想定していますが、下記には新規に作成する場合に関しても記載しています。
また、SSL証明書を利用しない場合は、SSL証明書検証用レコード定義は必要なくなります。

種別 リソース種類 名前 備考
data aws_route53_zone example ホストゾーンの参照(ホストゾーンがすでにある場合)
resource aws_route53_zone example_test ホストゾーンの作成(ホストゾーンを新規に作成する場合)
resource aws_route53_record example ALBのDNSレコード
resource aws_route53_record example_certificate SSL証明書の検証用レコード

作成したACM用のリソースは下記です。

種別 リソース種類 名前 備考
resource aws_acm_certificate example SSL証明書
resource aws_acm_certificate_validation example SSL証明書の検証完了まで待機(apply時にSSL証明書の検証が完了するまで待つ。何かのリソースが作られるわけではない。)

第9章 コンテナオーケストレーション

uml_9.dio.png
第9章ではコンテナオーケストレーション環境を作成します。
コンテナ定義はcontainer_definition.jsonで行われています。
これはTerraformプロジェクト内に置かれる定義ファイルで、構成図に本来載るものではないとは思うのですが、関係性を明示したかったので記載しました。(わかりやすければええやん精神)

図中にiamというモジュールがありますが、これは第5章 権限管理で作成したIAMモジュールを示しています。
また、図中のターゲットグループ第8章 ロードバランサーとDNSで作成済みのリソースを利用するため、この章で追加で作る必要はありません。

作成したCloudWatch用のリソースは下記です。

種別 リソース種類 名前 備考
resource aws_ecs_cluster example ECSクラスター
resource aws_ecs_task_definition example ECSタスク定義
resource aws_ecs_service example ECSサービス(起動タスクの数やタスクの維持、ALBとの橋渡し)
module - nginx_sg Nginx用セキュリティグループ

作成したACM用のリソースは下記です。

種別 リソース種類 名前 備考
resource aws_cloudwatch_log_group for_ecs CloudWatch Logs
data aws_iam_policy ecs_task_execution_role_policy ECSタスク実行IAMロールポリシーの参照(AWSが管理しているポリシー)
data aws_iam_policy_document ecs_task_execution ECSタスク実行IAMロールのポリシードキュメント
module - ecs_task_execution_role ECSタスク実行IAMロール

第10章 バッチ & 第12章 設定管理

uml_10_12.dio.png
第10章ではECSとCloudWatchを用いたバッチ処理を作成します。
バッチの作成で用いるバッチ用コンテナ定義は、第12章でSSMパラメータを使う形に調整されています。
そのため、第10章と第12章は一つにまとめて図を紹介しました。

また、図中のECSタスク実行IAMロール第9章 コンテナオーケストレーションで作成済みのリソースを利用するため、この章で追加で作る必要はありません。

作成したECS用のリソースは下記です。

種別 リソース種類 名前 備考
resource aws_ecs_task_definition example_batch バッチ用ECSタスク定義

作成したCloudWatch用のリソースは下記です。

種別 リソース種類 名前 備考
resource aws_cloudwatch_log_group for_ecs_scheduled_tasks バッチ用CloudWatch Logs
module - ecs_events_role CloudWatchイベントIAMロール
data aws_iam_policy ecs_events_role_policy CloudWatchイベントIAMロールポリシー
resource aws_cloudwatch_event_rule example_batch CLoudWatchイベントルール
resource aws_cloudwatch_event_target example_batch CloudWatchイベントターゲット

作成したSSM用のリソースは下記です。

種別 リソース種類 名前 備考
resource aws_ssm_parameter db_username DBのユーザ名の定義
resource aws_ssm_parameter db_password DBのダミーパスワードの定義

第11章 鍵管理

uml_11.dio.png
第11章では第13章で用いるためのカスタマーキーを作成します。
作成するカスタマーマスターキーにはUUIDが割り当てられているのですが、人には識別しづらい体系であるため、分かりやすい名前のエイリアスを作成しています。

作成したKMS用のリソースは下記です。

種別 リソース種類 名前 備考
resource aws_kms_key example カスタマーマスターキー
resource aws_kms_alias example エイリアスの定義(カスタマーキーのUUIDでは判別しづらいため)

第13章 データストア

uml_13.dio.png
第13章ではRDB向けデータストアのRDSとインメモリデータストアのElastiCacheを作成します。
作成するデータストアは、それぞれマルチAZに構築するため、第7章 ネットワークで作成したリージョンの異なるプライベートサブネット2つを指定しています。
プライベートサブネット0プライベートサブネット1はVPC内に作成したサブネットとして見ていただければと思います。(図示が難しかった)

また、図中のカスタマーマスターキー第11章 鍵管理で作成済みのリソースを利用するため、この章で追加で作る必要はありません。

作成したRDS用のリソースは下記です。

種別 リソース種類 名前 備考
resource aws_db_parameter_group example DBパラメータグループ
resource aws_db_option_group example DBオプショングループ(DBエンジンにオプション機能を追加する。例はMariaDB監査プラグイン)
resource aws_db_subnet_group example DBサブネットグループ(DBを稼働させるサブネットの定義)
resource aws_db_instance example DBインスタンス
module - mysql_sg DBインスタンスのセキュリティグループ

作成したElastiCache用のリソースは下記です。

種別 リソース種類 名前 備考
resource aws_elasticache_parameter_group example ElastiCacheパラメータグループ
resource aws_elasticache_subnet_group example ElastiCacheサブネットグループ
resource aws_elasticache_replication_group example ElastiCacheレプリケーショングループ(Redisサーバの作成)
module - redis_sg ElastiCacheレプリケーショングループのセキュリティグループ

第14章 デプロイメントパイプライン

uml_14.dio.png
第14章では継続的にシステムをデプロイするためのデプロイパイプラインをCodePipelineを中心にして作成します。

図中にECRへの矢印(関係性)が見えないと思うかもしれませんが、デプロイメントパイプラインで使われないわけではありません。
ビルドされるアプリケーションコード内にあるbuildspec.ymlにてプッシュ先リポジトリに指定されています。
今回はTerraformプロジェクト内には無いリソースのため、図中へは記載しませんでした。

また、図中のECSサービス第9章 コンテナオーケストレーションで作成済みのリソースを利用するため、この章で追加で作る必要はありません。

作成したECR用のリソースは下記です。

種別 リソース種類 名前 備考
resource aws_ecr_repository example ECRレポジトリ
resource aws_ecr_lifecycle_policy example ECRライフサイクルポリシー

作成したS3用のリソースは下記です。

種別 リソース種類 名前 備考
resource aws_s3_bucket artifact アーティファクトストア用バケット

作成したCodeBuild用のリソースは下記です。

種別 リソース種類 名前 備考
data aws_iam_policy_document codebuild CodeBuildサービスロールのポリシードキュメント
module - codebuild_role CodeBuildサービルロール
resource aws_codebuild_project example CodeBuildプロジェクト

作成したCodePipeline用のリソースは下記です。

種別 リソース種類 名前 備考
data aws_iam_policy_document codepipeline CodePipelineサービスロールのポリシードキュメント
module - codepipeline_role CodePipelineサービスロール
resource aws_codepipeline example CodePipeline(例では3つのステージで実装する)
resource aws_codepipeline_webhook example CodePipeline Webhook
resource github_repository_webhook example GitHub Webhook(GitHub上でのイベントを検知し、コードの変更を通知するWebhookの定義)

なお、AWSプロバイダ3.3.0から新規で作る時はOAuthTokenが必須らしく、書籍内の14.10のコードのままだとSourceステージでコケてしまいます。
そのため、github_tokenをSSMパラメータとして定義し、それを用いることにしました。

data "aws_ssm_parameter" "github_token" {
  name = "/continuous_apply/github_token"
}

# リスト14.10
# CodePipelineの定義(例では3つのステージで実装する)
resource "aws_codepipeline" "example" {
  name     = "example"
  role_arn = module.codepipeline_role.iam_role_arn

  # Sourceステージ:GitHubからソースコードを取得する
  stage {
    name = "Source"

    action {
      name             = "Source"
      category         = "Source"
      owner            = "ThirdParty"
      provider         = "GitHub"
      version          = 1
      output_artifacts = ["Source"]

      configuration = {
~中略~
        PollForSourceChanges = false
        OAuthToken           = data.aws_ssm_parameter.github_token.value # SSMパラメータから指定
      }
    }
  }
~後略~

追加したSSM用のリソースは下記です。

種別 リソース種類 名前 備考
resource aws_ssm_parameter github_token GitHub TokenをSSMパラメータとして定義

第15章 SSHレスオペレーション

uml_15.dio.png
第15章ではオペレーション用のサーバをSession ManagerとEC2を用いて作成します。
また、オペレーションログとしてSession Managerの操作ログを保存する仕組みを構築します。

オペレーションサーバ自体は第7章 ネットワークでVPC内に作成したプライベートサブネットに作成します。
user_data.shはTerraformプロジェクト内に配置されているshファイルですが、EC2インスタンス作成時に実行されるプロビジョニングスクリプトとして指定されています。

追加したEC2用のリソースは下記です。

種別 リソース種類 名前 備考
data aws_iam_policy_document ec2_for_ssm オペレーションサーバ用ポリシードキュメント
data aws_iam_policy ec2_for_ssm Session Manager用に定義されているポリシーをベースに利用する
module - ec2_for_ssm_role オペレーションサーバ用IAMロール
resource aws_iam_instance_profile ec2_for_ssm インスタンスプロファイル(EC2は直接IAMロールを関連付けられないため、IAMロールをラップしたインスタンスプロファイルを関連付ける)
resource aws_instance example_for_operation オペレーションサーバ用EC2インスタンス

追加したS3用のリソースは下記です。

種別 リソース種類 名前 備考
resource aws_s3_bucket operation_instance_id オペレーションログを保存するS3バケットの定義

作成したCloudWatch用のリソースは下記です。

種別 リソース種類 名前 備考
resource aws_cloudwatch_log_group operation オペレーションログを保存するCloudWatch Logs

作成したSSM用のリソースは下記です。

種別 リソース種類 名前 備考
resource aws_ssm_document session_manager_run_shell Session Manager用SSM document

第16章 ロギング

uml_16.dio.png
第16章ではロギングの仕組みを作成します。
ロギングにはCloudWatch Logsが便利であることを書籍では紹介した上で、サンプルプロジェクトではログをKinesis Data Firehoseの配信ストリームを用いてS3に永続化する方法を紹介しています。

作成したS3用のリソースは下記です。

種別 リソース種類 名前 備考
resource aws_s3_bucket cloudwatch_logs CloudWatch Logs永続化バケット

作成したKinesis Data Firehose用のリソースは下記です。

種別 リソース種類 名前 備考
data aws_iam_policy_document kinesis_data_firehose Kinesis Data Firehose IAMロールのポリシードキュメントの定義
module - kinesis_data_firehose_role Kinesis Data Firehose用IAMロール
resource aws_kinesis_firehose_delivery_stream example Kinesis Data Firehose配信ストリーム(Kinesis Data Firehoseにログが流れるとこの配信ストリームに設定したS3バケットへログを保存する)

作成したCloudWatch用のリソースは下記です。

種別 リソース種類 名前 備考
data aws_iam_policy_document cloudwatch_logs CloudWatch Logs用IAMロールポリシードキュメント
module - cloudwatch_logs_role CloudWatch Logs用IAMロール
resource aws_cloudwatch_log_subscription_filter example CloudWatch Logsサブスクリプションフィルタ

おわりに

本記事で挙げている図は完全に筆者のイメージで作られています。
そのため、実際のものと異なる可能性が多分にあります。
何かお気づきの点等あればコメント等にてお知らせいただけますと幸いです。

この記事が少しでも参考になっていたら嬉しいです。

272
252
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
272
252

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?