経緯・あらすじ
- 前回までで、業務のAWS(踏み台サーバ周りのNW)を cFnのテンプレにした
- その後、チームメンバーに説明してレビューしてもらった
- それを適用すべく、まず私物AWSに同じ構成+ nginx EC2 を立てて、インポート練習をした
- すると、作ったテンプレでは通らなかったので、足りないところを足していく
- 結果、最終的に、私物AWSを cFn管理にすることができた。
作ったcFnテンプレについて
- 詳しくは 前回の 「15日め」に書きましたが、 CloudFormationの実践ベストプラクティス - Qiita のベストプラクティス構成を踏襲しています。
- 思いっきり「CDKを使いましょう」と書かれてますが、一旦 cFnをマスターしたかったので、このSSHサーバ周りのNWだけ、cFnだけでやってみています
- それをしてよかったか, 悪かったかは 後日 CDKを学んだ時にこのブログに記します。
インポート検証環境つくり
方針
- 本稼働環境を稼働させたままcFn管理にできると思うけれど、それを実証したい
- ので、nginxをec2で動かして、ブラウザで1秒毎にアクセスしてやってみた
- インターネット経由のアクセスだし、(あまり頻繁にしてブロックされると嫌なので)1秒毎で良いと思う(アドオン利用)
やったこと
- 作ったcFnをテンプレをみながら私物AWSでぽちぽちしてつくった
- EC2のnginx部分は↓でやった
私物AWSでインポート練習してみたら問題が何個も発生した
問題1: ネストしたテンプレでは、実際にインポートしたいリソースをインポートできない
- 一番上の stacks/master.yml を「既存のリソースを使用する」で読み込んでも、その .yml で読み込んでる、 cFnのNetwork Stack の Stack IDを入力する画面にしかならなかった
- インポート機能自体が 2019/11 にできたものなので、ネスト先で使ってるリソースのインポートにはまだ対応して無くても仕方ないなと諦めた (2021/08/23)
- 仕方ないので、 templatex/VPN.yml とかで1つずつ インポートして、それらを読み込む stacks/network/master.yml や stacks/master.yml もインポート作成操作をしようと考えた
- CDKでこのあたり(インポート周り)も楽になるか要チェックポイント
問題2: 個別にインポートしてると Outputs を吐けない
- templates/network/VPC.yml を使ってインポートしようとしたら↓を言われた
- As part of the import operation, you cannot modify or add [Outputs]
- 一旦消して先に進めた
- でもインポートじゃない時だけ Outputs する、でいい気もする (この後やってみたい)
- 多分 UPDATEの時( UPDATE_COMPLETE にする時) には必要そう
問題3: インポートできないリソースがある
- AWS::EC2::Route や AWS::EC2::VPCGatewayAttachment は、インポートに非対応、と実行して初めてわかった
- もちろん、「どれがインポートに対応してるよ」表はAWSのドキュメントにあるんだけど
- 「次のリソースタイプは、リソースのインポートではサポートされていません: AWS::EC2::VPCGatewayAttachment 」
- 「次のリソースタイプは、リソースのインポートではサポートされていません: AWS::EC2::Route」
- 「次のリソースタイプは、リソースのインポートではサポートされていません: AWS::EC2::SubnetRouteTableAssociation」
- 一旦、対応してないリソースは消して、(練習用私物AWSで)インポートしてみた
- だが、後にそういう対処は誤りだと思った (既にある場合はリソースを作成しない、にテンプレをConditionalにするのがよさそう、と思っている 2021/08/23 23:35)
(自分の過ち: インポートするcFn Stackにも DeletionPolicy と UpdateReplacePolicy が必要)
- The following resources to import [PubSubAPne1d, VPC, IGW, RouteTableToIGW] must have DeletionPolicy attribute specified in the template.
- cfn-lint でも怒られてたっぽい
問題4: IMPORT_COMPLETE のステータスのスタックを親スタックはインポートできない (のでUPDATE_COMPLETEにしておく必要がある)
- 4つを一旦インポートしてみたので、その4つをインポートして stacks/network/master.yml を作ろうと思った。
- しかし、 ↓のように言われた
- IMPORT_COMPLETE では importable ではないらしい
- ダメといわれた stack で、 変更セットを作成して、適用すると、 UPDATE_COMPLETE になった。そうすると、 stacks/network/master.yml でインポートしたところ、そのエラーは言われなくなった。
問題5: 0.0.0.0/0 のRoute が既にあるから追加できない と言われる
- PubSubを一度、Route 抜きで既存リソースをインポートして作ったあとに、 Routeありにテンプレを戻して更新セット作ろうとしたら、「0.0.0.0/0 のルートはあるから」作れないよ、と言われた
- ので、 テンプレをConditionalにしてやり直そうと考えているところである 2021/08/23 23:42
リソースが無い時だけRouteとかのリソースを作る編 2021/08/24 0:03 32min
- あまり役立たなかった AWSドキュメント
- 少し役立った AWSドキュメント
- ☆ドンピシャなAWSドキュメント
- なんか、 渡したParameterでの分岐しかできないようだった
- 既にリソースがあるかをcFnに調べてもらって分岐はできなさそうだった
- まだcFnは発展途上だから仕方ないかな
- CDKでできるかは要チェックポイント
- 途中で出てきた noecho のマスク助かる (パスワードとかを非表示にできる)
- 「テンプレートに認証情報を埋め込まない」
aws::novalue擬似パラメーターは、戻り値として使用された場合、対応するリソースプロパティを削除します。
- cFnでソフトウェアインストールとかする時は、cFnのヘルパースクリプトというのを使うらしい
その方針でやった結果
- 概ねうまく行った
- 最終的に、nginxを止めないまま、CloudFormation管理下に置くことに成功した
- 一番上のmaster.yml は無くして、networkスタックとかを5つ管理しようと思った
結局インポートする時にやったこと
↓のテンプレを使ってインポートするには…
- ↓のテンプレの templates/ の各ファイルを使って、4つのスタック(VPC, IGW, PublicSubnetRouteTable, Subnet) をインポート作成していく
- その際、 Outputs と importに対応してないリソース(Conditionalなリソース)の部分は手元で消して、その手元のテンプレをcFnのマネジネントコンソールでアップロードしてインポートしていく (IMPORT_COMPLETEになる)
- インポートしたら、Outputsと 消したリソースを戻した元の状態のテンプレをcFnマネジネントコンソールでアップロードして変更セットをつくり、反映し、 IMPORT_COMPLETE を UPDATE_COMPLETEにしておく
- 4つの templates のリソースをインポートできたら、network スタックを作る
- S3に下のテンプレを全部アップロードして、 cFnマネジネントコンソールで S3上の stacks/network/master.yml を選んでインポートする
- インポートできたら、 変更セットを現在のテンプレートを使用する で作って、反映し、 IMPORT_COMPLETE状態からUPDATE_COMPLETE にしておく
できたcFnのテンプレート (197行)
stacks/network/master.yml (48行)
AWSTemplateFormatVersion: "2010-09-09"
Description: MyService Network Stack
Resources:
VPC:
Type: AWS::CloudFormation::Stack
DeletionPolicy: Retain
UpdateReplacePolicy: Retain
Properties:
Parameters:
VpcCidrBlock: 172.31.0.0/16
TemplateURL: 'https://myservice-cfn.s3.ap-northeast-1.amazonaws.com/templates/network/VPC.yml'
IGW:
Type: AWS::CloudFormation::Stack
DeletionPolicy: Retain
UpdateReplacePolicy: Retain
Properties:
Parameters:
VpcId: !GetAtt VPC.Outputs.VpcId
CreateOrImport: "import"
TemplateURL: 'https://myservice-cfn.s3.ap-northeast-1.amazonaws.com/templates/network/IGW.yml'
RouteTableToIGW:
Type: AWS::CloudFormation::Stack
DeletionPolicy: Retain
UpdateReplacePolicy: Retain
Properties:
Parameters:
VpcId: !GetAtt VPC.Outputs.VpcId
IgwId: !GetAtt IGW.Outputs.IgwId
CreateOrImport: "import"
TemplateURL: 'https://myservice-cfn.s3.ap-northeast-1.amazonaws.com/templates/network/PublicSubnetRouteTable.yml'
# Subnets
PubSubAPne1d:
Type: AWS::CloudFormation::Stack
DeletionPolicy: Retain
UpdateReplacePolicy: Retain
Properties:
Parameters:
VpcId: !GetAtt VPC.Outputs.VpcId
VpcCidrBlock: 172.31.32.0/20
AvailabilityZone: "ap-northeast-1d"
RouteTableId: !GetAtt RouteTableToIGW.Outputs.RouteTableId
InternetAccessibility: "public"
CreateOrImport: "import"
TemplateURL: 'https://myservice-cfn.s3.ap-northeast-1.amazonaws.com/templates/network/Subnet.yml'
templates/network/
VPC.yml (22行)
AWSTemplateFormatVersion: "2010-09-09"
Parameters:
VpcCidrBlock:
Type: String
AllowedPattern: (\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})/(\d{1,2})
Description: IP address class used for VPC.
Resources:
VPC:
Type: AWS::EC2::VPC
DeletionPolicy: Retain
UpdateReplacePolicy: Retain
Properties:
CidrBlock: !Ref VpcCidrBlock
Tags:
- Key: Name
Value: vpc-cfn
Outputs:
VpcId:
Value: !Ref VPC
IGW.yml (34行)
AWSTemplateFormatVersion: "2010-09-09"
Parameters:
VpcId:
Type: String
CreateOrImport:
Type: String
AllowedValues: ["newly create", "import"]
Conditions:
CreateNewAttachment: !Equals [!Ref CreateOrImport, "newly create"]
Resources:
IGW:
Type: AWS::EC2::InternetGateway
DeletionPolicy: Retain
UpdateReplacePolicy: Retain
Properties:
Tags:
- Key: Name
Value: igw-cfn
AttachGateway:
Type: AWS::EC2::VPCGatewayAttachment
Condition: CreateNewAttachment
DeletionPolicy: Retain
UpdateReplacePolicy: Retain
Properties:
VpcId: !Ref VpcId
InternetGatewayId: !Ref IGW
Outputs:
IgwId:
Value: !Ref IGW
PublicSubnetRouteTable.yml (41行)
AWSTemplateFormatVersion: "2010-09-09"
Parameters:
VpcId:
Type: String
IgwId:
Type: String
CreateOrImport:
Type: String
AllowedValues: ["newly create", "import"]
Conditions:
CreateRoute: !Equals [!Ref CreateOrImport, "newly create"]
Resources:
RouteTable:
Type: AWS::EC2::RouteTable
DeletionPolicy: Retain
UpdateReplacePolicy: Retain
Properties:
VpcId: !Ref VpcId
Tags:
- Key: Name
Value: public-subnet-routetable-cfn
# Routing
# (Route for local will be created automatically as 1st priority routing)
# PubSub-Internet Routing
RouteToIGW:
Type: AWS::EC2::Route
Condition: CreateRoute
DeletionPolicy: Retain
UpdateReplacePolicy: Retain
Properties:
RouteTableId: !Ref RouteTable
DestinationCidrBlock: 0.0.0.0/0
GatewayId: !Ref IgwId
Outputs:
RouteTableId:
Value: !Ref RouteTable
Subnet.yml (52行)
AWSTemplateFormatVersion: "2010-09-09"
Parameters:
VpcId:
Type: String
VpcCidrBlock:
Type: String
AllowedPattern: (\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})/(\d{1,2})
AvailabilityZone:
Type: String
AllowedValues:
- "ap-northeast-1a"
- "ap-northeast-1c"
- "ap-northeast-1d"
RouteTableId:
Type: String
InternetAccessibility:
# This Parameter is used only in Name tag
Type: String
AllowedValues:
- "public"
- "private"
CreateOrImport:
Type: String
AllowedValues: ["newly create", "import"]
Conditions:
CreateRouteTableAssociation: !Equals [!Ref CreateOrImport, "newly create"]
Resources:
Subnet:
Type: AWS::EC2::Subnet
DeletionPolicy: Retain
UpdateReplacePolicy: Retain
Properties:
AvailabilityZone: !Ref AvailabilityZone
VpcId: !Ref VpcId
CidrBlock: !Ref VpcCidrBlock
Tags:
- Key: Name
Value: !Join
["-", [!Ref InternetAccessibility, "subnet", !Ref AvailabilityZone, "cfn"]]
# Associate Route Table To Subnet
AssoRouteTable:
Type: AWS::EC2::SubnetRouteTableAssociation
Condition: CreateRouteTableAssociation
DeletionPolicy: Retain
UpdateReplacePolicy: Retain
Properties:
SubnetId: !Ref Subnet
RouteTableId: !Ref RouteTableId
感想
- 慣れたらスムーズかも
- でも全然ワンタッチではないので、CDKに期待
- メキメキとCloudFormation力がついていってるのが分かるのはいいね (AWS NW知識もついた)
- CloudFormation力は CDKでも要るはずなのでいいんじゃないかなと思う
時間管理
- 前回まで(0からcFnを学んで、cFnテンプレにして、チームメンバーに共有するまで)で 23.5時間かかっていたらしい
- 今回は、そのテンプレを使って私物AWSでcFn管理下にするまでで、9時間かかった