はじめに
先日ランチタイムテックトークというお昼にラジオ感覚で技術の話を聞こうという社内のイベントで「IaCについて適当に喋る」と簡単な内容ではあったものの意外と好評だったので、記事にもまとめようと思います
ここ2年くらい案件でCloudFormationとTerraformに触ったので、個人的な所感をまとめたものです
IaCとは
IaCとはInfrastructure as Codeのことで、インフラ構成をコードで管理することです
IaCのメリット
- 再現性
→同じコードを使うと、同じリソースが作成される - 手作業の減少
→人的ミスが減り、自動化できる - バージョン管理ができる
→変更履歴を追うことができ、戻すのも楽
IaCのデメリット
- 学習コストが高い
- 1回しか作らない場合はコンソールから作った方が早い
代表的なIaCサービス
- AWS CloudFormation
・提供元:AWS
・対応クラウド:AWS
・記述言語:JSON、YAML
分岐やループのような組み込み関数が少なくわかりやすい
一方で、記述量が増えてしまう
- AWS CDK
・提供元:AWS
・対応クラウド:AWS
・記述言語:TypeScript、Python、C#など
CloudFormationをいい感じに動かしてくれる
元々開発している人なら慣れた言語で扱える
記述量が少なくなる(らしい)
- Terraform
・提供元:HashiCorp
・対応クラウド:AWS、GoogleCloud、Azureなど
・記述言語:HCL (Hashicorp Configuration Language)
対応しているクラウドが多いためマルチクラウドも可能
記述言語が専用で特に学習コストが高い
GoogleCloudは公式ドキュメントにもIaCツールとしてTerraformが使用されている
IaCを使う時に考慮したいこと
- モジュール化
管理しやすい単位でリソースを分割し1ファイルとして管理する
1ファイルが大きくなりすぎることを防ぐ
別のファイルから呼び出すこともできる
例)S3を1つ作るCloudFormationのテンプレートを子スタックとして、親スタックから呼び出す - CI/CD
CloudFormationとGithubを連携したり、Githubアクションを使用して特定のブランチにプッシュされるのをトリガーとすることで、デプロイを自動化できる - セキュリティ
Githubなどのコード管理ツールで管理することが多く、SecretManagerなどを利用しリポジトリに機微情報が載らないように注意が必要
実際に動かしてみた
今回は社内イベントの中でCloudFormationを実際に動かしてみました
手順としては
- テンプレートを用意する
※社内イベントで使ったテンプレートを後ろに載せておきます - AWSコンソールにログインする
- CloudFormation用のIAMロールを作成する
リソースを作るのはCloudFormationなので、必要な権限を与えます
後述するテンプレートだとEC2のフルアクセスとssmの読み取りで動きます
※実際のシステムで使う場合は最小権限を意識しましょう - CloudFormationのスタックを作成する
作成したテンプレートとIAMロールを指定してスタックを作成します
パラメータはこの時に入力します - 作成されたリソースを確認する
- (リソースを削除する)
検証で作成した場合は余計なコストが発生しないように作成したリソースを削除します
基本的にはスタックを削除すると、スタックが管理しているリソースは消えますが、削除ポリシーで保持の設定をしていたり、IAMロールに削除権限が無いとリソースが残ってしまうので注意
今回の社内イベントの中で実際にCloudFormationを動かしてみた時のテンプレートを載せておきます
作成したリソースはVPC関連とEC2です
AWSTemplateFormatVersion: '2010-09-09'
Description: 'Create an EC2 instance in a public subnet within the free tier'
Parameters:
SystemName:
Type: String
Default: MySystem
Description: 'System name'
EnvironmentName:
Type: String
Default: Dev
Description: 'Environment name'
Resources:
MyVPC:
Type: AWS::EC2::VPC
Properties:
CidrBlock: 10.0.0.0/16
EnableDnsSupport: true
EnableDnsHostnames: true
Tags:
- Key: Name
Value: !Sub "${SystemName}-${EnvironmentName}-VPC"
MyInternetGateway:
Type: AWS::EC2::InternetGateway
AttachGateway:
Type: AWS::EC2::VPCGatewayAttachment
Properties:
VpcId: !Ref MyVPC
InternetGatewayId: !Ref MyInternetGateway
MyPublicSubnet:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref MyVPC
CidrBlock: 10.0.1.0/24
MapPublicIpOnLaunch: true
AvailabilityZone: !Select [0, !GetAZs '']
Tags:
- Key: Name
Value: !Sub "${SystemName}-${EnvironmentName}-PublicSubnet"
MyRouteTable:
Type: AWS::EC2::RouteTable
Properties:
VpcId: !Ref MyVPC
Tags:
- Key: Name
Value: !Sub "${SystemName}-${EnvironmentName}-RouteTable"
MyRoute:
Type: AWS::EC2::Route
DependsOn: AttachGateway
Properties:
RouteTableId: !Ref MyRouteTable
DestinationCidrBlock: 0.0.0.0/0
GatewayId: !Ref MyInternetGateway
MySubnetRouteTableAssociation:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
SubnetId: !Ref MyPublicSubnet
RouteTableId: !Ref MyRouteTable
MySecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: Allow SSH and HTTP
VpcId: !Ref MyVPC
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 22
ToPort: 22
CidrIp: 0.0.0.0/0
- IpProtocol: tcp
FromPort: 80
ToPort: 80
CidrIp: 0.0.0.0/0
Tags:
- Key: Name
Value: !Sub "${SystemName}-${EnvironmentName}-SecurityGroup"
MyInstance:
Type: AWS::EC2::Instance
Properties:
InstanceType: t2.micro
ImageId: !Sub "{{resolve:ssm:/aws/service/ami-amazon-linux-latest/al2023-ami-kernel-default-x86_64}}"
SubnetId: !Ref MyPublicSubnet
SecurityGroupIds:
- !Ref MySecurityGroup
Tags:
- Key: Name
Value: !Sub "${SystemName}-${EnvironmentName}-EC2"
さいごに
かなり基本的な内容だったので日頃からIaCを触っている人には少し退屈な内容だったかもしれないですが、これからIaCを触ってみようと思っている人やIaCって聞いたことあるくらいの人が興味を持つきっかけになってたら嬉しいです