タイトル通りですが、今回のお題は『パラメータ→構築自動化』です。
イメージとしては、 ・PowerShellスクリプト叩く ・CSVからパラメータ読み込む、 ・CFnのテンプレ(JSON)にパラメータを渡し、スタック作成。 という感じです。
先ずは簡単なところから…ということで、VPC~Subnetの作成までを行ってみます。 構成はVPC内にPublicなSubnet×2(マルチAZ)というシンプルなもの。
因みに、"AWS Tools for PowerShell"を使用していますが初期設定は割愛しています。
目次
- 1. CloudFormationテンプレートファイル作成
- 2. CSVファイルの準備
- 3. PowerShellスクリプト作成
- 4. スクリプト実行
- 5. スタックの状態確認
- 6. リソースの確認
CloudFormationテンプレートファイル作成
はじめにCFnのテンプレートファイルを作成します。 今回はVPCとSubnet作成用に2ファイル用意。(見やすいという理由で) "Parameters"ブロックで受け取る引数を指定、 "Resources"ブロック内で作成するリソースに関する記述を行っています。
{ "AWSTemplateFormatVersion": "2010-09-09", "Parameters": { "vpccidrblock": { "AllowedPattern": "(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})/(\\d{1,2})", "Default": "172.31.0.0/16", "Type": "String" }, "vpcname":{ "Type": "String" } }, "Resources": { "VPC": { "Properties": { "CidrBlock": { "Ref": "vpccidrblock" }, "Tags": [ { "Key": "Application", "Value": { "Ref": "AWS::StackId" } }, { "Key": "Name", "Value": { "Ref": "vpcname" } } ] }, "Type": "AWS::EC2::VPC" } } }
Subnet作成用JSONファイル(subnettest.json)
{ "AWSTemplateFormatVersion": "2010-09-09", "Parameters": { "subnetname": { "Type": "String" }, "subnetcidrblock": { "Type": "String" }, "subnetazname": { "Type": "AWS::EC2::AvailabilityZone::Name" }, "subnetpublicipflag": { "Type": "String" }, "vpcid": { "Type": "String" } }, "Resources": { "Subnet": { "Properties": { "CidrBlock": { "Ref": "subnetcidrblock" }, "MapPublicIpOnLaunch" : { "Ref": "subnetpublicipflag" }, "AvailabilityZone": { "Ref": "subnetazname" }, "VpcId" : { "Ref" : "vpcid" }, "Tags": [ { "Key": "Name", "Value": { "Ref": "subnetname" } } ] }, "Type": "AWS::EC2::Subnet" } } }
また、作成したJSONファイルはS3にアップロードしておきます。
ここでは"my-cfn-templates-000"という名前でバケットを作成し、 その中にJSONファイルをアップロードしています。
CSVファイルの準備
特筆するところもないですが、 前項で作成したCFnテンプレに渡す為のパラメータを記述したCSVを用意します。 見づらいので、Excelで開いたものを載せておきます。
"subnetazflag"は、東京リージョンのAZ "ap-northeast-1a"、"ap-northeast-1c"を判別するフラグになります。
また同一VPC内にSubnetを作成することを前提として作成しているので、 2行目はブランクにしています。
PowerShellスクリプト作成
続いて、PowerShellのスクリプトを作成します。 汚いコードですが、以下のような感じに書いてみました。 少し長いので3分割しています。
①変数設定等 Credential等の設定はEC2上から実行するのであれば不要ですね。
#Credentialファイルのパスを指定 $credentials_path = "<任意のパス>" #リージョンの指定(今回は東京リージョン) $aws_region = "ap-northeast-1" #CFnテンプレートファイルを格納したS3のURLを指定 $template_url1 = "https://s3.amazonaws.com/my-cfn-templates-000/vpctest.json" $template_url2 = "https://s3.amazonaws.com/my-cfn-templates-000/subnettest.json" #Credintial、リージョンの設定 Set-AWSCredentials -StoreAs $credentials_path Set-DefaultAWSRegion -Region $aws_Region #CSVファイルの読み込み(デスクトップに配置したparam.csvを指定) $csvfile = Get-ChildItem env:USERPROFILE | % {$_.value} $csvfile += "\Desktop\param.csv" $cfnparam = Get-Content $csvfile | ConvertFrom-Csv -Delimiter ","
②VPC作成処理 スタック名はユニークにする必要があるので注意です。 "vpcname"ですがSubnet作成処理でVPCのidを特定するのに使う為、 スコープを"script"にしています。
#インスタンスを作成し、パラメータを付加 function Create_Object($param_key,$param_value){ $p = New-Object -Type Amazon.CloudFormation.Model.Parameter $p.ParameterKey = $param_key $p.ParameterValue = $param_value return $p } #VPC作成処理 function Create_Vpc{ $stackname = "vpc-stack-00" $script:vpcname = $cfnparam.vpcname $vpccidrblock = $cfnparam.vpccidrblock $p1 = Create_Object vpcname $vpcname $p2 = Create_Object vpccidrblock $vpccidrblock New-CFNStack -StackName $stackname ` -TemplateURL $template_url1 ` -Parameter @( $p1, $p2 ) ` -OnFailure "ROLLBACK" }
③Subnet作成処理、Function実行 CSVファイルを見ればお察しかと思いますが、 "vpcname"パラメータを変数に代入する際、複数行だと当然ながら配列型になってしまう為、 文字列型かそうでないかを判別しています。(無理やり感満載ですが…)
Function実行部分では、"Start-Sleep"にて処理を待つようにしています。 が、入れなくても問題ない?気がしています…。
#Subnet作成処理 function Create_Subnet{ $stack_count = 0 if($vpcname.gettype().fullname -ne [System.String]){ $vpcid = (Get-EC2Tag -region $aws_Region | ? {$_.value -eq $vpcname[0]} | % {$_.resourceid}) }else{ $vpcid = (Get-EC2Tag -region $aws_Region | ? {$_.value -eq $vpcname} | % {$_.resourceid}) } $avz = Get-EC2AvailabilityZone -region $aws_Region | % {$_.zonename} foreach ($cfn_param in $cfnparam) { $stackname = "subnet-stack-" + ("{0:00}" -F $stack_count) $stack_count ++ $subnetname = $cfn_param.subnetname $subnetcidrblock = $cfn_param.subnetcidrblock $subnetazflag = $cfn_param.subnetazflag $subnetpublicipflag = $cfn_param.subnetpublicipflag $p3 = Create_Object subnetname $subnetname $p4 = Create_Object subnetcidrblock $subnetcidrblock $p5 = Create_Object subnetazname $avz[$subnetazflag] $p6 = Create_Object subnetpublicipflag $subnetpublicipflag $p7 = Create_Object vpcid $vpcid New-CFNStack -StackName $stackname ` -TemplateURL $template_url2 ` -Parameter @( $p3, $p4, $p5, $p6, $p7 ) ` -OnFailure "ROLLBACK" } } Create_Vpc Start-Sleep -Seconds 60 Create_Subnet
スクリプト実行
前項で作成したスクリプトを叩くだけです…。
スタックの状態確認
マネジメントコンソールから確認してみます。 "CREATE_COMPLETE"となっていれば完了です。
リソースの確認
最後にVPC、Subnetをコマンドで確認してみましょう。 "Get-EC2Vpc"、"Get-EC2Subnet"を使用します。
CSVファイルに入力したパラメータ通り、作成できていることが確認できました。 以上が一連の流れとなります。
EC2の作成は割愛しましたので、中途半端ではありますが如何でしょうか。 頑張れば構築が楽になりそうな気が?しますね…。
また、デフォルトではスタックを削除するとリソースも削除されるのですが オプションにて削除しないようにすることもできます。
JSONファイルの"Resources"ブロックにて "DeletionPolicy" : "Retain"とすることで削除されなくなります。
それでは次の機会に。