この記事は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の全体像は以下のようになっています。
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. リソース作成までの流れ
① テンプレートを作成
今回はサンプルとしてnuco-advent-sample-bucketという名前のS3バケットを構築します。
AWSTemplateFormatVersion: "2010-09-09"
Description: template sample
Resources:
SampleBucket:
Type: AWS::S3::Bucket
Properties:
BucketName: nuco-advent-sample-bucket
② S3にアップロード
AWSのマネジメントコンソールからCloudFormationを選択し、スタックの作成に進みます。
ここで①のテンプレートをアップロードします。
マネジメントコンソールからテンプレートをアップロードすると、テンプレート管理用のS3バケットに配置されます。
③ 差分チェック(更新時)
スタックの新規作成時は変更セットは作成されません。
更新時の挙動については③'の項目で扱います。
④, ⑤ スタックを作成・更新, AWSリソースを構築
スタックの作成・更新が完了するとテンプレートファイルに記述されたS3バケット(nuco-advent-sample-bucket)が構築されています。
③' 更新時の挙動
スタックの更新時は、変更セットが作成されます。
以下のテンプレートを使い、作成済みのS3バケットを非公開にします。
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リソースが表示されています。
そのまま更新すると、テンプレートに追加した設定が反映され、バケットが非公開になります。
4-5. 実務での利用パターン
- 作成・更新したテンプレートの反映作業自体を自動化する場合もあります
- → CI/CD (継続的インテグレーション/継続的デリバリー)を実現
- 具体的には、以下のサービスも使い、CFnの実行をパイプライン経由にします
このようにしておくと、以下のようなヒューマンエラーを防ぐことができます。
- 更新対象のスタックを間違える
- 使用するテンプレートファイルを間違える
5. Terraform
5-1. 概要
Terraformは、HashiCorp社が提供するマルチクラウド対応のIaCツールです。
5-2. 全体像
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. サーバーの設定)するためのプラグイン
- Provider
5-4. リソース作成までの流れ
CFnのサンプル同様、AWS環境にnuco-advent-sample-bucketという名前のS3バケットを構築します。
環境設定
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"」を設定します。
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の認証情報を設定
}
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が作成されます。
{
"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は下記のようにします。
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を実行します
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化しておいて良かった」思えると思います。この記事が最初のハードルを乗り越える一助になれば幸いです。
最後に
弊社では、経験の有無を問わず、社員やインターン生の採用を行っています。
興味のある方はこちらをご覧ください。