インフラやクラウドの専門というわけではないのですがそろそろIaC周りもちゃんと勉強しておきたい・・・という感じなのでAWSのCloudFormationについて入門しつつ復習として記事にまとめておきます。
※とりあえず最初ということでEC2を絡めたごく基本的なところの記事を書いていきます。将来もしかしたら3記事目以降を執筆して追加のEC2関係や他の様々なサービスや機能などにも触れていくかもしれません。
注意事項と記事までの振り返り
本記事の処理を動かすとEC2関係などで色々と追加になったり起動したりします。その辺はリソースの停止や削除などをしないとお金がかかったりしてくる可能性があるためご注意ください。
また、本記事は2記事目となります。前回までの内容を踏襲していく形となっているのでご注意ください。
1記事目:
前回までに設定した主な内容:
-
cloudformation-test-1
とcloudformation-test-2
という名前でのEC2のキーペアを追加しました。 - 以下のような形のYAMLテンプレートで
my-first-ec2-instance
という名前でスタックが作成済みとなります(ただし最後に変更セット失敗時の挙動を試したので最終的なステータスはUPDATE_ROLLBACK_COMPLETE
となっています。変更セットなどによる更新は効くのでそのまま使っていきます)。
AWSTemplateFormatVersion: "2010-09-09"
Resources:
MyFirstEC2Instance:
Type: AWS::EC2::Instance
Properties:
ImageId: ami-0590f3a1742b17914
InstanceType: t2.nano
KeyName: cloudformation-test-2
また、前回の記事中で追加したインスタンスリソースを(コストなどの面を加味して)停止状態などにしていた場合には再開前に起動しておきます(起動していないとCloudFormationの操作でエラーになったりします)。
停止済みになっている場合にはEC2のインスタンスのページに遷移し、runningのフィルターを外して表示されるインスタンスを選択しインスタンスの状態 → インスタンスを開始のメニューを選択して起動しておきます。
触れること
- EC2インスタンスリソースでのCloudFormation上でのセキュリティグループの設定
- セキュリティグループの一部説明
- EC2インスタンス以外のリソースとなるセキュリティグループのリソース追加設定
- 追加したセキュリティグループのEC2インスタンスリソースへの組み込み関数を使用した設定
既存のセキュリティグループのEC2インスタンスへの設定方法
既存のセキュリティグループをEC2インスタンスのリソースへと追加していきます。
セキュリティグループなど自体に関しては引用程度に留めてこの記事では触れません。必要に応じて以下の記事などをご確認ください。
1.セキュリティグループとは?
・Amazon EC2 インスタンスに適用可能なAWS標準のファイアウォール機能であり、EC2インスタンスへのアクセスを"許可"したり、トラフィックを"制御"することができます。
まずは既存の存在するセキュリティグループを確認します。EC2関係のページに遷移し、左のメニューのネットワーク&セキュリティの部分からセキュリティグループのメニューをクリックします。
そうすると作成済みのセキュリティグループ一覧が表示されます。今回は勉強用の個人のAWSアカウントなのでセキュリティグループ名がdefault(最初から追加されているもの)のみ存在しています。
今回はこのdefaultのセキュリティグループをCloudFormation上で設定していきます。
CloudFormation上ではEC2のProperties
部分にSecurityGroups
キー名を追加して、設定するセキュリティグループ名をリストで指定します。以下のような感じになります。
AWSTemplateFormatVersion: "2010-09-09"
Resources:
MyFirstEC2Instance:
Type: AWS::EC2::Instance
Properties:
ImageId: ami-0590f3a1742b17914
InstanceType: t2.nano
KeyName: cloudformation-test-2
SecurityGroups:
- default
さっそくこのYAMLテンプレートをアップロードしていきます。スタックのページに移動して既存のスタックを選択 → スタックアクション → 既存スタックの変更セットを作成メニューをクリックします。
既存テンプレートを置き換える → テンプレートファイルのアップロードを選択して対象のYAMLをアップロードします。
後はパラメータやタグ設定などはスキップして次へボタンを何回か押して進めます。
レビュー画面で変更セットの作成ボタンをクリックします。変更セット名はadd-default-security-group
としました。
変更セットの作成画面に移ったらしばらく待ってリロードし、ステータスがCREATE_COMPLETE
になるまで待ちます。
今回は置換がTrueとなっているので既存のインスタンスの破棄と作り直しが実行されます。
特に今回は置換が走っても問題ないためそのまま変更セットを実行ボタンをクリックします。
イベントの画面になるためステータスがUPDATE_COMPLETE
になるまでしばらく待ちます。リロードしてUPDATE_COMPLETE
と出れば追加したセキュリティグループの設定が問題なく通っています。
EC2インスタンスのページに遷移して作成されたインスタンスを選択 → セキュリティのタブを表示するとdefaultのセキュリティグループが設定されていることが確認できます。
※defaultのセキュリティグループはCloudFormation上で指定していなくともEC2インスタンス作成時に付与されるためdefaultのセキュリティグループしか使わない場合にはCloudFormation側は省略しても結果は変わりません。この節ではCloudFormation上でのセキュリティグループの設定とその設定がエラーにならないことを確認しています。
セキュリティグループの追加時の設定項目の確認と各項目の説明
defaultのセキュリティグループ設定だけだと微妙なので追加でセキュリティグループの追加をCloudFormation上で対応してみます。
まずはセキュリティグループの設定でどんな項目が存在しているのかをwebコンソールで確認します。
EC2のセキュリティグループのページを開いて右上のセキュリティグループを作成ボタンをクリックします。すると以下のような設定項目が画面に表示されます。
- セキュリティグループ名
- 説明
- VPC
- インバウンドルール
- アウトバウンドルール
- タグ
また、インバウンドルールでルールを追加をクリックしてみると以下のような項目があることが確認できます。
- タイプ
- プロトコル
- ポート範囲
- ソース
- 検索フォーム
- 説明
検索フォーム部分はクリックしてみるとCIDR ブロックを選択する形となっていることが確認できます。
タイプやポート範囲、説明などの項目は分かりやすいので説明は本記事では割愛しますが、インバウンドルールやアウトバウンドルール、CIDR ブロックに関しては少し触れておきます。
AWSのセキュリティグループのインバウンドルールは外部から対象のEC2インスタンスへの通信の許可設定となります。
外部からのアクセス設定となるため、基本的に最低限のみ開放する形が好ましくなります(webサーバーであればweb関係のポートのみ開放するなど)。
デフォルトでは設定を追加するまで外部からのトラフィックは弾かれるようになっているようです。
セキュリティグループを作成するときには、インバウンドルールはありません。インバウンドルールをセキュリティグループに追加するまでは、別のホストからインスタンスに送信されるインバウンドトラフィックは許可されません。
インバウンドルールというのは、そのEC2インスタンスにアクセスできるトラフィックに制限をするためのルールです。AWSでEC2インスタンスを起動する場合にセキュリティグループをEC2インスタンスに対して設定しますが、インバウンドルールを最低限必要なIPアドレス、ポートのみに限定することでEC2インスタンスを安全にすることができます。
...
EC2インスタンスを安全に使うために、セキュリティグループのインバウンドルールをできる限り最小限に限定することは、一番重要な対策です。ただ、一般ユーザー向けにWebサーバを公開する場合など「任意の場所」に対してアクセスを許可しなければいけない場合もあるかと思います。
アウトバウンドルールは逆にEC2インスタンス側から外部へと通信する際の制限設定です。例えばDBを設置してあるインスタンスで、クエリ結果のデータを別のホストへと送信する・・・みたいなものもアウトバウンドのものに該当します。
インバウンドルールと比べるとこれに起因して外部から攻撃を受けやすい・・・という感じではないのでデフォルトでは全ての別のホストへのアウトバウンドトラフィックは許可されているようです(ただしドキュメント上ではこの全てのトラフィックを許可する設定は削除して特定のもののみに制限するといったことが推奨されています)。
デフォルトでは、セキュリティグループにはすべてのアウトバウンドトラフィックを許可するアウトバウンドルールが含まれています。このデフォルトのルールを削除し、特定のアウトバウンドトラフィックのみを許可するアウトバウンドルールを追加することをお勧めします。
CIDR(サイダー)はIPアドレスのネットワーク部分とホスト部分のサブネットマスク関係などを柔軟に扱う仕組みです。
xxx.xx.xxx.xxx/yy
みたいなスラッシュとその後の桁数指定を含んだIPアドレスが該当します。
この辺は以下の記事などがとても分かりやすいので必要に応じてご確認ください。
ちなみに後述の節で0.0.0.0/0
というCIDRの指定が出てきます。これは全てのIPアドレスを対象とする、という指定に該当するようです。
0.0.0.0/0 means from the whole Internet
追加のセキュリティグループをCloudFormation上で用意する
セキュリティグループの追加をCloudFormation上で行いたい場合にはEC2インスタンスのリソース部分とは別のリソースとしてYAML上で記述します。
TypeのキーにはAWS::EC2::SecurityGroup
を指定します。
※EC2関係のTypeの一覧は以下のドキュメントをご確認ください。
リソース名(論理ID)部分は任意の文字列を指定できます。今回はMySecurityGroup
としました。
セキュリティグループの説明はProperties
の部分にGroupDescription
キーを追加することで設定ができます。
セキュリティグループ追加のリソース設定部分だけ抽出すると以下のような感じになります。
MySecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: My new security group
過去に扱ったEC2インスタンスリソースも含めるとYAMLは以下のようになります。なお、この時点では新しいセキュリティグループは追加されるものの追加されたセキュリティグループがEC2インスタンスは設定される・・・といった挙動はしません(追加のみとなります)。その辺のEC2インスタンスへの設定関係は後々触れます。
AWSTemplateFormatVersion: "2010-09-09"
Resources:
MyFirstEC2Instance:
Type: AWS::EC2::Instance
Properties:
ImageId: ami-0590f3a1742b17914
InstanceType: t2.nano
KeyName: cloudformation-test-2
SecurityGroups:
- default
MySecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: My new security group
一旦このYAMLをアップロードしていきます。前節までと同様なのでスクショは割愛しますが、CloudFormationのスタックのページで既存のスタックを選択し、スタックアクション → 既存スタックの変更セットを作成 → 既存テンプレートを置き換える → テンプレートファイルのアップロードを選択してYAMLのアップロードを対応します。パラメータやタグ設定などはそのまま変更せずに進めます。
変更セット名はadd-my-new-security-group
としました。
変更セットを作成してステータスがCREATE_COMPLETE
になるまでリロードしつつ待ちます。
CREATE_COMPLETE
になってから変更部分を確認すると、EC2インスタンス関係は表示されず、セキュリティグループ関係のみの追加となっていることが分かります。既存のものには影響しないので置換に関してもハイフン表示になっています。
変更セットの実行をクリックして反映処理をスタートさせます。今回はセキュリティグループの追加のみなので10秒強くらいでさくっとステータスがCREATE_COMPLETE
とUPDATE_COMPLETE
になりました。セキュリティグループ側はCREATE_COMPLETE
となっていることから分かるように、正常に作成処理が動いてくれています。
EC2のセキュリティグループのページにアクセスしてみると、default以外のCloudFormation経由で作成されたセキュリティグループが追加になっていることを確認できます。説明部分も設定したGroupDescription
の値が反映されていることを確認できます。
ただしEC2インスタンスリソース側へは追加したセキュリティグループの指定などはまだしていないため、EC2のページのセキュリティタブを見てみるとdefaultのセキュリティグループのみ設定されています。
次節で追加したセキュリティグループのEC2インスタンスへの反映について触れていきます。
CloudFormation上で追加したセキュリティグループをCloudFormation上でEC2インスタンス側に設定する
追加したセキュリティグループのリソースがEC2インスタンスリソース側に設定されるように調整してみます。
CloudFormation上で他のリソースへアクセスする(例 : EC2インスタンスリソースからセキュリティグループのリソースへのアクセス等)場合にはCloudFormationのRef関数が必要になります。
CloudFormationには数はそこまで多くありませんが、YAML上で使用できる組み込み関数が以下のドキュメントに記載されているようにいくつか用意されています。
Ref関数はその組み込み関数の1つであり、Ref関数によって指定されたパラメータもしくはリソースを参照することができます。
YAMLでの書き方は上記のドキュメントにはRef: logicalName
といったように書かれています。logicalName
のところはCloudFormation上で指定したリソースのリソース名(論理ID)を指定します。今回は追加したセキュリティグループのものを指定したいためMySecurityGroup
を指定する形となるため、Ref: MySecurityGroup
といった形になります。
上記の記述をEC2インスタンスのリソースのSecurityGroups
のリスト部分に追加します。YAMLの記述は以下のようになりました。
AWSTemplateFormatVersion: "2010-09-09"
Resources:
MyFirstEC2Instance:
Type: AWS::EC2::Instance
Properties:
ImageId: ami-0590f3a1742b17914
InstanceType: t2.nano
KeyName: cloudformation-test-2
SecurityGroups:
- default
- Ref: MySecurityGroup
MySecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: My new security group
上記YAMLをCloudFormationでアップしてみます。
スタックのページで既存のスタックを選択してスタックアクション → 既存スタックの変更セットの作成 → 既存テンプレートを置き換える → テンプレートファイルのアップロードを選択してYAMLをアップし、タグやパラメータなどは変えずに進めます。
変更セット名はadd-security-group-reference-from-ec2-instance
としました。
作成された変更セットでステータスがCREATE_COMPLETE
になるまでリロードしつつ待ちます。
今回はEC2インスタンス側が変更のリストに表示されています。セキュリティグループの追加の場合も置換がTrueとなるようです。
変更セットを実行ボタンを押して反映します。発行されるイベントでステータスがUPDATE_COMPLETE
などになるまでリロードしつつ待ちます。
ステータスがUPDATE_COMPLETE
などになったらEC2のページにアクセスして、置換されたインスタンスを選択してセキュリティのタブを表示するとdefault以外のRef関数で設定したセキュリティグループが対象のインスタンスに設定されていることが確認できます。
組み込み関数の短縮系での書き方について
CloudFormationの組み込み関数には!の記号を付けることで短縮系で記述することも可能です。
前述のRef関数だとRef: logicalName
という書き方の代わりに!Ref logicalName
といったように書いても同様の挙動になります。
正直Ref関数に関しては短縮系でも記述が短くならないので使わなくとも良いという所感ですが他の組み込み関数に関してはぼちぼち短く書くことができます。
例えばFn::Cidr
関数であれば短縮系になると!Cidr
となります。
どちらを使用しても挙動は変わりませんのでお好きな方をお使いください。
セキュリティグループにCloudFormation上からインバウンドルールを追加してみる
今度は追加したセキュリティグループのリソースにCloudFormation上でインバウンドルールを追加してみます。
インバウンドルールを追加するには対象のセキュリティグループのProperties
以下にSecurityGroupIngress
というキー名で設定を追加します(ちなみにアウトバウンドルールの場合にはSecurityGroupEgress
というキー名になります)。
SecurityGroupIngress
内の設定としてはプロトコルタイプのIpProtocol
、ポート範囲のためのFromPort
とToPort
、CIDRの指定用のCidrIp
などを設定します。
今回は22のポートのみを開放する形でIpProtocol
にtcp、FromPort
に22、ToPort
にも22、CidrIp
には0.0.0.0/0を指定する形にしてみます。
以下のような記述になります。
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 22
ToPort: 22
CidrIp: 0.0.0.0/0
YAML全体だと以下のようになります。
AWSTemplateFormatVersion: "2010-09-09"
Resources:
MyFirstEC2Instance:
Type: AWS::EC2::Instance
Properties:
ImageId: ami-0590f3a1742b17914
InstanceType: t2.nano
KeyName: cloudformation-test-2
SecurityGroups:
- default
- Ref: MySecurityGroup
MySecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: My new security group
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 22
ToPort: 22
CidrIp: 0.0.0.0/0
前節までと同様にYAMLをアップロードする形で変更セットを作成して反映します。変更セット名はadd-ingress-rule-to-security-group
としました。
作成された変更セットのステータスがCREATE_COMPLETE
になってから変更内容を確認してみるとセキュリティグループのみの更新且つ置換がFalseとなっていることが確認できます。インバウンドルールの追加だけであればどうやら既にEC2インスタンスに設定されているセキュリティグループの変更の場合でも置換は走らないようです。
変更セットの実行をクリックして反映処理をスタートさせます。リロードしつつ待っていると、20秒強程度でステータスがUPDATE_COMPLETE
となったようです。
EC2インスタンスのページに遷移して対象のインスタンスを選択しセキュリティタブを表示すると、インバウンドルール部分でポート範囲に22、プロトコルにTCP、ソース部分にはCIDRの0.0.0.0/0が反映されていることが確認できます。
大分長くなってきたため本記事は一旦ここで区切ります。残りは3記事目以降で触れていこうと思います。
参考サイト・講座・文献まとめ