プロパティの指定は多岐に渡るため、細かい指定を暗記する必要はありません。
公式ドキュメントを検索し、素早く読み解けるようになることが重要です。
AWSTemplateFormatVersion: 2010-09-09
Resources:
MyVPC2:
Type: AWS::EC2::VPC
Properties:
CidrBlock: 10.0.8.0/21
EnableDnsSupport: true
Tags:
- Key: Name
Value: MyVPC2fromCF
subnetName:
Type: AWS::EC2::Subnet
Properties:
AvailabilityZone: "ap-northeast-1a"
VpcId: !Ref MyVPC2
CidrBlock: 10.0.8.0/24
Tags:
- Key: Name
Value: subnet1formCF
secGroupName:
Type: AWS::EC2::SecurityGroup
Properties:
GroupName: GroupName-SG
GroupDescription: GroupDescription-SG
VpcId: !Ref MyVPC2
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 22
ToPort: 22
CidrIp: 0.0.0.0/0
Tags:
- Key: Name
Value: SGfromCF
Outputs:
Subnet1:
Value: !Ref subnetName
Export:
Name: Subnet1Name
SG1:
Value: !GetAtt secGroupName.GroupId
Export:
Name: SG1Name
AWSTemplateFormatVersion: 2010-09-09
Resources:
myEC2Instance:
Type: t2.micro
Properties:
SecurityGroupIds:
- !ImportValue SG1Name
SubnetId: !ImportValue Subnet1Name
Tags:
- Key: Name
Value: CFec2
【CloudFormation講座5】クロススタック参照 / Outputsセクション / ImportValue関数 / GetAtt関数
【13:24】
(0:00)
今回の講座では、クロススタック参照 / Outputsセクション / ImportValue関数 / GetAtt関数について学んでいきます。
(0:06)
こちらが前回までのハンズオンの結果です。テンプレートバージョン3と、VPC/サブネット/セキュリティグループが紐付いた状態です。右側に実際に稼働しているAWSサービスを表してみました。同様にVPC/サブネット/セキュリティグループが稼動しています。
こちらにEC2インスタンスを1つ、CloudFormationで作成していきます。
新しいCloudFormationをもう1つ作成して、こちらにEC2を作成する記述を行い、テンプレートを分けていきましょう。EC2専用のテンプレートとスタックを作っていきます。ではなぜ、わざわざテンプレートを分けるのでしょうか。
こちらはBlackbeltからの引用ですが、1つのCloudFormationテンプレートに記述しても良いですが、それだとかなり長くなってしまいます。いろいろな思想がありますが、基本的にはリソースの種類によってCloudFormationを分割すべしという考え方があります。
では、どのように分割するか。こちらに記載されているとおり、一番下にはネットワークレイヤー、VPC/サブネット/エンドポイント/ルートテーブル/内部DNS/インターネットゲートウェイなど、ネットワーク関連のスタックを作るCloudFormationテンプレートを1つ、もう1つはセキュリティレイヤーですね、セキュリティグループ/IAMグループ、ロール、ポリシーなど、セキュリティ関連のスタックを作るCloudFormationテンプレートを1つ、最後にアプリケーションレイヤーとして、これはEC2/RDS/ロードバランサーなど、お客さんへ提供するアプリケーション部分のレイヤー、このように3つの階層にするという考え方が基本となります。
(1:51)
そして異なるCloudFormationテンプレート同士で参照し合う状態が発生します。これをクロススタックといいます。前に説明したRef関数は、同一テンプレート内でしか値を参照できません。今回は新しくEC2インスタンスのテンプレートを作成して、別のテンプレートで作成されたセキュリティグループの値を参照しなければなりません。
他のスタックのリソースを参照する方法はクロススタックになりますけれども、こちらのスライドで、具体的にクロススタックをやる方法についてざっくりと解説して、後ほどハンズオンで実際にやってみましょう。
(2:25)
まずざっくり、クロススタックをするためには、Outputsというセクションで、他のテンプレートから参照させる準備が必要になります。Outputsでサブネットとセキュリティグループを、他のテンプレートから参照できる状態にさせてあげます。そしてもう1つのテンプレートで、Ref関数ではなく、ImportValueという関数を使用します。Outputsで出力された、Nameという赤枠で囲った部分を、!ImportValue[スペース]名前で参照します。
こうみると複雑そうに見えますけれども、大丈夫、簡単ですので安心して下さい。なお、これからやるハンズオンでは、GetAtt関数というものも使用します。GetAtt関数については、論理ID内のどの属性を指定するかを指定しますが、ハンズオンをやっていく中で実際の動きを見たほうが理解が早まりますので、早速デモをやっていきましょう。
(3:18)
それではCloudFormationテンプレートを使ってEC2インスタンスを作成していきましょう。
VSCodeのこちらのボタンを押しますと、新しいファイルが作成されますので、ec2.ymlとしておきましょう。なお、こちらのボタンを押しますと、画面が分割されますので、左側にネットワークのテンプレート、右側にEC2のテンプレートを参照しながら書いていきましょう。こちらにstartと打って骨格を表示させまして、Resources以外を削除しましょう。Resourcesの下でec2と打ちますと、EC2インスタンスの骨格が作成されます。
(3:56)
EC2インスタンスを作成するのに指定する箇所があります。必須の項目、例えばセキュリティグループやサブネットIDが必要ですけれども、同じようにRefでSecGroupNameとすればいいのかというと、テンプレートの構文エラーとなって作成することができません。Refは同じテンプレート内で値を参照するには有効ですが、テンプレートが跨る場合はRefでの参照ができません。ImportValueが用意されているので、こちらで別のテンプレートを参照することができます。しかしこれだけでは不十分で、参照される側のテンプレートに、Outputsというタグを用意する必要があります。別のテンプレートで値を参照させるようにするために、このOutputsが必要なわけです。
では、セキュリティグループとサブネットIDをOutputsへ作成してみましょう。論理IDとValueとExportの3点セットで憶えておいて下さい。まず、論理IDは何でもいいですが、ここではSubnet1という論理IDを作成しました。Valueについては、同じテンプレート内のサブネット名を取得するので、RefのSubnetName、SubnetNameというのはこちらの論理IDとなります。この情報をValueとして持っておく。そしてExport、名前はSubnet1Nameとしましたが、このSubnet1Nameを別のテンプレートのImportValueへ記載すると、こちらのテンプレートでSubnet1Nameという名前でサブネットの情報を取得することができます。
(5:29)
続いてセキュリティグループもやってみましょう。こちらのように、論理IDがSG1、ValueがRefのsecGroupName、これはこちらのセキュリティグループを作成した論理IDです。そしてExportの名前をSG1Name、この値が他のテンプレートから参照できる箇所になります。では左側のテンプレートを一旦保存して、CloudFormation画面でNetworkのテンプレートを更新してみましょう。更新する前に出力のタブを確認してもらいたいのですが、今は出力はありませんとなっています。こちらに先程設定したOutputsの値が更新後に参照できることを確認してみましょう。
更新するボタンを押して「既存テンプレートを置き換える」「テンプレートファイルのアップロード」を選択し、「ファイルの選択」でcloudformation.ymlのOutputsを追加したものを選択して次へを押しましょう。
(6:32)
UPDATE_COMPLETEとなりましたので、出力タブを確認すると、SG1とSubnet1というKeyができて、値としてはSG1がセキュリティグループのID、Subnet1がサブネットのIDとなります。そしてエクスポート名は他のCloudFormationテンプレートから使用できる値が出力されることが確認できました。これらの値が何なのかというと、このSG1はセキュリティグループのIDとなります。セキュリティグループを開いてCFと検索すると、CloudFormationで作られたセキュリティグループIDがCloudFormationの値として出力されています。この値は他のテンプレートからSG1という値で参照できます。
(7:22)
VSCodeに戻って、SecurityGroupIDsという箇所にはImportValue、他のCloudFormationテンプレートから出力した値を使用しますという宣言をしまして、それが何なのかと言うとSubnet1Name、それをこちらのエクスポート名であるSG1Nameに置き換えると、別のテンプレートからセキュリティグループIDを取得できます。ではこの下にSubnetIDも指定していきましょう。SubnetIDと打ちまして
!ImportValueと入力します。ImportValueの値は何なのかと言うと、Subnet1Nameを貼り付けてあげます。Subnet1NameというのはNetworkのテンプレートから出力されたサブネットのIDでして、この値は何なのかと言うと、CloudFormationテンプレートで作成したsubnet1fromCFのサブネットIDになります。
(8:23)
残りのEC2インスタンスの指定された箇所をやっていきましょう。KeyNameは使用するキーペアの名前ですが、キーペアの箇所から、デモではMykeypairというキーペアを使っていましたので、こちらはMykeypairとしましょう。ImageIdですが、AMIのIDを指定します。EC2インスタンスを作成する際に、例えばAmazon Linux 2 AMIには、こちらのIDが割り振られていますので、これをコピーして指定します。InstanceTypeはt2.microとしましょう。監視のオプションであるMonitoringはfalseにします。そしてセキュリティグループとサブネットIDがありまして、UserDataは今回なしとしましょう。TagsのKeyはName、ValueはCFec2として保存しましょう。
(9:23)
ではこの状態でスタックの作成から「テンプレートファイルのアップロード」「ファイルの選択」でec2.ymlを指定して次へを押しましょう。スタックの名前は、ここではComputeとしておきましょう。次へを押します。デフォルトのままでスタックの作成ボタンを押しますとCreateが始まりますので、しばらく待ちましょう。
CREATE_COMPLETEとなりましたので、EC2インスタンスの画面を見ていきましょう。CFec2という名前のものが立ち上がっている途中なのが確認できました。
(10:05)
ここまでご覧になって、Outputsについて疑問点のある方がいるかもしれません。Value: !Ref subnetName を指定することでサブネットグループのIDであったり、こちらのようにValue: !Ref secGroupName にセキュリティグループのIDが出力されましたが、出力される値は1つだけに決まっているのかというとそんなことはありません。例えばセキュリティグループが所属するVPCのIDを出力することもできます。今回はRefで出力しましたが、!GetAtt というものも使えます。こちらは使い方があり、例えば!GetAtt 論理IDの後ろに.(ドット)GroupIdと打ちますと、この場合でもセキュリティグループのIDを出力できますし、他にも.VpcIdとすると、このセキュリティグループが所属するVPCのIDを出力できます。ちょっと試しにやってみましょう。Valueに!GetAtt secGroupName.VpcId この状態で保存し、Networkを更新したいんですが、更新する前に既にComputeの値でOutputsの出力が使用されておりますので、一旦Computeを削除します。そうすることで、Computeのテンプレートで定義されているスタック(EC2インスタンス)が削除されます。こちらでしばらく待ちたいと思います。
(11:31)
削除が正常に完了しましたので、Networkのテンプレートを選択して更新するボタンを押し、「既存テンプレートを置き換える」「テンプレートファイルのアップロード」を選択し、「ファイルの選択」でcloudformation.ymlを指定します。これで更新してみましょう。
(11:48)
そうすると出力の値(今だとセキュリティグループの値)、これを更新しますとVPCのIDに変わりましたね。これはGetAttでセキュリティグループの所属するVPCのIDを出力してくださいねという指定に変えたからになります。ではこちらをVpcIdではなく、GroupIdという名前に置き換えてもう一度更新してみましょう。出力の値に注目して下さい。今はVPCのIDですが、セキュリティグループのIDに戻りましたね。このようにGetAttという指定をすることによって、セキュリティグループの中の何を取りたいのか、セキュリティグループのIDなのか、それともセキュリティグループが所属するVPCのIDなのかを取得することができます。ではGetAttで取得できる値は何なのかということですが、こちらも公式ドキュメントに書かれています。
(12:45)
こちらは公式ドキュメントのセキュリティグループの説明ですけれども、戻り値というところのGetAttの箇所になります。「このタイプの指定された属性の値を返します。以下には利用可能な属性とサンプル戻り値のリストが示されます。」要はGetAttを指定して 論理ID.GroupId としますと指定されたセキュリティグループのID、.VpcIdとしますとVPCの物理IDなど、このように、どのアトリビュート(属性)が指定できて、何が返るのかというのも全て公式ドキュメントに記載されています。