Amazon VPCを使ったサーバ環境をCloudFormerでCloudFormationのテンプレートにする
はじめに
前回「Amazon VPCを使ったサーバ環境をコマンドラインツールで構築する」はAWS EC2 Command Line Toolsを使って、VPC上にサブネットとEC2、RDSインスタンスを作成しました。
前回記事内にも書きましたがコマンドラインでAWSのサービスを作成する場合、各種IDを把握するのが大変でした。VPC IDやEC2インスタンスIDなど様々なIDをコマンド引数として指定する必要があり、慣れないと予想以上に構築に時間がかかってしまいます。
そこで今回からはCloudFormationという環境構築サービスを使って、環境構築を省力化してみたいと思います。
CloudFormerについて
「CloudFormer」というのは、すでに自分がAWSに構築済みの環境からCloudFormationのテンプレートを作成してくれるツールです。CloudFormationを使うにあたり、いきなり構築の元となる「テンプレート」を作成するのは敷居が高いので、今回はCloudFormerを使ってテンプレートを作ってみます。
CloudFormerでCloudFormationのテンプレートを作成する
作成するにあたっては、すでに弊社ブログで以前とりあげた記事を参考にしてください。
この記事通り、ツールが動作するEC2インスタンスを自環境に用意し、ブラウザでツールのページにアクセスし、テンプレート化したいEC2インスタンスの選択・・・など指示通りに回答していくだけで簡単にテンプレートを作ることができました。
CloudFormerが作成したテンプレートの問題点
CloudFormerを使ってCloudFormationのテンプレートを作れましたが、作成されたテンプレートには色々問題があります。
- PrivtiateIPアドレスが固定になっている
- sshのキー名(KeyName)が固定になっている
- VPCサブネットIDが固定になっている
- VPCやサブネットのリソース作成がテンプレートに含まれていない
- ルートテーブルも作成されないのでNATへのルーティング設定が自動化されていない
- AMIのIDが固定(リージョンごとに変更したい)
- セキュリティグループの通信元(Source)に別のセキュリティグループが設定されていない
- セキュリティグループがVPCに紐付けられていない
- RDSのデータベース名が"MyDatabase"固定になっている(???)
値が固定になっているものはテンプレートに手を加えてパラメータ化してあげれば良さそうです。VPC作成まではサポートしてくれない上、サブネットIDが固定なので、そのまま流用できそうにありません。「VPCを使わないEC2を使っていいのは小学生まで」なのでこれは困りました。VPCに対応していない部分については、今後テンプレートの書き方を覚え修正することにしましょう。
まとめ
さて今回はCloudFormerを使ってCloudFormationのテンプレートを作成しました。作成されたテンプレートは再利用性が低く、またVPCも考慮していないため残念ながら実用的には使えなさそうです。
ただ、すでに自分で作成し構成を把握している環境を基にテンプレートを作ってくれるので、テンプレート内でどのようにリソースを定義しパラメータを設定しているのかなんとなく読めるのではないかと思います。CloudFormationのテンプレートに慣れるためのステップとしてCloudFormerを試してみてはいかがでしょうか。
【おまけ】作成されたテンプレート
{ "AWSTemplateFormatVersion": "2010-09-09", "Resources": { "eip54249103142": { "Type": "AWS::EC2::EIP", "Properties": { "InstanceId": { "Ref": "instancei3f1fcb3d" } } }, "instancei3f1fcb3d": { "Type": "AWS::EC2::Instance", "Properties": { "AvailabilityZone": "ap-northeast-1a", "DisableApiTermination": "FALSE", "ImageId": "ami-173fbf16", "InstanceType": "t1.micro", "KernelId": "aki-44992845", "KeyName": "my_keypair", "Monitoring": "false", "Tags": [ { "Key": "Name", "Value": "public" } ], "SubnetId": "subnet-2af6e843", "PrivateIpAddress": "10.0.0.251" } }, "instancei2118cc23": { "Type": "AWS::EC2::Instance", "Properties": { "AvailabilityZone": "ap-northeast-1a", "DisableApiTermination": "FALSE", "ImageId": "ami-173fbf16", "InstanceType": "t1.micro", "KernelId": "aki-44992845", "KeyName": "my_keypair", "Monitoring": "false", "Tags": [ { "Key": "Name", "Value": "private" } ], "SubnetId": "subnet-22f6e84b", "PrivateIpAddress": "10.0.1.80" } }, "instanceifdf92eff": { "Type": "AWS::EC2::Instance", "Properties": { "AvailabilityZone": "ap-northeast-1a", "DisableApiTermination": "FALSE", "ImageId": "ami-12d86d13", "InstanceType": "t1.micro", "KernelId": "aki-d209a2d3", "KeyName": "my_keypair", "Monitoring": "false", "Tags": [ { "Key": "Name", "Value": "nat" } ], "SubnetId": "subnet-2af6e843", "PrivateIpAddress": "10.0.0.63" } }, "rdstestdb": { "Type": "AWS::RDS::DBInstance", "Properties": { "AllocatedStorage": "5", "BackupRetentionPeriod": "0", "DBInstanceClass": "db.t1.micro", "DBName": "MyDatabase", "DBParameterGroupName": "my-dbpg-test-mysql55", "Engine": "mysql", "EngineVersion": "5.5.27", "MasterUsername": "testuser", "MasterUserPassword": "testuser", "Port": "3306", "PreferredBackupWindow": "17:33-18:03", "PreferredMaintenanceWindow": "fri:20:11-fri:20:41" } }, "sgmysgtestnat": { "Type": "AWS::EC2::SecurityGroup", "Properties": { "GroupDescription": "SG for NAT (public subnet)", "SecurityGroupIngress": [ { "IpProtocol": "tcp", "FromPort": "80", "ToPort": "80" }, { "IpProtocol": "tcp", "FromPort": "22", "ToPort": "22" } ] } }, "sgmysgtestmysql": { "Type": "AWS::EC2::SecurityGroup", "Properties": { "GroupDescription": "SG for test mysql (private subnet)", "SecurityGroupIngress": [ { "IpProtocol": "tcp", "FromPort": "3306", "ToPort": "3306" } ] } }, "sgmysgtestpub": { "Type": "AWS::EC2::SecurityGroup", "Properties": { "GroupDescription": "SG for test (public subnet)", "SecurityGroupIngress": [ { "IpProtocol": "icmp", "FromPort": "-1", "ToPort": "-1", "CidrIp": "0.0.0.0/0" }, { "IpProtocol": "tcp", "FromPort": "22", "ToPort": "22", "CidrIp": "0.0.0.0/0" }, { "IpProtocol": "tcp", "FromPort": "80", "ToPort": "80", "CidrIp": "0.0.0.0/0" } ] } }, "sgmysgtestpri": { "Type": "AWS::EC2::SecurityGroup", "Properties": { "GroupDescription": "SG for test (private subnet)", "SecurityGroupIngress": [ { "IpProtocol": "tcp", "FromPort": "22", "ToPort": "22" }, { "IpProtocol": "udp", "FromPort": "161", "ToPort": "161" } ] } } }, "Description": "VPC environment with Public/Private subnets.\r\n1 EC2 instance and 1 RDS instance in Private Subnet.\r\n2 EC2 instances (Web and NAT) in Public subnet.", "Outputs": { "rdstestdbEndpoint": { "Value": { "Fn::GetAtt": [ "rdstestdb", "Endpoint.Address" ] } } } }