はじめに
最近、AWSから正式リリースされた「AWS Console-to-Code」という機能を見つけました。普段から、インフラ構築をコード化するIaC(Infrastructure as Code)を書く手間を少しでも減らしたいと考えていたため、この機能は今後役立つのではないかと思い、試してみることにしました。
AWS Console-to-Codeについて
AWS Console-to-Codeとは、マネジメントコンソール上での操作を自動でコード(AWS CLI コマンド、CloudFormation テンプレート、AWS CDK コードなど)に変換してくれるサービスです。手動操作からインフラのコード管理(IaC)への移行が簡単になり、効率的にコード化できます。
個人的には、AWS CLIによるリソース操作コードを自動生成できるため、手順書を作る手間が省くことができ、とても助かりそうです。
現在、対応しているサービスは以下の3つです:
・Amazon EC2
・Amazon RDS
・Amazon VPC
対応しているコード形式
・AWS CloudFormationテンプレート(YAMLまたはJSON形式)
・AWS CDK(TypeScript、Python、Javaで出力可能)
詳細はこちらから
AWS Console-to-Codeを試してみる
構成要件
今回は、以下のVPC、EC2、RDSまでの基本的な構成を手動で作成し、その過程をConsol-to-Codeで記録してスタック化を試してみました。
AWS Console-to-Code の始め方
Console-to-Code を使用するために、まずEC2サービスのコンソールに移動します(VPC や RDS のコンソールからも利用可能です)
- 画面右側に表示される「Console-to-Code」ウィジェットをクリックします。
- 「記録を開始」ボタンをクリックすると、操作の記録が開始されます。
AWS Console-to-Codeの見方
・記録されたアクション
コンソール上で実行した操作内容をもとに、情報を収集してオペレーションを表示してくれます。
・タイプ
操作内容は、「書き込み」と「読み取り」の二つのタイプに分類されます。
・書き込み:インスタンスの作成や設定のアタッチなど、データが変更される操作。
・読み取り:画面遷移時に読み込まれる情報の取得など、データに変更がない操作。
VPC、EC2、RDS の作成
要件どおりに VPC、EC2、RDSをすべて作成して、最終的には以下のように記録されました。
「停止」ボタンをクリックすることで、記録を終了します。
記録が完了すると、「記録されたアクション」欄で タイプ を「書き込み」に設定し、必要なアクションにチェックを入れます。今回は CloudFormation の YAML を生成しようと思います。
※ちなみに、タイプが「読み取り」の場合、CLI コマンドはコピーできますが、YAML などのコードは生成できなかったです。
YAML コードの生成
実際に YAML コードが生成され、ダウンロードできるようになりました。
生成したyamlのコード↓
Resources:
VPC:
Type: AWS::EC2::VPC
Properties:
CidrBlock: 10.0.0.0/16
InstanceTenancy: default
EnableDnsHostnames: true
EnableDnsSupport: true
Tags:
- Key: Name
Value: test-dev-vpc
PublicSubnetA:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref VPC
AvailabilityZone: !Select [3, !Split ['-', !Ref 'AWS::Region']]
CidrBlock: 10.0.0.0/24
MapPublicIpOnLaunch: true
Tags:
- Key: Name
Value: public Subnet A
PrivateSubnetA:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref VPC
AvailabilityZone: !Select [3, !Split ['-', !Ref 'AWS::Region']]
CidrBlock: 10.0.20.0/24
MapPublicIpOnLaunch: false
Tags:
- Key: Name
Value: Private Subnet A
PrivateSubnetB:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref VPC
AvailabilityZone: !Select [3, !Split ['-', !Ref 'AWS::Region']]
CidrBlock: 10.0.30.0/24
MapPublicIpOnLaunch: false
Tags:
- Key: Name
Value: Private Subnet B
InternetGateway:
Type: AWS::EC2::InternetGateway
VPCGatewayAttachment:
Type: AWS::EC2::VPCGatewayAttachment
Properties:
VpcId: !Ref VPC
InternetGatewayId: !Ref InternetGateway
PublicRouteTable:
Type: AWS::EC2::RouteTable
Properties:
VpcId: !Ref VPC
PublicRoute:
Type: AWS::EC2::Route
DependsOn: VPCGatewayAttachment
Properties:
RouteTableId: !Ref PublicRouteTable
DestinationCidrBlock: 0.0.0.0/0
GatewayId: !Ref InternetGateway
PublicSubnetARouteTableAssociation:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
SubnetId: !Ref PublicSubnetA
RouteTableId: !Ref PublicRouteTable
PublicSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupName: test-dev-public-sg
GroupDescription: test-dev-public-sg
VpcId: !Ref VPC
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 22
ToPort: 22
CidrIp: xxxx
PrivateSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupName: test-dev-private-sg
GroupDescription: test-dev-private-sg
VpcId: !Ref VPC
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 3306
ToPort: 3306
SourceSecurityGroupId: !Ref PublicSecurityGroup
EC2Instance:
Type: AWS::EC2::Instance
Properties:
ImageId: ami-xxx
InstanceType: t2.micro
NetworkInterfaces:
- AssociatePublicIpAddress: "false"
DeviceIndex: "0"
GroupSet:
- !Ref PublicSecurityGroup
SubnetId: !Ref PublicSubnetA
CreditSpecification:
CPUCredits: standard
Tags:
- Key: Name
Value: test-dev-EC2
DBSubnetGroup:
Type: AWS::RDS::DBSubnetGroup
Properties:
DBSubnetGroupDescription: test-dev-RDS-sub
SubnetIds:
- !Ref PrivateSubnetA
- !Ref PrivateSubnetB
RDSInstance:
Type: AWS::RDS::DBInstance
Properties:
Engine: mysql
EngineVersion: 8.0.39
DBInstanceClass: db.t3.micro
DBSubnetGroupName: !Ref DBSubnetGroup
VPCSecurityGroups:
- !Ref PrivateSecurityGroup
AllocatedStorage: 20
BackupRetentionPeriod: 1
DBName: ""
MasterUsername: admin
MasterUserPassword: test1234
PreferredBackupWindow: 02:00-03:00
PreferredMaintenanceWindow: sun:05:00-sun:06:00
PubliclyAccessible: false
初心者目線ではありますが、生成されたコードを確認して、特に印象に残ったポイントは以下の通りです。
・VPC、サブネット、インターネットゲートウェイ、ルートテーブル、セキュリティグループ、EC2インスタンス、RDSインスタンスが設定どおりに連携し、正確に定義されている点は良かったです。
・一方で、RDSのパスワードがコード内に平文で記載されていたため、AWS Secrets ManagerやLambdaなどを使って機密情報を保護する必要があると感じました。
CloudFormation でのスタック作成
最後に、生成されたYAMLコードをそのまま使ってCloudFormationでスタックを作成しようとしたところ、Template error: Fn::Select cannot select nonexistent value at index 3
というエラーが発生しました。
調べたところ、問題はコード内で指定したアベイラビリティゾーン(AZ)のインデックスにありました。AvailabilityZone: !Select [3, !Split ['-', !Ref 'AWS::Region']]
という記述がエラーの原因でした。
このコードはAZリストのインデックス3
を指定していますが、東京リージョンではAZが3つ(インデックス0〜2
)しかないため、存在しないAZを参照してしまい、エラーが発生していました。
エラーを解消するため、以下のようにAZリストから最初の要素(インデックス0
)を選択するコードAvailabilityZone: !Select [0, !GetAZs '']
に修正しました。
修正後、CloudFormationでスタックを再作成したところ、正常に作成が完了しました!
まとめ
今回は、AWS Console-to-Code を使用して VPC、EC2、RDS の基本構成をコード化し、CloudFormation でデプロイする手順を試してみました。
自動生成されたコードには一部修正が必要でしたが、大部分を自動でコード化できるのは、凄いと感じました。今後、他のサービスでも Console-to-Code が利用できることを期待しています!