【CloudFormation】パブリックサブネットにCloud9(SSH)をデプロイしてみる
1. はじめに
こんにちわ、Mitsuoです。
今住んでいる家にようやくクーラーが設置され快適な環境が手に入りました。
今年も暑いようですので、体調にはお気を付けください。
2. 今回のお題
さて、今回のお題に入りますが、「CloudFormationを用いてCloud9をデプロイ」してみました。
Cloud9をコンソールで作成すると、裏でCloudFormationのスタックが作成され、Cloud9用のEC2が生成されると思います。
しかしながら、ブログ主は凄く怠惰なのでコンソールでは無くテンプレートで持っておきたいな、と言うのが今回のネタになります。
3. 作成したリソース
テンプレートで作成するリソースは以下の通りです。
- VPC
- Subnet(Public)
- RouteTable
- InternetGateway
- NACL
- Cloud9
「プライベートサブネットになぜ配置しないの?」、「Session Managerを使えよ」と思ったそこのあなた、おっしゃる通りです。
言い訳をすると、初心者の方にも取っ掛かりやすい内容で書きたかったんです。
後は、もう少しコンパクトに書いても良いのですが、補足を入れると結構な文字数になるなという訳で・・・。今回は書きませんが、ストックは持っているので、近いうちに記事にする予定です。
4 テンプレート情報
作成したテンプレートになります。
AWSTemplateFormatVersion: 2010-09-09
Description: Create Cloud9 for Public subnet, network and related resources such as subnet, route table.
# ------------------------------------------------------------#
# Caution:
# This template is for deploying resources on AZ-1a in Tokyo region(ap-northeast-1).
# If you deploy them in another region, make sure that you understand below content and make modification for parameters such as AvailabilityZone.
# ------------------------------------------------------------#
# Metadata:
# This can privide details about the template.
# For more information, see https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/metadata-section-structure.html.
# As Metadata Keys, AWS::CloudFormation::Interface can Defines the grouping and ordering of input parameters
# when they are displayed in the AWS CloudFormation console.
# For more information, see https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-cloudformation-interface.html.
# ------------------------------------------------------------#
Metadata:
"AWS::CloudFormation::Interface":
ParameterGroups:
-
Parameters:
- SystemName
- EnvType
- Tagprefix
- Owner
- VPCCIDR
- PublicSubnet1CIDR
ParameterLabels:
SystemName:
default: "Please type the Systemname"
EnvType:
default: "Please select the environment to which you want to deploy resources"
Tagprefix:
default: "Please type the Tagprefix which is logical unit name about this stack(e.g. Webserver,Monitoring,Logging)"
Owner:
default: "Please type who owns these resources (e.g. project name or worker, whether this purpose is just verification or not)"
VPCCIDR:
default: "Please type VPC's CIDR such as NN.NN.NN.NN/NN based on RFC 1918"
PublicSubnet1CIDR:
default: "Please type your subnet's CIDR in AZ-A such as NN.NN.NN.NN/NN based on RFC 1918"
# ------------------------------------------------------------#
# Parameters
# This Can enable templates to input custom values each time you create or update a stack.
# For more information, see https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/parameters-section-structure.html.
# ------------------------------------------------------------#
Parameters:
SystemName:
Type: String
EnvType:
Type: String
Default: "dev"
AllowedValues:
- dev
- stg
- prod
Tagprefix:
Type: String
Owner:
Type: String
VPCCIDR:
Type: String
Default: "10.0.0.0/16"
ConstraintDescription: "Please type VPC's CIDR such as NN.NN.NN.NN/NN based on RFC 1918"
PublicSubnet1CIDR:
Type: String
Default: "10.0.1.0/24"
ConstraintDescription: "Please type your subnet's CIDR in AZ-A such as NN.NN.NN.NN/NN based on RFC 1918"
# ------------------------------------------------------------#
# Resources
# This can declare the AWS resources that you want to include in the stack.
# For more information, see https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/resources-section-structure.html.
# ------------------------------------------------------------#
Resources:
# ------------------------------------------------------------#
# Create VPC
# ------------------------------------------------------------#
VPC:
Type: AWS::EC2::VPC
Properties:
CidrBlock: !Ref VPCCIDR
EnableDnsHostnames: "true"
EnableDnsSupport: "true"
Tags:
- Key: Name
Value: !Sub ${SystemName}-${EnvType}-${Tagprefix}-VPC
- Key: Owner
Value: !Sub ${Owner}
# ------------------------------------------------------------#
# Create PublicSubnet
# ------------------------------------------------------------#
PublicSubnet1:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref VPC
CidrBlock: !Ref PublicSubnet1CIDR
AvailabilityZone: ap-northeast-1a
MapPublicIpOnLaunch: true
Tags:
- Key: Name
Value: !Sub ${SystemName}-${EnvType}-${Tagprefix}-PublicSubnet-1a
- Key: Owner
Value: !Sub ${Owner}
# ------------------------------------------------------------#
# Create InternetGateway and associate it with VPC
# ------------------------------------------------------------#
InternetGateway:
Type: AWS::EC2::InternetGateway
Properties:
Tags:
- Key: Name
Value: !Sub ${SystemName}-${EnvType}-${Tagprefix}-Internet-Gateway
- Key: Owner
Value: !Sub ${Owner}
AttachGateway:
Type: AWS::EC2::VPCGatewayAttachment
Properties:
VpcId: !Ref VPC
InternetGatewayId: !Ref InternetGateway
# ------------------------------------------------------------#
# Create Route Table and associate it with Public Subnet
# ------------------------------------------------------------#
PublicRouteTable:
Type: AWS::EC2::RouteTable
Properties:
VpcId: !Ref VPC
Tags:
- Key: Name
Value: !Sub ${SystemName}-${EnvType}-${Tagprefix}-RouteTable-PublicSubnet
- Key: Owner
Value: !Sub ${Owner}
PublicSubnetRouteTableAssociation1:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
SubnetId: !Ref PublicSubnet1
RouteTableId: !Ref PublicRouteTable
PublicRoute:
Type: AWS::EC2::Route
DependsOn: AttachGateway
Properties:
RouteTableId: !Ref PublicRouteTable
DestinationCidrBlock: "0.0.0.0/0"
GatewayId: !Ref InternetGateway
# ------------------------------------------------------------#
# Create NetworkACL and associate it with Public Subnet
# ------------------------------------------------------------#
PublicNetworkACL:
Type: AWS::EC2::NetworkAcl
Properties:
VpcId: !Ref VPC
Tags:
- Key: Name
Value: !Sub ${SystemName}-${EnvType}-${Tagprefix}-Public-Networkacl
- Key: Owner
Value: !Sub ${Owner}
PublicNaclInboundRule:
Type: AWS::EC2::NetworkAclEntry
Properties:
NetworkAclId: !Ref PublicNetworkACL
RuleNumber: 100
Protocol: -1
Egress: false
RuleAction: allow
CidrBlock: 0.0.0.0/0
PublicNaclOutboundRule:
Type: AWS::EC2::NetworkAclEntry
Properties:
NetworkAclId: !Ref PublicNetworkACL
RuleNumber: 100
Protocol: -1
Egress: true
RuleAction: allow
CidrBlock: 0.0.0.0/0
PublicNetworkACLAssoc1:
Type: AWS::EC2::SubnetNetworkAclAssociation
Properties:
NetworkAclId: !Ref PublicNetworkACL
SubnetId: !Ref PublicSubnet1
# ------------------------------------------------------------#
# Create Cloud9
# ------------------------------------------------------------#
Cloud9:
Type: AWS::Cloud9::EnvironmentEC2
Properties:
AutomaticStopTimeMinutes: 30
ConnectionType: CONNECT_SSH
Description: The Cloud9 on Public subnet connecting Via SSH.
ImageId: amazonlinux-2-x86_64
InstanceType: t3.small
Name: !Sub ${SystemName}-${EnvType}-${Tagprefix}-Cloud9-SSH
# OwnerArn: Please use this property if you want to set up the ARN of environment owner.
# Repositories: Please use this property if you want to set up any CodeCommit source code repositories to be cloned into the environment.
SubnetId: !Ref PublicSubnet1
Tags:
- Key: Owner
Value: !Sub ${Owner}
DependsOn: PublicSubnet1
# ------------------------------------------------------------#
# Outputs
# This can output each value specified as output section.
# For more information, see https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/resources-section-structure.html.
# ------------------------------------------------------------#
Outputs:
VPC:
Description: VPC
Value: !Ref VPC
PublicSubnet1:
Description: PublicSubnet1
Value: !Ref PublicSubnet1
PublicRouteTable:
Description: PublicRouteTable
Value: !Ref PublicRouteTable
InternetGateway:
Description: InternetGateway
Value: !Ref InternetGateway
PublicNetworkACL:
Description: PublicNetworkACL
Value: !Ref PublicNetworkACL
Cloud9:
Description: Cloud9
Value: !Ref Cloud9
5. テンプレートの補足
テンプレートに関して、以下の通り補足します。
5.1 Metadata/Parameters
メタデータおよびパラメターセクションで、4つの値を定義します。
項目 | 備考 |
---|---|
ProjectName |
プロジェクト名や利用目的等を入力する |
EnvType |
デプロイする環境を選択する 検証、ステージング、本番の3点 |
Tagprefix |
任意で入力するPrefix値 |
Owner |
作業者、所有者、コスト管理用に入力する |
Cloud9を除くNameタグの値に、ProjectName
、EnvType
、Tagprefix
の3点を含みます。
Owner
はOwnerタグの値に利用します。
Cloud9は、Nameプロパティがある為、テンプレートでNameタグの指定が出来ない仕様になっています。
指定したNameプロパティに加えて、ランダム文字列を付与します。
5.2 Resources
以下のリソースセクションを設定しています。
AWS::EC2::VPC
AWS::EC2::Subnet
AWS::EC2::InternetGateway
AWS::EC2::VPCGatewayAttachment
AWS::EC2::RouteTable
AWS::EC2::SubnetRouteTableAssociation
AWS::EC2::Route
AWS::EC2::NetworkAcl
AWS::EC2::NetworkAclEntry
AWS::EC2::SubnetNetworkAclAssociation
AWS::Cloud9::EnvironmentEC2
VPC、サブネット周りは、他にも有用な記事が沢山あるので、私の記事では割愛します。
Cloud9だけ補足します。
5.3 Cloud9(Type: AWS::Cloud9::EnvironmentEC2)
- Cloud9が起動してから自動的に停止する時間を分単位で指定
AutomaticStopTimeMinutes: 30
- Cloud9への接続方式
SSH接続かSystems Manager(Session Manager)で指定可能
デフォルトがSSH接続
ConnectionType: CONNECT_SSH
- Cloud9の説明、名前欄に記入する項目
Cloud9はNameタグの指定が出来ず、プロパティ側で設定する必要がある
Description: The Cloud9 on Public subnet connecting Via SSH.
Name: !Sub ${SystemName}-${EnvType}-${Tagprefix}-Cloud9-SSH
- Cloud9で実行するイメージを指定、AMIのエイリアスかSSM Pathsの指定が必要
インスタンスタイプも指定出来る
ImageId: amazonlinux-2-x86_64
InstanceType: t3.small
- Cloud9の所有者をARNベースで指定出来る
デフォルトは、ログインユーザ(スイッチロール含む)になる
# OwnerArn: Please use this property if you want to set up the ARN of environment owner.
- Cloud9はCodeCommitと統合されており、CodeCommitのソース情報をCloud9にクローン(Git Cloneと同じように同期)したい場合、利用する
# Repositories: Please use this property if you want to set up any CodeCommit source code repositories to be cloned into the environment.
5.4 その他
- CloudFormationでCloud9を作成してもCloud9用テンプレートが別途作成されます。
合計2個ですね。
別途作成されたテンプレートのステータスがCREATE_COMPLETE
になれば、Cloud9にアクセス出来る状況のはずです。
Cloud9のIDE環境にアクセスした後、どちらのテンプレートのステータスもCREATE_COMPLETE
になっている事を確認済みです。
- SSH接続のCloud9の場合は、セキュリティグループが自動的に生成されますが、SSMを利用するためのIAMロール(実際にアタッチされているのはインスタンスプロファイル)はインスタンスにアタッチされません。この辺りは、コンソールと同じですね。
6. まとめ
今回はCloud9のテンプレートを作成してみました。需要があるかはさておき一時的にCloud9を使いたい、かつネットワークリソースは他と分けたい様なニーズがあれば使えるテンプレートだとは思います。
とはいえ、パブリックサブネットに配置するCloud9はセンスが無いので、プライベートサブネット用のテンプレートもブログで書くようにします。
この記事が誰かの役に立てれば嬉しいです。Mitsuoでした!
Discussion