コードでインフラを管理!CloudFormationで始めるIaCの実践
こんにちは!現役エンジニアのakrです。
「【AWSプロフェッショナルへの道】現役エンジニアが贈るクラウド実践ガイド」の第9回をお届けします。前回はDynamoDBでNoSQLデータベースの基本と実践を学び、アプリケーションのデータストアの選択肢を広げました。これまではマネジメントコンソールを使ってAWSリソースを構築してきましたが、ここから一歩進んだクラウドの運用方法に入っていきます。
今回は、AWSにおけるIaC (Infrastructure as Code) の中心的なサービスであるAWS CloudFormationを徹底的に解説します。IaCとは、「インフラをコードとして管理する」という考え方で、これによりインフラ構築の自動化、一貫性の確保、バージョン管理などが可能になります。
「毎回手作業でリソースを作るのは面倒...」「環境ごとに設定がバラバラになるのが怖い...」といった悩みを、CloudFormationがどのように解決してくれるのかを学びましょう。本記事では、IaCの概念から、CloudFormationテンプレートの作成、スタックのデプロイ、更新、そして基本的な運用までを網羅的に学び、実践的なIaCスキルを身につけます。
1. IaC (Infrastructure as Code) とは?なぜIaCが必要なのか?
まず、「IaC (Infrastructure as Code)」とは何か、そしてなぜ現代のクラウド運用において不可欠なのかを理解しましょう。
IaCは、従来の「手動でサーバーを構築し、ネットワークを設定する」といったインフラ管理の方法から脱却し、インフラストラクチャのプロビジョニングと管理を、コードとして定義し、自動化するアプローチです。
なぜIaCが必要なのか?
- 自動化と効率化: 手作業によるインフラ構築は時間がかかり、ヒューマンエラーの原因となります。IaCにより、インフラのデプロイと変更をスクリプトやテンプレートで自動化し、作業時間を大幅に短縮できます。
- 一貫性と再現性: 開発環境、ステージング環境、本番環境など、複数の環境で同じインフラを再現するのは手作業では困難です。IaCは、コードによって常に同じインフラをプロビジョニングできるため、環境間の一貫性を保証し、デプロイの信頼性を高めます。
- バージョン管理: インフラの定義がコードになるため、Gitなどのバージョン管理システムで管理できます。これにより、変更履歴の追跡、変更のレビュー、必要に応じたロールバック(元の状態に戻すこと)が容易になります。
- コラボレーション: チームメンバー間でインフラの定義を共有し、共同で開発・改善することができます。
- コスト削減: 不要なリソースを自動で削除したり、最適な構成をコードで管理することで、コスト効率の良い運用が可能になります。
CloudFormationは、AWSにおけるこのIaCを実現するための主要なツールです。
2. AWS CloudFormationとは?
AWS CloudFormationは、AWSリソースのコレクションを記述するためのテンプレートを作成し、そのテンプレートに基づいてリソースをプロビジョニング、更新、削除できるサービスオーケストレーションサービスです。
CloudFormationテンプレートは、YAMLまたはJSON形式で記述され、必要なAWSリソースとその設定(例: EC2インスタンスのタイプ、VPCのCIDRブロック、S3バケットのポリシーなど)を宣言的に定義します。
CloudFormationの主な特徴
- 宣言的: 「何を構築するか」を記述し、「どのように構築するか」はCloudFormationが自動的に判断して実行します。
- リソースオーケストレーション: 複数のAWSサービスにまたがる複雑なインフラスタック(例: VPC、EC2、RDS、ELBなど)を単一のテンプレートで一貫してデプロイできます。
- 依存関係の自動解決: テンプレート内で定義されたリソース間の依存関係をCloudFormationが自動的に解決し、正しい順序でリソースを作成します。
- ロールバック機能: デプロイ中にエラーが発生した場合、または手動でロールバックを指示した場合、CloudFormationはスタックを元の安定した状態に戻します。これにより、インフラの変更におけるリスクを低減できます。
- 変更セット: デプロイ前にテンプレートの変更が既存のインフラにどのような影響を与えるかをプレビューできます。
- クロスアカウント/クロスリージョンデプロイ: テンプレートを複数のAWSアカウントやリージョンにデプロイできます。
3. CloudFormationテンプレートの主要なセクション
CloudFormationテンプレートは、通常、以下の主要なセクションで構成されます。
3.1. AWSTemplateFormatVersion (オプション)
テンプレート形式のバージョンを指定します。現在の推奨バージョンは2010-09-09です。
3.2. Description (オプション)
テンプレートの説明文を記述します。
3.3. Metadata (オプション)
テンプレートに関する追加情報(例: 設計ツール、作成者)を記述します。
3.4. Parameters (オプション)
スタックを作成または更新する際に、ユーザーが入力する値を定義します。例えば、EC2インスタンスタイプや環境名などを動的に指定したい場合に利用します。
Parameters:
InstanceType:
Type: String
Default: t2.micro
Description: EC2インスタンスのタイプを選択してください
AllowedValues:
- t2.micro
- t3.micro
EnvironmentName:
Type: String
Description: 環境名を入力してください (例: dev, prod)
3.5. Mappings (オプション)
条件付きで値を指定したい場合に、キーと値の対応付けを定義します。例えば、リージョンごとに異なるAMI IDを指定する場合などに便利です。
Mappings:
RegionMap:
ap-northeast-1:
AMI: ami-0abcdef1234567890
us-east-1:
AMI: ami-0fedcba9876543210
3.6. Conditions (オプション)
特定のリソースを作成するかどうか、または特定のプロパティ値を割り当てるかどうかを制御する条件を定義します。
Conditions:
CreateProdResources: !Equals [ !Ref EnvironmentName, "prod" ]
3.7. Resources (必須)
テンプレートの主要なセクションであり、作成するAWSリソースを定義します。各リソースには論理IDを付け、リソースタイプとプロパティを指定します。
Resources:
MyVPC:
Type: AWS::EC2::VPC
Properties:
CidrBlock: 10.0.0.0/16
EnableDnsSupport: true
EnableDnsHostnames: true
Tags:
- Key: Name
Value: !Sub "${EnvironmentName}-VPC" # Parametersの値を参照
MyEC2Instance:
Type: AWS::EC2::Instance
Properties:
ImageId: !FindInMap [RegionMap, !Ref "AWS::Region", AMI] # Mappingsと組み合わせてAMIを選択
InstanceType: !Ref InstanceType # Parametersの値を参照
SubnetId: !Ref MySubnet # 同じテンプレート内の他のリソースを参照
SecurityGroupIds:
- !Ref MySecurityGroup
Tags:
- Key: Name
Value: !Sub "${EnvironmentName}-WebServer"
# 条件付きリソース作成の例 (prod環境のみ作成)
Condition: CreateProdResources
MySecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: Enable SSH access via port 22
VpcId: !Ref MyVPC # 同じテンプレート内の他のリソースを参照
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 22
ToPort: 22
CidrIp: 0.0.0.0/0
-
!Ref: 同じテンプレート内で定義されたパラメータやリソースの論理IDを参照します。 -
!Sub: 文字列内の変数(${変数名})を置換します。 -
!GetAtt: 特定のリソースの属性値を取得します(例:!GetAtt MyBucket.Arn)。 -
!FindInMap: Mappingsで定義された値を取得します。
3.8. Outputs (オプション)
スタックの作成後に、外部から参照できるリソースの情報を定義します。例えば、作成したELBのDNS名やS3バケット名などを出力して、別のCloudFormationスタックや外部ツールから参照できるようにします。
Outputs:
WebsiteURL:
Description: S3 Static Website URL
Value: !GetAtt MyBucket.WebsiteURL
Export:
Name: !Sub "${AWS::StackName}-WebsiteURL" # 他のスタックから参照可能にする
4. 実践!シンプルなWebサーバーをCloudFormationで構築してみよう
それでは、実際にCloudFormationテンプレートを作成し、EC2インスタンスとセキュリティグループをデプロイしてみましょう。今回はYAML形式で記述します。
4.1. CloudFormationテンプレートの作成 (web-server-template.yaml)
以下の内容でファイルを作成してください。
AWSTemplateFormatVersion: '2010-09-09'
Description: A simple web server stack with EC2 instance and Security Group.
Parameters:
EnvironmentName:
Type: String
Default: dev
Description: Name of the environment (e.g., dev, prod)
InstanceType:
Type: String
Default: t2.micro
AllowedValues:
- t2.micro
- t3.micro
- t3a.micro
Description: Choose your desired EC2 instance type.
LatestAmiId:
Type: 'AWS::SSM::Parameter::Value<AWS::EC2::Image.Id>'
Default: '/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2'
Description: Latest Amazon Linux 2 AMI ID from SSM Parameter Store.
VpcId:
Type: 'AWS::EC2::VPC::Id'
Description: The VPC ID where the EC2 instance will be launched.
PublicSubnetId:
Type: 'AWS::EC2::Subnet::Id'
Description: The Public Subnet ID for the EC2 instance.
KeyPairName:
Type: 'AWS::EC2::KeyPair::KeyName'
Description: Name of an existing EC2 KeyPair for SSH access.
Resources:
WebServerSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: Enable SSH and HTTP access for web server
VpcId: !Ref VpcId
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 22
ToPort: 22
CidrIp: 0.0.0.0/0 # 本番環境では特定のIPアドレスに制限してください
- IpProtocol: tcp
FromPort: 80
ToPort: 80
CidrIp: 0.0.0.0/0
Tags:
- Key: Name
Value: !Sub "${EnvironmentName}-WebServer-SG"
WebServerInstance:
Type: AWS::EC2::Instance
Properties:
ImageId: !Ref LatestAmiId
InstanceType: !Ref InstanceType
KeyName: !Ref KeyPairName
NetworkInterfaces:
- AssociatePublicIpAddress: true
DeviceIndex: 0
GroupSet:
- !Ref WebServerSecurityGroup
SubnetId: !Ref PublicSubnetId
UserData: !Base64 |
#!/bin/bash
yum update -y
yum install -y httpd
systemctl start httpd
systemctl enable httpd
echo "<h1>Hello from CloudFormation!</h1>" > /var/www/html/index.html
Tags:
- Key: Name
Value: !Sub "${EnvironmentName}-WebServer"
Outputs:
WebServerPublicIp:
Description: Public IP address of the web server
Value: !GetAtt WebServerInstance.PublicIp
Export:
Name: !Sub "${EnvironmentName}-WebServerPublicIp"
WebServerSecurityGroupId:
Description: ID of the Web Server Security Group
Value: !Ref WebServerSecurityGroup
Export:
Name: !Sub "${EnvironmentName}-WebServerSecurityGroupId"
このテンプレートは以下のAWSリソースを定義しています。
-
Parameters: 環境名、インスタンスタイプ、AMI ID、VPC ID、パブリックサブネットID、キーペア名を外部から入力できるようにしています。
-
AWS::SSM::Parameter::Value<AWS::EC2::Image.Id>: 最新のAMI IDを自動で取得する便利なParameterタイプです。
-
-
Resources:
-
WebServerSecurityGroup: SSH (22番ポート) とHTTP (80番ポート) のアクセスを許可するセキュリティグループを作成します。 -
WebServerInstance: EC2インスタンスを作成します。UserDataプロパティを使って、インスタンス起動時にApache Webサーバーをインストールし、簡単なHTMLページを配置するスクリプトを実行しています。
-
- Outputs: 作成されたWebサーバーのパブリックIPアドレスとセキュリティグループIDを出力し、他のスタックから参照できるようにエクスポートしています。
4.2. CloudFormationスタックの作成
作成したテンプレートを使って、AWSリソースをデプロイしましょう。
- AWSマネジメントコンソールにサインインし、「CloudFormation」サービスに移動します。
- 「スタックを作成」をクリックし、「新しいリソースを使用 (標準)」を選択します。
-
ステップ1: テンプレートの指定
- 「テンプレートファイルをアップロード」を選択し、「ファイルの選択」をクリックして、先ほど作成した
web-server-template.yamlファイルを選択します。 - 「次へ」をクリック。
- 「テンプレートファイルをアップロード」を選択し、「ファイルの選択」をクリックして、先ほど作成した
-
ステップ2: スタックの詳細を指定
-
スタックの名前:
MyWebServerStackなど、分かりやすい名前を設定します。 -
Parameters:
-
EnvironmentName:dev -
InstanceType:t2.micro -
VpcId: 前回作成したmy-web-app-vpcのIDを入力します。(VPCコンソールで確認できます) -
PublicSubnetId: 前回作成したmy-web-app-public-subnet-aのIDを入力します。(VPCコンソールで確認できます) -
KeyPairName: EC2コンソールで作成済みのキーペア名を選択します(例:my-web-server-keypair)。
-
- 「次へ」をクリック。
-
スタックの名前:
-
ステップ3: スタックオプションの設定 (オプション)
- タグ付けやIAMロールなどを設定できます。今回はデフォルトのままで「次へ」をクリック。
-
ステップ4: レビュー
- 設定内容を確認します。一番下までスクロールし、「AWS CloudFormation によって IAM リソースが作成される場合があることを承認します。」にチェックを入れます。
- 「スタックを作成」をクリック。
スタックの作成が開始されます。「イベント」タブで進捗を確認できます。ステータスが「CREATE_COMPLETE」になるまで数分待ちます。
4.3. 作成されたWebサーバーにアクセスしてみよう
スタックの作成が完了したら、Webサーバーにアクセスして確認しましょう。
- CloudFormationコンソールで、作成したスタック (
MyWebServerStack) を選択します。 - 「出力」タブをクリックします。
-
WebServerPublicIpに表示されているパブリックIPアドレスをコピーします。 - Webブラウザで、コピーしたIPアドレスにアクセスします。
Hello from CloudFormation! と表示されれば成功です!マネジメントコンソールでEC2インスタンスやセキュリティグループを確認すると、CloudFormationによってリソースが作成されていることが分かります。
4.4. スタックの更新 (テンプレートの変更)
インフラに変更を加える場合も、テンプレートを更新して適用します。
-
web-server-template.yamlを編集し、例えばHTMLのメッセージを変更してみましょう。# UserData の部分を以下のように変更 UserData: !Base64 | #!/bin/bash yum update -y yum install -y httpd systemctl start httpd systemctl enable httpd echo "<h1>Hello from CloudFormation - Updated!</h1>" > /var/www/html/index.html - CloudFormationコンソールで、スタック (
MyWebServerStack) を選択し、「更新」をクリックします。 - 「現在のテンプレートを置き換える」を選択し、「テンプレートファイルのアップロード」で更新した
web-server-template.yamlファイルを選択します。 - 「次へ」をクリックし、残りのステップを進めて「スタックを更新」をクリックします。
スタックの更新が完了したら、再度Webサーバーにアクセスし、メッセージがHello from CloudFormation - Updated!に変わっていることを確認してください。
4.5. スタックの削除
不要になったリソースは、スタックごと削除できます。これにより、関連するすべてのAWSリソースが自動的にクリーンアップされ、課金が停止します。
- CloudFormationコンソールで、スタック (
MyWebServerStack) を選択します。 - 「削除」をクリックします。
- 確認ダイアログで「削除」をクリック。
ステータスが「DELETE_COMPLETE」になるまで数分待ちます。関連するEC2インスタンスやセキュリティグループが全て削除されたことをEC2コンソールで確認できます。
5. CloudFormationのベストプラクティスと応用
- モジュール化とネストされたスタック: 巨大なテンプレートは管理が困難になります。VPC、EC2、RDSなど、機能ごとにテンプレートを分割し、それらを組み合わせて利用する「ネストされたスタック」を活用しましょう。
- 変更セットの活用: 本番環境にデプロイする前に、変更セットを作成して、テンプレートの変更が既存のスタックにどのような影響を与えるかを必ず確認しましょう。
- ドリフト検出: 手動で変更されたリソース(テンプレートの定義と実際の状態の乖離)を検出するために、「ドリフト検出」機能を活用しましょう。
- Gitとの連携: CloudFormationテンプレートをGitリポジトリで管理し、CI/CDパイプライン(AWS CodePipeline, GitHub Actionsなど)と連携させることで、インフラ変更の自動化と承認プロセスを確立できます。
- カスタムリソース: CloudFormationが直接サポートしていないAWSリソースや、AWS外のサービスをプロビジョニングしたい場合に、Lambda関数を使ってカスタムリソースを実装できます。
- スタックポリシー: 重要な本番環境のスタックに対して、誤った変更や削除を防ぐためにスタックポリシーを設定しましょう。
- ガードレール: AWS OrganizationsのService Control Policies (SCP) などと組み合わせて、組織全体でのIaCのベストプラクティスを強制するガードレールを設置しましょう。
まとめ
今回は、クラウドインフラをコードで管理するIaCの概念と、そのAWSにおける主要な実現手段であるAWS CloudFormationについて深く掘り下げました。
- IaCは、インフラの構築・管理を自動化し、一貫性、再現性、バージョン管理、コラボレーションを可能にします。
- CloudFormationは、AWSリソースを宣言的に定義するテンプレート(YAML/JSON)を使って、スタックとして一括でプロビジョニングします。
- テンプレートの主要なセクション(
Parameters,Resources,Outputsなど)の役割を理解しました。 - 実際にシンプルなWebサーバーのCloudFormationテンプレートを作成し、スタックの作成、更新、削除を実践しました。
CloudFormationを習得することで、あなたは手動でのインフラ構築から解放され、より効率的で信頼性の高いクラウド運用を実現できるようになります。これは、クラウドエンジニアとしてのスキルアップにおいて、非常に重要なステップです。ぜひ、ご自身の環境で様々なリソースをテンプレート化してみてください。
この記事が皆さんのAWS学習の一助となれば幸いです。
もしこの記事が役に立ったと感じたら、ぜひ「いいね」👍をお願いします!励みになります!
