CloudFormationテンプレートを編集してVPCの変更やセキュリティグループの紐づけをしてみました。

どうもさいちゃんです。今回はCloudFormationでインスタンスを立ち上げ、テンプレートを編集することで細かいインスタンスの設定に挑戦してみました。
2022.02.14

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

今回はCloudForemationを使ってインスタンスを立ち上げてテンプレートを編集してみました。何度かCloudForemationを使ったことはあったのですが、インスタンスタイプの指定やVPC載せていなど細かいところを指定する方法が知りたかったのでCloudForemationのハンズオンを受講してみようと思い立ちました。

参考にしたのはこちらのハンズオンです。早速やってみました。

CloudForemationの概要

CloudForemationはAWS環境のコードによる管理を実現し、テンプレートで定義した環境の作成、変更、削除を行うことが可能なサービスです。

テンプレートに定義された構成で自動的に環境構築、依存関係の解決をしてくれるので、何度も同じ構成の環境を作りたい時など便利に利用することができます。

テンプレートはスタック作成後も何度も編集を加えることができるので、似たような環境だけどインスタンスタイプだけを変更して再度立ち上げたい。ってときなんかにも利用できます。


ハンズオンを受ける前の前知識としてはこんな感じのざっくりのイメージしかありませんでした。

ではさっそくテンプレートの編集をしていきたいと思います。

やってみた

当ブログではすでにVPCをCloudForemationを使って立ち上げたところから始めていきます。VPCの立ち上げ方等は上記のハンズオンを参考にしました。

今回はこちらのテンプレートを修正しながらEC2インスタンスを立ち上げたいと思います。

AWSTemplateFormatVersion: 2010-09-09
Description: Hands-on template for EC2

Parameters:
VPCStack:
    Type: String
    Default: handson-cfn
EC2AMI:
    Type: AWS::SSM::Parameter::Value<AWS::EC2::Image::Id>
    Default: /aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2

Resources:
EC2WebServer01:
    Type: AWS::EC2::Instance
    Properties:
    ImageId: !Ref EC2AMI
    InstanceType: t2.micro

Outputs:
EC2WebServer01:
    Value: !Ref EC2WebServer01
    Export:
    Name: !Sub ${AWS::StackName}-EC2WebServer01


Parametersセクションはテンプレートのカスタマイズを記述しています。パラメーターを記述するとスタック作成、更新のたびにテンプレートにカスタム値を入力することができます。

これを利用することで、構成はほとんど同じでも細部の違うインスタンスを建てたいという際利用します。概要で説明したような、構成は同じだけどインスタンスタイプを変えたい時なんかに使うと新たにテンプレートを作り直さなくてもいいので便利です。

Resourcesセクションは必須です。ここにはスタックに含めるリソースを記述します。ここを今回は修正していきたいと思います。

Outputsセクションでは、他のスタックで値を参照したり、CloudForemationコンソールに値を出力したりする際に使います。今回はEC2の情報を出力する際の情報を記述しています。これによってELBとの連携などに用いることができます。

EC2スタックの立ち上げ

まずはCLIでスタックを立ち上げていきます。今回はCloud9を使って行きます。

最初に~/environment/cfnディレクトリに移動をしてから、下記コマンドを実行します。

aws cloudformation create-stack --stack-name EC2スタック名 --template-body file://ファイル名

CloudFormationの画面を確認するとスタックが作成されていることがわかります。

VPCの変更とユーザーデータの追記

CloudForemationリファレンスEC2インスタンスの項目を参考にテンプレートを編集していきます。

ここでやりたいことは以下の通りです。

  • VPCをデフォルトから自身が作成したモノに変更(サブネットIDを使用)
  • WordPressを使用するためのユーザーデータの追記
  • セキュリティグループの追加
SubnetId:(指定したいサブネットIDを記述)

上記をResourcesの一番最後に追記します。最初のテンプレートではこちらを指定していないため、インスタンスはデフォルトVPCで作成されています。

サブネットIDを指定することで、インスタンスの入れ替えが行われます。元々使っていたインスタンスから新たに指定したサブネットにインスタンスが再作成されるということです。

これはイメージIDを指定する場合も同じようです。


ここで注意なのですが、テンプレートを編集した際には必ずCtrl+Sで保存してください。ここで保存をしないと検証してもエラーは出ないのに、更新ができないという事態が発生してしまいます。(初回ここでハマりました。。)

aws cloudformation validate-template --template-body file://ファイル名

次にCLI上でこちらのコマンドを実行します。このaws cloudformation validate-templateコマンドは変更したテンプレートの構文が正しく書かれているかの検証を行うものです。

