目次
はじめに
EC2を使って検証してみよーっと
の前にVPCから構築しなきゃ。。。
ってこと皆さん経験あるでしょうか。
自分はしょっちゅうあります(笑)
1度作成したリソースをそのまま残しておけば検証は楽ですが、思わぬとこでコストがかかってしまったり、多額の請求につながってしまう恐れがあります。
簡単な検証をするためにいちいちサブネット作って、SGを設定して、エンドポイント作成したけど、セッションマネージャでうまく繋がらなかった時ってめちゃくちゃストレスですよね。。。
どこの設定を間違えているかか探す時間がもったいないし
ということでセッションマネージャーで接続可能な検証用EC2を手軽に構築できるCloudFormationテンプレートを作成しました。
セッションマネージャーとは
めっっっっっちゃくちゃ簡単にまとめるとSSH鍵を使用せず、EC2に接続できるサービスです。
プライベートサブネットに配置したEC2に接続しようとした場合、パブリックIPアドレスが振られていないので直接SSHで接続することができず、パブリックサブネットに配置した踏み台サーバ等からSSHで接続する必要があります。
セッションマネージャーを使用するとAWSコンソール画面からプライベートサブネット内のEC2に直接接続でき、踏み台サーバやSSH鍵が不要になります。
構築概要図
今回CloudFormationでテンプレート化したNATGatewayを使用した構成の概要図です。
(図には記載がないですが、SGで疎通を制限したり、IAMロールもアタッチします)
セッションマネージャーを使用したEC2への接続方法はいくつか方法があります。
ここではNATGatewayを使用した方法を解説します。
ほかの接続方法についても記事を書こうと思いますので気になる方は読んでいただけたらと思います。
スタックの作成
前置きが長くなってしまいましたが本題のテンプレートです。
各パラメータの説明とかどうやってここまで書き上げたかって話を書いちゃうと
めちゃくちゃ長くて読む気が失せると思うので今回は割愛します。
近いうちに別の記事で紹介できたらなと思ってますので、もしよかったら読んでください。
AWSTemplateFormatVersion: 2010-09-09
Description:
Cfn templete for session-manager
Parameters:
VPCName:
Type: String
Default: SesssionManagerNatGateway
VPCCidrBlock:
Type: String
Default: 10.0.0.0/16
PrivateSubnetCidrBlock:
Type: String
Default: 10.0.1.0/24
PublicSubnetCidrBlock:
Type: String
Default: 10.0.2.0/24
#PublicSubnetのAZに指定
AZ1:
Type: String
AllowedValues:
- ap-northeast-1a
- ap-northeast-1c
- ap-northeast-1d
#PrivateSubnetのAZに指定
AZ2:
Type: String
AllowedValues:
- ap-northeast-1a
- ap-northeast-1c
- ap-northeast-1d
#起動するEC2のAMIに書き換えて使用
CustomAMI:
Type: String
Default: ami-*******
AllowedValues:
-ami-*******
-ami-*******
-ami-*******
-ami-*******
InstanceType:
Type: String
Default: t2.micro
AllowedValues:
- t2.micro
- t3.micro
- t3.small
- m1.small
Resources:
VPC:
Type: AWS::EC2::VPC
Properties:
CidrBlock: !Ref VPCCidrBlock
Tags:
- Key: Name
Value: !Ref VPCName
PrivateSubnet:
Type: AWS::EC2::Subnet
Properties:
AvailabilityZone: !Ref AZ1
VpcId: !Ref VPC
CidrBlock: !Ref PrivateSubnetCidrBlock
MapPublicIpOnLaunch: 'false'
Tags:
- Key: Name
Value: SSMPrvSub
PublicSubnet:
Type: AWS::EC2::Subnet
Properties:
AvailabilityZone: !Ref AZ2
VpcId: !Ref VPC
CidrBlock: !Ref PublicSubnetCidrBlock
Tags:
- Key: Name
Value: SSMPubSub
NatGateway:
Type: AWS::EC2::NatGateway
DependsOn: AttachIGW
Properties:
AllocationId: !GetAtt ElasticIP.AllocationId
ConnectivityType: public
SubnetId: !Ref PublicSubnet
Tags:
- Key: Name
Value: SSMNatGW
ElasticIP:
Type: AWS::EC2::EIP
Properties:
Domain: vpc
Tags:
- Key: Name
Value: SSM-NatIP
InternetGateway:
Type: AWS::EC2::InternetGateway
Properties:
Tags:
- Key: Name
Value: SSM-IGW-cfn
AttachIGW:
Type: AWS::EC2::VPCGatewayAttachment
DependsOn: VPC
Properties:
VpcId: !Ref VPC
InternetGatewayId: !Ref InternetGateway
PublicSubRouteTable:
Type: AWS::EC2::RouteTable
Properties:
VpcId: !Ref VPC
Tags:
- Key: Name
Value: SSMPublicRouteTable
PrivateSubRouteTable:
Type: AWS::EC2::RouteTable
Properties:
VpcId: !Ref VPC
Tags:
- Key: Name
Value: SSMPrivateRouteTable
ToNATRoute:
DependsOn: NatGateway
Type: AWS::EC2::Route
Properties:
DestinationCidrBlock: 0.0.0.0/0
NatGatewayId: !Ref NatGateway
RouteTableId: !Ref PrivateSubRouteTable
ToIGWRoute:
DependsOn: InternetGateway
Type: AWS::EC2::Route
Properties:
DestinationCidrBlock: 0.0.0.0/0
GatewayId: !Ref InternetGateway
RouteTableId: !Ref PublicSubRouteTable
PubAssociateRouteTable:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
RouteTableId: !Ref PublicSubRouteTable
SubnetId: !Ref PublicSubnet
PriAssociateRouteTable:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
RouteTableId: !Ref PrivateSubRouteTable
SubnetId: !Ref PrivateSubnet
SecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
VpcId: !Ref VPC
GroupDescription: SecurityGroup-for-SessionManager
SecurityGroupEgress:
- CidrIp: 0.0.0.0/0
IpProtocol: tcp
FromPort: 443
ToPort: 443
Tags:
- Key: Name
Value: NatEC2ssessionmanagerSG
InstanceProfile:
DependsOn: SessionManagerRole
Type: AWS::IAM::InstanceProfile
Properties:
Path: '/'
Roles:
- !Ref SessionManagerRole
SessionManagerRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: 'Allow'
Principal:
Service:
- 'ec2.amazonaws.com'
Action:
- 'sts:AssumeRole'
Path: '/'
RoleName: SessionManager-role-cfn
ManagedPolicyArns:
- arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore
myEC2Instance:
Type: AWS::EC2::Instance
DependsOn: PrivateSubnet
Properties:
ImageId: !Ref CustomAMI
InstanceType: !Ref InstanceType
SubnetId: !Ref PrivateSubnet
IamInstanceProfile: !Ref InstanceProfile
SecurityGroupIds:
- !Ref SecurityGroup
Tags:
- Key: Name
Value: Cfn-nat-ssm
まずCloudFormationのコンソール画面を開き、「スタックの作成」の「新しいリソースを使用(標準)」
を押下します。
「ファイルの選択」から起動したいテンプレートをアップロードします。
今回はテンプレートで定義したデフォルト値で設定します。
AZは好きなところを選んでください。
必要に応じてタグやスタックポリシー等を設定してください。
作成に時間がかかるリソースが多い場合は「スタック失敗オプション」で「正常にプロビジョニングされたリソースの保持」を選択することで、ロールバックされずに済みます。
次の画面で「AWS CloudFoamationリソースがカスタム名で作成される場合があることを承認します」にチェックを入れて、「スタックの作成」を押下すると作成が始まります。
EC2にセッションマネージャで接続するための権限(AmazonSSMManagedInstanceCore)を付与したロールをこのテンプレートで作成するので、チェックは必ず入れてください。
稼働確認
テンプレートからスタックを作成したら作成完了まで待ちます。
スタック名に指定した論理IDのステータスが「CREATE_COMPLETE」になれば成功です。
今回は「Test-Stack-SessionManager」というスタック名で作成しています。
VPCを確認すると指定したCIDRで作成されていることが確認できました。
EC2のコンソール画面で接続したいインスタンスを選択し、「接続」を押下します。
セッションマネージャの接続が可能な状態になって入れば「接続」の文字がオレンジになります。
よくある設定ミス
AWSの勉強を始めたばかりのころに自分も経験したのですが、セッションマネージャーで接続するためにはVPCにサブネットを作成し、EC2を起動するだけでは接続できません。
セッションマネージャーで接続できない場合によくある設定ミスをいくつか挙げておきます。
- 接続先EC2にアタッチしたロールに「AmazonSSMManagedInstanceCore」ポリシーがアタッチされていない
- 接続対象インスタンスにSSmエージェントがインストールされていない
- SGのアウトバウンド:443が許可されていない(SSMエージェントが使用するポート)
- NACLでインバウンド・アウトバウンドが許可されていない、もしくは拒否されている
(NACLはステートレスなのでインバウンド・アウトバウンドで明示的な許可が必要です)
さいごに
初めて記事を書いたのでまだまだ読みづらい箇所が多いかと思いますが、たくさん書いて読みやすい記事を書けるように頑張ります!