こんにちは。SCSK石原です。
AWSを利用した開発において、Cloud9を利用する機会はあるかと思います。
Cloud9ではコードを修正や踏み台(プライベートサブネットに存在するRDSやEC2にアクセスするため)などに利用できます。
このCloud9ですが、IAMユーザに対して紐づくものとなっていますので、基本的には利用する人が利用したいタイミングで自ら作成するというのが、本来のあり方かと思います。WEBコンソールから作成した場合、作成したIAMユーザがオーナーとなります。他のメンバーが利用するためにはCLIでオーナーを変更するか、共有することが必要となります。
開発チーム・インフラチームなどと分かれている場合には、VPCやサブネットなどのリソースをインフラチームが管理していることから、払い出しの依頼が来ることもあります。(Ex 取り敢えず、アサインされていてIAMユーザを持っている人全員の環境を払い出しておいて・・・etc…)
Cloud9環境を他のユーザ向けに払い出すのは意外と手間のかかる作業でしたので、テンプレートを作成しました。ぜひご活用ください。
事前準備(VPC)
事前にVPCなどネットワーク関連のリソースを準備しておきます。
Cloud9環境はプライベートサブネットに作成することを想定しています。
Cloud9環境にクライアントから接続する際は、「AWS Systems Manager」を経由することによりインバウンド通信の許可が必要ありません。その代わりにCloud9からアウトバウンド通信が必要になりますので、NATゲートウェイかVPCエンドポイントを用意します。
今回はNATゲートウェイを利用しています。

