Tomorrow Will Be A Better Day

Published

- 10 min read

CloudFormationとTerraformの使用感〜2017年7月版〜

img of CloudFormationとTerraformの使用感〜2017年7月版〜

1.背景

2016年9月、CloudFormation(以下、CFn)がYAML書式に対応しました。
AWS CloudFormation の更新 – YAML、クロススタック参照、簡略化された置換

また、Terraformも0.9になったことで、各環境ごとに設定を切り替えることができるようになりました。
Terraform 0.9がリリース。0.8.xから0.9.xのStateマイグレーション手順をまとめました。
Summary of Terraform v0.9

これらのリリースによって、それぞれのツールに対する使用感が大分変わったので、
備忘がてら2017年7月時点でのCFnとTerraformの使用感をメモしておきます。
なお、本記事のTerraformは無料版なので、エンタープライズ版の使用感とは異なると思います。

2.TL;DR

AWSだけの運用に絞れる環境であれば、今はTerraformで環境ごとの設計を色々考えるよりも、
CFnで構築した方が運用する上でも大分楽なんじゃないかなーというのが執筆時点での感想です。

3.機能比較

主機能の違いは以下の通り。

機能CFNCFN(2017/07時点)TERRAFORM(~0.8)TERRAFORM(0.9~)
書式JSONJSON,YAMLHCLHCL
対応環境AWSAWSAWS,GCP,Azure,github,etc…AWS,GCP,Azure,github,etc…
実行管理AWSAWStfstate(JSON)tfstate(JSON)
実行権限AccessKeyAccessKey, IAM RoleAccessKeyAccessKey
環境分割方法スタック分割スタック分割、クロススタック参照ディレクトリ分割、module&output機能env分割、module&output機能

HCL:HashiCorp Configuration Language

この中で、各項目についての使用感を以下の項目で記載します。

3-1.書式の変遷

CFnの場合

兎にも角にも、CFnのYAML対応がとても嬉しいです。
JSONでもコメント文を書けるよという話はちらほらあったけど、少なくともパラメータやリソースそれぞれに対して、
下記のようにコメント文が記載できるようになっただけでも、大分視認性が上がるかなと。

CFnのYAML書式例

   AWSTemplateFormatVersion: 2010-09-09
######################################
# Parameters Settings
######################################
Parameters:
  AppName:
    Type: String
    Default: hogehoge
    Description: App Name
(snip)
######################################
# Mappings Settings
######################################
Mappings:
  StackConfig:
    VPC:
      CIDR: 10.0.0.0/16
(snip)
######################################
# Resources Settings
######################################
Resources:
    VPC:
        Type: 'AWS::EC2::VPC'
        Properties:
            CidrBlock: !FindInMap [ StackConfig, VPC, CIDR ]
            EnableDnsSupport: true
            EnableDnsHostnames: true
            InstanceTenancy: default
(snip)
######################################
# Outputs Settings
######################################
Outputs:
  VPC:
    Value: !Ref VPC
    Export:
      Name: VPCId
(snip)

Terraformの場合

Terraformのドキュメントがかなりわかりやすいので、基本はここに記載されているresourceの使い方を学んでいくスタイル。
terraform planとterraform applyの2種類のコマンドを使い、おおむね3日程度でTerraformで必要な書式方法がわかるかなと。

Terraformの書式例

   #####################################
# VPC Settings
#####################################
resource "aws_vpc" "vpc_main" {
    cidr_block = "10.0.0.0/16"
    enable_dns_hostnames = true
    tags {
        Name = "${module.common.app_name}"
        Env = "common"
    }
}
######################################
## Internet Gateway Settings
######################################
resource "aws_internet_gateway" "vpc_main-igw" {
    vpc_id = "${aws_vpc.vpc_main.id}"
    tags {
        Name = "${module.common.app_name} igw"
        Env = "common"
    }
}

3-2.対応プラットフォームの変遷

CFnの場合

当然ながら、CFnはAWSの一種なので、AWS関連の操作に限られます。

Terraformの場合