こんな感じで帰ってくれば、構文は問題ないということです。逆にここでエラーが返される場合は構文ミスがあるので確認してみる必要があります。

次にユーザーデータの追記です。

UserData: |
    #! /bin/bash
    yum update -y
    amazon-linux-extras install php7.2 -y
    yum -y install mysql httpd php-mbstring php-xml

    wget http://ja.wordpress.org/latest-ja.tar.gz -P /tmp/
    tar zxvf /tmp/latest-ja.tar.gz -C /tmp
    cp -r /tmp/wordpress/* /var/www/html/
    touch /var/www/html/.check_alive
    chown apache:apache -R /var/www/html

    systemctl enable httpd.service
    systemctl start httpd.service

こちらを先ほどのSubnetIdのすぐ下に記述します。ここで注意したいのが最初の:の後にスペース+|を入れることです。

yamlでは複数行を記述する際にはコロンの後にスペース+|を記述しないと一行の文字列として解釈されてしまいそのままテンプレートの検証が通ってしまいますので注意が必要です。


次にbase64エンコードを実行するための組み込み関数を記述します。こちらに関しては組み込みリファレンス(Fn::Base64)に説明があります。

!Base64これをの前に記述することで見た目はテキストのままでユーザーデータプロパティに対してはbase64エンコードを行った状態にすることができます。

ここでテンプレートを保存したのちに、先ほどのaws cloudformation validate-template --template-body file://ファイル名という検証コマンドを再度実行し、テンプレートの検証を行います。

異常がなければ下記の更新コマンドを実行します。これはtwンプレートに変更を加えた後にスタックを更新するコマンドです。

aws cloudformation update-stack --stack-name スタック名 --template-body file://ファイル名


異常がなければこのように帰ってきます。

行った変更がしっかりインスタンスに反映されているか確認してみましょう。

新しく作成したEC2のVPCやサブネットがデフォルトのものからハンズオン用に作成したモノに代わっていることが分かります。

同じようにユーザーデータも確認します。作成したEC2インスタンスを右クリックしインスタンスの設定→ユーザーデータを編集を選択し、中身を確認します。

しっかりユーザーデータの中身が反映されていました。

セキュリティグループの追加

今回セキュリティグループではELBを含むプライベートネットワークからのHTTPによるアクセスを許可する設定にしていきます。


ちなみにセキュリティグループを指定するにはSecurityGroupIds: SecurityGroups:で指定する2つの方法がありますが、後者はEC2クラシックやデフォルトVPCで使用するものになっています。なので、今回は SecurityGroupIds:を使っていきます。

SecurityGroupIds:ではセキュリティグループのIDを指定する必要があるので、先にセキュリティグループの作成を行います。

Resourcesにセキュリティグループの設定を追加していきます。

EC2SG:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: sg for web server
      VpcId:(指定したいVPCIDを記述)
      SecurityGroupIngress:
        - IpProtocol: tcp
          CidrIp: 10.0.0.0/16
          FromPort: 80
          ToPort: 80

CidrIPではVPC全体を示す値を設定しておきます。FromPortToPortではHTTPを表す80を指定しておきます。

これで先ほどと同じようにテンプレート保存後aws cloudformation validate-template --template-body file://ファイル名で検証をして、問題がなければaws cloudformation update-stack --stack-name スタック名 --template-body file://ファイル名でアップデートします。

CloudForemation側の画面でリソースを確認すると、新たにセキュリティグループができていることが確認できます。

セキュリティグループのインバウンドルールを確認するとちゃんと意図した設定になっていることがわかります。

それではこの作成したセキュリティグループをインスタンスに紐づけていきます。


ResourcesEC2WebServer01の一番最後にこちらを追記します。

SecurityGroupIds:
- !Ref EC2SG

セキュリティグループのIDではなく組み込み関数の!Refを使いEC2SGを指定します。

保存→検証に問題がなければupdate-stackコマンドを使いスタックを更新します。

その後EC2を確認してみるとセキュリティグループがしっかり反映されていることが確認できます。

感想

CloudForemationのテンプレートを編集していくにはYAMLファイルを編集するのでその辺の知識がない分不安でしたが、ユーザーガイドにはサンプルテンプレートはもちろんテンプレートリファレンスやトラブルシューティングガイドが用意されているので、コード書くのが苦手な私でも、思いのほか詰まることなくテンプレートを編集することができました!

AWSをうまく活用する一番の近道はやはり公式ドキュメントをうまく活用していくことですね!