上記の構成を作成するテンプレートは以下の通りです。
AWSTemplateFormatVersion: "2010-09-09"
Description: "sample-nw Template"
Parameters:
ProjectID:
Type: String
MinLength: 3
MaxLength: 15
Default: "sample"
AllowedValues:
- "sample"
Resources:
# ================================
# VPC
# ================================
SAMPLEVPC:
Type: "AWS::EC2::VPC"
Properties:
CidrBlock: "192.168.0.0/16"
EnableDnsSupport: true
EnableDnsHostnames: true
InstanceTenancy: "default"
Tags:
- Key: "Name"
Value: !Sub "${ProjectID}-vpc"
# ================================
# Subnet
# ================================
SubnetNW1a:
Type: "AWS::EC2::Subnet"
Properties:
AvailabilityZone: !Sub "${AWS::Region}a"
CidrBlock: "192.168.0.0/24"
VpcId: !Ref SAMPLEVPC
MapPublicIpOnLaunch: false
Tags:
- Key: "Name"
Value: !Sub "${ProjectID}-nw-public-1a"
SubnetDev1a:
Type: "AWS::EC2::Subnet"
Properties:
AvailabilityZone: !Sub "${AWS::Region}a"
CidrBlock: "192.168.1.0/24"
VpcId: !Ref SAMPLEVPC
MapPublicIpOnLaunch: false
Tags:
- Key: "Name"
Value: !Sub "${ProjectID}-dev-private-1a"
# ================================
# ACL
# ================================
NetworkAclNW:
Type: "AWS::EC2::NetworkAcl"
Properties:
VpcId: !Ref SAMPLEVPC
Tags:
- Key: "Name"
Value: !Sub "${ProjectID}-nw-acl"
NetworkAclDev:
Type: "AWS::EC2::NetworkAcl"
Properties:
VpcId: !Ref SAMPLEVPC
Tags:
- Key: "Name"
Value: !Sub "${ProjectID}-dev-acl"
# # ACL association
NetworkAclAssociationNW1a:
Type: "AWS::EC2::SubnetNetworkAclAssociation"
Properties:
SubnetId: !Ref SubnetNW1a
NetworkAclId: !Ref NetworkAclNW
NetworkAclAssociationDev1a:
Type: "AWS::EC2::SubnetNetworkAclAssociation"
Properties:
SubnetId: !Ref SubnetDev1a
NetworkAclId: !Ref NetworkAclDev
# # ACL NW Egress
NetworkAclEntryNWEg100:
Type: "AWS::EC2::NetworkAclEntry"
Properties:
CidrBlock: "0.0.0.0/0"
Egress: true
NetworkAclId: !Ref NetworkAclNW
Protocol: -1
RuleAction: "allow"
RuleNumber: 100
# # ACL NW Ingress
NetworkAclEntryNWIg100:
Type: "AWS::EC2::NetworkAclEntry"
Properties:
CidrBlock: "0.0.0.0/0"
Egress: false
NetworkAclId: !Ref NetworkAclNW
Protocol: -1
RuleAction: "allow"
RuleNumber: 100
# # ACL Dev Egress
NetworkAclEntryEC2Eg100:
Type: "AWS::EC2::NetworkAclEntry"
Properties:
CidrBlock: "0.0.0.0/0"
Egress: true
NetworkAclId: !Ref NetworkAclDev
Protocol: -1
RuleAction: "allow"
RuleNumber: 100
# # ACL Dev Ingress
NetworkAclEntryEC2Ig100:
Type: "AWS::EC2::NetworkAclEntry"
Properties:
CidrBlock: "0.0.0.0/0"
Egress: false
NetworkAclId: !Ref NetworkAclDev
Protocol: -1
RuleAction: "allow"
RuleNumber: 100
# ================================
# Route Table
# ================================
RouteTableNW:
Type: "AWS::EC2::RouteTable"
Properties:
VpcId: !Ref SAMPLEVPC
Tags:
- Key: "Name"
Value: !Sub "${ProjectID}-nw-public-rt"
RouteTableDev:
Type: "AWS::EC2::RouteTable"
Properties:
VpcId: !Ref SAMPLEVPC
Tags:
- Key: "Name"
Value: !Sub "${ProjectID}-dev-private-rt"
# route table association
RouteTableAssociationNW1a:
Type: "AWS::EC2::SubnetRouteTableAssociation"
Properties:
RouteTableId: !Ref RouteTableNW
SubnetId: !Ref SubnetNW1a
RouteTableAssociationDev1a:
Type: "AWS::EC2::SubnetRouteTableAssociation"
Properties:
RouteTableId: !Ref RouteTableDev
SubnetId: !Ref SubnetDev1a
# ================================
# NAT Gateway
# ================================
InternetGateway:
Type: AWS::EC2::InternetGateway
Properties:
Tags:
- Key: stack
Value: !Sub "${ProjectID}-igw"
EIPNATGW:
Type: AWS::EC2::EIP
Properties:
Domain: vpc
NatGateway:
Type: AWS::EC2::NatGateway
Properties:
AllocationId: !GetAtt EIPNATGW.AllocationId
SubnetId: !Ref SubnetNW1a
VPCGatewayAttachment:
Type: AWS::EC2::VPCGatewayAttachment
Properties:
InternetGatewayId: !Ref InternetGateway
VpcId: !Ref SAMPLEVPC
OutBoundOnlyRoute:
Type: AWS::EC2::Route
Properties:
DestinationCidrBlock: "0.0.0.0/0"
NatGatewayId: !Ref NatGateway
RouteTableId: !Ref RouteTableDev
PublicRoute:
Type: AWS::EC2::Route
Properties:
DestinationCidrBlock: "0.0.0.0/0"
GatewayId: !Ref InternetGateway
RouteTableId: !Ref RouteTableNW
Outputs:
# Subnet_Dev
OUTPUTSubnetDev1a:
Description: subnet dev 1a
Value: !Ref SubnetDev1a
Export:
Name: !Sub "${ProjectID}-subnet-dev-1a"
Cloud9作成用テンプレート
Cloud9を作成するテンプレートは以下の通りです。
|
ProjectID
|
任意(Cloud9の環境名に利用しています) |
|
IAMUserName
|
利用するIAMユーザ名を入力してください |
|
SelectInstanceType
|
Cloud9環境のインスタンスタイプを入力してください |
|
SubnetID
|
Cloud9環境を配置するサブネットのIDを入力してください |
AWSTemplateFormatVersion: "2010-09-09"
Description: "Cloud9 Template"
Parameters:
ProjectID:
Type: String
MinLength: 3
MaxLength: 15
IAMUserName:
Type: String
SelectInstanceType:
Type: String
Default: t2.micro
AllowedValues:
- t2.micro
- t3.small
- m5.large
# Please rewrite the subnet ID before use.
SubnetID:
Type: String
Default: subnet-xxxxxxxxxxxx
# AllowedValues:
# - subnet-xxxxxxxxxxxx
# - subnet-yyyyyyyyyyyy
Resources:
# ================================
# Cloud9
# ================================
Cloud9Instance:
Type: AWS::Cloud9::EnvironmentEC2
Properties:
AutomaticStopTimeMinutes: 60
ConnectionType: CONNECT_SSM
Description: !Sub "${IAMUserName}-${ProjectID}-cloud9-ide"
ImageId: "resolve:ssm:/aws/service/cloud9/amis/amazonlinux-2-x86_64"
InstanceType: !Ref SelectInstanceType
Name: !Sub "${IAMUserName}-${ProjectID}-cloud9-ide"
OwnerArn: !Sub "arn:aws:iam::${AWS::AccountId}:user/${IAMUserName}"
SubnetId: !Ref SubnetID
Outputs:
Cloud9IDEURL:
Description: Cloud9 IDE URL
Value: !Join
- ""
- - "https://ap-northeast-1.console.aws.amazon.com/cloud9/ide/"
- !Ref Cloud9Instance
Cloud9環境には、コンソールまたはCFnのOutputsで出力されたURLからアクセスできます。
終わりに
今回は、インフラ担当者がCloud9環境を払い出すという目的になっています。開発者自身に環境を払い出してもらう場合には、サービスカタログに登録することをお勧めします。
下記のCloud9とサービスカタログのエンドユーザ系の権限だけで利用できるので、不用意に強い権限を与えることなく開発環境を利用できます。
|
AWSCloud9EnvironmentMember |
|
AWSServiceCatalogEndUserFullAccess |
ぜひ、テンプレートを活用してたくさん環境を作成しましょう。