Terraformは複数のプラットフォームを操作することが可能なので、マルチクラウド環境を運用するときにTerraform内のドキュメントを追えば、
必須のパラメータなりを見て、多少なりとも他環境でもキャッチアップしやすくなるかなと。
個人的には、TerraformでAWSのようなインフラ環境を操作するだけでなく、
以下のようにgithubのTeam設定もコード化しておいて、退職者対応とかでも履歴を残せるのがよいなと思います。

Terraformのgithubプロバイダ利用例

   ###########################
# Team Setting
###########################
resource "github_team" "hoge" {
  name        = "developer"
  description = "hoge"
  privacy     = "closed"
}
###########################
# Team Membership Setting
###########################
resource "github_team_membership" "maintainer" {
  team_id  = "${github_team.hoge.id}"
  username = "CkReal"
  role     = "maintainer"
}
resource "github_team_membership" "fuga" {
  team_id  = "${github_team.hoge.id}"
  username = "fuga"
  role     = "member"
}
(snip)
###########################
# Team Repository Setting
###########################
resource "github_team_repository" "hoge_test" {
  team_id    = "${github_team.hoge.id}"
  repository = "test"
  permission = "push"
}

3-3.実行管理の変遷

ここに対する認識が、両者の実運用方法において、大きく見解が別れるところだと思います。

CFnの場合

CFnは実行した結果がManagementConsoleで確認でき、CFnが管理しているリソースが可視化されています。

CFnの実行結果例

CFn_ManagementConsole.png

CFnの管理リソース例

リソース.png

Terraformの場合

Terraformの場合、terraform state listやterraform showというコマンドや、
terraform showコマンドとgraphvizを組み合わせたりして、管理しているリソースを確認できます。
ただ、基本的にtfstateファイルでリソース管理されているため、
CFnのような可視化を行いたいのであれば、ユーザー側で何かしらのツールなどを作成する必要があります。

terraform showコマンド実行例

   % terraform show
github_team.administrator:
  id = XXXXXXX
  description = 管理者
  name = administrator
  privacy = closed
github_team.developer:
  id = XXXXXXX
  description = 開発者
  name = developer
  privacy = closed
github_team.operator:
  id = XXXXXXX
  description = 運用者
  name = operator
  privacy = closed

3-4.実行権限の変遷

CFnの場合

IAM Userの権限とは別に、実行するIAM Roleを選択できるようになっているので、必要なRoleをIAM Userに使用させるといったことが可能。

Terraformの場合

複数人でTerraformを利用するのであれば、TerraformのBackendにS3やGCSを利用したりして、同時実行を避けるような仕組みが運用上必須かなと思います。
そのため、このtfstateファイルを保存するS3のバケットポリシー設定や、そのS3を操作するIAM権限も考えておく必要があります。
(他で利用しているIAM Userがterraformで管理しているバケットを更新しないように設定するなど)

3-5.環境分割方法の変遷

CFnの場合

Parameterを活用すれば、どのSecurityGroupを変数で実行するかがプルダウンで指定できたりするのが便利です。
このあたりは、流石にAWSのサービスだなあと感じます。
また、2016年にはクロススタック参照ができるようになったので、Stackの粒度を小さく管理できるようになり、共通変数を使いまわししやすくなりました。

Terraformの場合

0.8以前は、moduleとoutputを使用して、ディレクトリごとtfstateを分割し、必要な環境変数はgetコマンドで取りに行く方針が主流だったと思います。
0.9になると、ここにenvの概念が出てきて、同じディレクトリ内で環境を切り替えるといったことができるようになり、backendに設定したtfstateも分割することができるようになりました。

4.まとめ

CFnもTerraformもどんどん機能追加されて、進化していっています。
Terraformについては、私が使い始めた頃はplanとapplyのみを中心に考えていけばよかったのですが、0.9以降になるとenvとgetの概念も使いこなす必要が出てきました。
また、さらにbackendにS3を使うなら、S3やIAMの権限設計といった感じで、Terraformを安全に使うために考えることが多くなってきた感じです。
CFnについては、JSONのみで別Stackへ変数を渡せなかったりした時代から、 YAML対応,クラススタック参照,変更セットといった機能が追加され、かなりAWS環境の実運用で回せるように洗練されてきた印象です。