あめがえるのITブログ

頑張りすぎない。ほどほどに頑張るブログ。

AWS CloudShellのVPC内起動を試してみた


CloudShellがVPC内で起動できるようになったらしいので試してみた

やること

AWS CloudShellをVPC内で起動し、PrivateSubnetからDBSubnetのRDS(mysql)へ接続する

実践!

1.環境作成
1-1.下記CloudFormationを実行

AWSTemplateFormatVersion: '2010-09-09'
Description: Stack to create VPC, subnets, EC2 instance, NAT Gateway, RDS instance with Secrets Manager

Parameters:
  VpcCIDR:
    Type: String
    Default: '10.0.0.0/16'
    Description: CIDR block for the VPC
  PublicSubnetCIDR:
    Type: String
    Default: '10.0.1.0/24'
    Description: CIDR block for the public subnet
  PrivateSubnet1CIDR:
    Type: String
    Default: '10.0.2.0/24'
    Description: CIDR block for the first private subnet
  PrivateSubnet2CIDR:
    Type: String
    Default: '10.0.3.0/24'
    Description: CIDR block for the second private subnet
  DbSubnet1CIDR:
    Type: String
    Default: '10.0.4.0/24'
    Description: CIDR block for the first DB subnet
  DbSubnet2CIDR:
    Type: String
    Default: '10.0.5.0/24'
    Description: CIDR block for the second DB subnet
  InstanceType:
    Type: String
    Default: 't2.micro'
    Description: EC2 instance type
  AMIID:
    Type: String
    Default: 'ami-061a125c7c02edb39'
    Description: Amazon Linux 2023 AMI

Resources:
  MyVPC:
    Type: AWS::EC2::VPC
    Properties:
      CidrBlock: !Ref VpcCIDR
      EnableDnsSupport: true
      EnableDnsHostnames: true
      Tags:
        - Key: Name
          Value: MyVPC

  PublicSubnet:
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !Ref MyVPC
      CidrBlock: !Ref PublicSubnetCIDR
      MapPublicIpOnLaunch: true
      Tags:
        - Key: Name
          Value: PublicSubnet

  PrivateSubnet1:
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !Ref MyVPC
      CidrBlock: !Ref PrivateSubnet1CIDR
      AvailabilityZone: !Select [ 0, !GetAZs '' ]
      Tags:
        - Key: Name
          Value: PrivateSubnet1

  PrivateSubnet2:
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !Ref MyVPC
      CidrBlock: !Ref PrivateSubnet2CIDR
      AvailabilityZone: !Select [ 1, !GetAZs '' ]
      Tags:
        - Key: Name
          Value: PrivateSubnet2

  DbSubnet1:
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !Ref MyVPC
      CidrBlock: !Ref DbSubnet1CIDR
      AvailabilityZone: !Select [ 0, !GetAZs '' ]
      Tags:
        - Key: Name
          Value: DbSubnet1

  DbSubnet2:
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !Ref MyVPC
      CidrBlock: !Ref DbSubnet2CIDR
      AvailabilityZone: !Select [ 1, !GetAZs '' ]
      Tags:
        - Key: Name
          Value: DbSubnet2

  InternetGateway:
    Type: AWS::EC2::InternetGateway
    Properties:
      Tags:
        - Key: Name
          Value: InternetGateway

  AttachGateway:
    Type: AWS::EC2::VPCGatewayAttachment
    Properties:
      VpcId: !Ref MyVPC
      InternetGatewayId: !Ref InternetGateway

  RouteTable:
    Type: AWS::EC2::RouteTable
    Properties:
      VpcId: !Ref MyVPC

  PublicRoute:
    Type: AWS::EC2::Route
    DependsOn: AttachGateway
    Properties:
      RouteTableId: !Ref RouteTable
      DestinationCidrBlock: '0.0.0.0/0'
      GatewayId: !Ref InternetGateway

  NatGatewayEIP:
    Type: AWS::EC2::EIP
    Properties:
      Domain: vpc

  NatGateway:
    Type: AWS::EC2::NatGateway
    Properties:
      AllocationId: !GetAtt NatGatewayEIP.AllocationId
      SubnetId: !Ref PublicSubnet

  PrivateRouteTable1:
    Type: AWS::EC2::RouteTable
    Properties:
      VpcId: !Ref MyVPC

  PrivateRoute1:
    Type: AWS::EC2::Route
    Properties:
      RouteTableId: !Ref PrivateRouteTable1
      DestinationCidrBlock: '0.0.0.0/0'
      NatGatewayId: !Ref NatGateway

  PrivateRouteTableAssociation1:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      SubnetId: !Ref PrivateSubnet1
      RouteTableId: !Ref PrivateRouteTable1

  PrivateRouteTable2:
    Type: AWS::EC2::RouteTable
    Properties:
      VpcId: !Ref MyVPC

  PrivateRoute2:
    Type: AWS::EC2::Route
    Properties:
      RouteTableId: !Ref PrivateRouteTable2
      DestinationCidrBlock: '0.0.0.0/0'
      NatGatewayId: !Ref NatGateway

  PrivateRouteTableAssociation2:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      SubnetId: !Ref PrivateSubnet2
      RouteTableId: !Ref PrivateRouteTable2

  PublicRouteTable:
    Type: AWS::EC2::RouteTable
    Properties:
      VpcId: !Ref MyVPC

  PublicRoute1:
    Type: AWS::EC2::Route
    Properties:
      RouteTableId: !Ref PublicRouteTable
      DestinationCidrBlock: '0.0.0.0/0'
      GatewayId: !Ref InternetGateway

  PublicRouteTableAssociation:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      SubnetId: !Ref PublicSubnet
      RouteTableId: !Ref PublicRouteTable

  DbRouteTable1:
    Type: AWS::EC2::RouteTable
    Properties:
      VpcId: !Ref MyVPC

  DbRoute1:
    Type: AWS::EC2::Route
    Properties:
      RouteTableId: !Ref DbRouteTable1
      DestinationCidrBlock: '0.0.0.0/0'
      NatGatewayId: !Ref NatGateway

  DbRouteTableAssociation1:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      SubnetId: !Ref DbSubnet1
      RouteTableId: !Ref DbRouteTable1

  DbRouteTable2:
    Type: AWS::EC2::RouteTable
    Properties:
      VpcId: !Ref MyVPC

  DbRoute2:
    Type: AWS::EC2::Route
    Properties:
      RouteTableId: !Ref DbRouteTable2
      DestinationCidrBlock: '0.0.0.0/0'
      NatGatewayId: !Ref NatGateway

  DbRouteTableAssociation2:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      SubnetId: !Ref DbSubnet2
      RouteTableId: !Ref DbRouteTable2

  DBSubnetGroup:
    Type: AWS::RDS::DBSubnetGroup
    Properties:
      DBSubnetGroupDescription: "Subnet group for RDS"
      SubnetIds:
        - !Ref DbSubnet1
        - !Ref DbSubnet2
        
  DBSecret:
    Type: AWS::SecretsManager::Secret
    Properties:
      Description: "Secrets for RDS access"
      GenerateSecretString:
        SecretStringTemplate: '{"username": "admin"}'
        GenerateStringKey: "password"
        PasswordLength: 16
        ExcludeCharacters: '"@/\'

  DBInstance:
    Type: AWS::RDS::DBInstance
    Properties:
      DBInstanceClass: db.t3.micro
      AllocatedStorage: 20
      Engine: mysql
      EngineVersion: "8.0.37"
      DBSubnetGroupName: !Ref DBSubnetGroup
      MasterUsername: !Sub '{{resolve:secretsmanager:${DBSecret}:SecretString:username}}'
      MasterUserPassword: !Sub '{{resolve:secretsmanager:${DBSecret}:SecretString:password}}'


2.CloudShellをVPC内で起動する
※今回はCloudFormationで作成したPrivateSubnetに設置する
2-1.[AWS] - [CloudShell]

2-2.[アクション] - [Create VPC Environment (max 2)]

2-3.下記を入力
 Name:CloudShell名
 Virtual private cloud (VPC):CloudFormationで作成したVPC
 Subnet:CloudFormationで作成したPrivateSubnet1
 SecurityGroup:CloudFormationで作成したVPCのデフォルトのSG

2-4.[Create]

3.RDS(mysql)接続情報確認(SecretsManager)
3-1.[AWS] - [SecretsManager]
3-2.CloudFormationで作成したシークレットを選択

3-3.[シークレットの値を取得する]

3-4.usernameとpasswordを控える

4.RDS(mysql)接続情報確認(RDS)
4-1.[AWS] - [RDS]
4-2.CloudFormationで作成したデータベースを選択

4-3.エンドポイント名を控える

5.RDS接続確認
5-1.通常のCloudShellとVPC内起動のCloudShellで下記を実行し、VPC内起動のもののみRDSへ接続できることを確認

mysql -h <RDSエンドポイント名> -u admin -p
例)mysql -h test-stack01-dbinstance-v6xejjmv8e49.ckmgc9vjvwrf.ap-northeast-1.rds.amazonaws.com -u admin -p

5-2.Enter Passwordが表6示されたらシークレットのpasswordを入力

通常のClouShell

VPC内起動のCloudShell(MySQL [(none)]が表示される)

6.CloudShell環境削除
6-1.[AWS] - [CloudShell]
6-2.VPC内で起動したCloudShellを選択

6-3.[アクション] - [AWS CloudShell 環境を削除]

6-4.[delete]を入力し、[削除]

6-5.削除されたことを確認



感想

これでRDSメンテナンス用の踏み台がいらなくなるかも!