0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【Amazon Linux 2023】プライベートサブネット内EC2にNAT Gateway無しでパッケージをインストールする方法

Posted at

はじめに

セキュリティ向上のため、EC2インスタンスをプライベートサブネットに配置することがあります。
この場合、インターネット通信が制限されるため、通常の手段では外部リソースに接続してパッケージをインストールしたり更新したりできません。

一般的には、パッケージの更新やインターネット通信が必要な際、パブリックサブネットにNAT Gatewayを配置し、EC2インスタンスからの通信を通過させる方法が考えられます。
しかし、Amazon LinuxのパッケージはS3にホストされているため、NAT Gatewayを設置しなくても、S3のゲートウェイ型VPCエンドポイントを活用すれば、インターネット接続なしでパッケージのインストール・更新が可能です。

実際に構築してみた

以下に、NAT Gatewayを使用せずに、プライベートサブネット内でパッケージ更新を可能にするCloudFormationテンプレート全体を示します。
このテンプレートでは以下のリソースを構築します。
 VPC
 プライベートサブネット
 プライベートサブネット用ルートテーブル
 EC2・SSM用セキュリティグループ
 SSM接続用VPCエンドポイント
 S3ゲートウェイ型VPCエンドポイント
 EC2(Amazon Linux 2023)
 EC2用IAMロール

template.yml
AWSTemplateFormatVersion: 2010-09-09

Resources:
  # VPC作成
  MyVPC:
    Type: AWS::EC2::VPC
    Properties:
      CidrBlock: 10.0.0.0/16
      EnableDnsSupport: true
      EnableDnsHostnames: true

  # プライベートサブネット作成
  PrivateSubnet:
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !Ref MyVPC
      CidrBlock: 10.0.1.0/24
      
  # プライベートサブネット用ルートテーブル作成
  PrivateSubnetRouteTable:
    Type: AWS::EC2::RouteTable
    Properties:
      VpcId: !Ref MyVPC

  # プライベートサブネットにルートテーブルをアタッチ
  PrivateSubnetRoute:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      SubnetId: !Ref PrivateSubnet
      RouteTableId: !Ref PrivateSubnetRouteTable

  # SSM用セキュリティグループの作成
  MySSMSecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: "for SSM VPC Endpoint"
      VpcId: !Ref MyVPC
      
  # EC2用セキュリティグループの作成
  MyEC2SecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: "Allow outbound access to S3"
      VpcId: !Ref MyVPC
      
  # SSM用セキュリティグループのインバウンドルールに、EC2からの疎通を許可するルールを追加
  MySSMSecurityGroupIngress: 
    Type: AWS::EC2::SecurityGroupIngress
    Properties:
      GroupId: !Ref MySSMSecurityGroup
      IpProtocol: tcp
      FromPort: 443
      ToPort: 443
      SourceSecurityGroupId: !GetAtt MyEC2SecurityGroup.GroupId

  # EC2用セキュリティグループのアウトバウンドルールに、SSM用VPCエンドポイントへの疎通を許可するルールを追加
  MyEC2SecurityGroupEgressAllowToSSM: 
    Type: AWS::EC2::SecurityGroupEgress
    Properties:
      GroupId: !Ref MyEC2SecurityGroup
      IpProtocol: tcp
      FromPort: 443
      ToPort: 443
      DestinationSecurityGroupId: !GetAtt MySSMSecurityGroup.GroupId

  # EC2用セキュリティグループのアウトバウンドルールに、S3への疎通を許可するルールを追加
  MyEC2SecurityGroupEgressAllowToS3: 
    Type: AWS::EC2::SecurityGroupEgress
    Properties:
      GroupId: !Ref MyEC2SecurityGroup
      IpProtocol: tcp
      FromPort: 443
      ToPort: 443
      DestinationPrefixListId: pl-61a54008

  # SSM用VPCエンドポイントの作成
  VPCEndpointSSM:
    Type: AWS::EC2::VPCEndpoint
    Properties:
      ServiceName: !Sub com.amazonaws.${AWS::Region}.ssm
      VpcId: !Ref MyVPC
      SubnetIds: [!Ref PrivateSubnet]
      VpcEndpointType: Interface
      PrivateDnsEnabled: true
      SecurityGroupIds: [!Ref MySSMSecurityGroup]

  # EC2メッセージング用VPCエンドポイントの作成
  VPCEndpointEC2Messages:
    Type: AWS::EC2::VPCEndpoint
    Properties:
      ServiceName: !Sub com.amazonaws.${AWS::Region}.ec2messages
      VpcId: !Ref MyVPC
      SubnetIds: [!Ref PrivateSubnet]
      VpcEndpointType: Interface
      PrivateDnsEnabled: true
      SecurityGroupIds: [!Ref MySSMSecurityGroup]

  # SSMメッセージング用VPCエンドポイントの作成
  VPCEndpointSSMMessage:
    Type: AWS::EC2::VPCEndpoint
    Properties:
      ServiceName: !Sub com.amazonaws.${AWS::Region}.ssmmessages
      VpcId: !Ref MyVPC
      SubnetIds: [!Ref PrivateSubnet]
      VpcEndpointType: Interface
      PrivateDnsEnabled: true
      SecurityGroupIds: [!Ref MySSMSecurityGroup]

  # S3用VPCエンドポイントの作成
  S3VPCEndpoint:
    Type: AWS::EC2::VPCEndpoint
    Properties:
      VpcId: !Ref MyVPC
      ServiceName: !Sub com.amazonaws.${AWS::Region}.s3
      RouteTableIds:
        - !Ref PrivateSubnetRouteTable   # 対象サブネットのルートテーブルを紐づける

  # EC2作成
  MyEC2Instance:
    Type: AWS::EC2::Instance
    Properties:
      InstanceType: t3.micro
      SubnetId: !Ref PrivateSubnet
      BlockDeviceMappings:
        - DeviceName: /dev/xvda  
          Ebs:
            VolumeType: gp3
            VolumeSize: 30  
            Encrypted: true  # 暗号化を有効にする
      SecurityGroupIds:
        - !Ref MyEC2SecurityGroup
      ImageId: resolve:ssm:/aws/service/ami-amazon-linux-latest/al2023-ami-kernel-default-x86_64  # Amazon Linux 2023のAMI IDを指定
      IamInstanceProfile: !Ref MyInstanceProfile
      UserData:
        Fn::Base64: !Sub |
          #!/bin/bash
          sudo yum -y install http://s3-ap-northeast-1.amazonaws.com/amazon-ssm-ap-northeast-1/latest/linux_amd64/amazon-ssm-agent.rpm

  # インスタンスプロファイル作成
  MyInstanceProfile:
    Type: AWS::IAM::InstanceProfile
    Properties:
      Roles:
        - !Ref SSMRole

  # EC2用IAMロール作成
  SSMRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Version: "2012-10-17"
        Statement:
          - Effect: Allow
            Principal:
              Service: ec2.amazonaws.com
            Action: sts:AssumeRole
      ManagedPolicyArns:
        - arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore

次に各リソースの設定方法とポイントを解説します。

1. VPCとプライベートサブネット

まず、仮想ネットワーク(VPC)とその内部にプライベートサブネット、ルートテーブルを作成します。

template.yml
  # VPC作成
  MyVPC:
    Type: AWS::EC2::VPC
    Properties:
      CidrBlock: 10.0.0.0/16
      EnableDnsSupport: true
      EnableDnsHostnames: true

  # プライベートサブネット作成
  PrivateSubnet:
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !Ref MyVPC
      CidrBlock: 10.0.1.0/24
      
  # プライベートサブネット用ルートテーブル作成
  PrivateSubnetRouteTable:
    Type: AWS::EC2::RouteTable
    Properties:
      VpcId: !Ref MyVPC

  # プライベートサブネットにルートテーブルをアタッチ
  PrivateSubnetRoute:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      SubnetId: !Ref PrivateSubnet
      RouteTableId: !Ref PrivateSubnetRouteTable

2. EC2・SSM用セキュリティグループ

EC2とSSM用VPCエンドポイントに紐づけるセキュリティグループを作成します。
EC2用セキュリティグループのアウトバウンドルールには、以下のルールを追加します。
 SSM用VPCエンドポイントへのHTTPS通信を許可するルール
 S3のマネージドプレフィックスへのHTTPS通信を許可するルール
  ※ゲートウェイ型S3用VPCエンドポイントとの疎通に必要

SSM用セキュリティグループのインバウンドルールには、以下のルールを追加します。
 EC2からのHTTPS通信を許可するルール

template.yml
  # SSM用セキュリティグループの作成
  MySSMSecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: "for SSM VPC Endpoint"
      VpcId: !Ref MyVPC
      
  # EC2用セキュリティグループの作成
  MyEC2SecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: "Allow outbound access to S3"
      VpcId: !Ref MyVPC
      
  # SSM用セキュリティグループのインバウンドルールに、EC2からの疎通を許可するルールを追加
  MySSMSecurityGroupIngress: 
    Type: AWS::EC2::SecurityGroupIngress
    Properties:
      GroupId: !Ref MySSMSecurityGroup
      IpProtocol: tcp
      FromPort: 443
      ToPort: 443
      SourceSecurityGroupId: !GetAtt MyEC2SecurityGroup.GroupId

  # EC2用セキュリティグループのアウトバウンドルールに、SSM用VPCエンドポイントへの疎通を許可するルールを追加
  MyEC2SecurityGroupEgressAllowToSSM: 
    Type: AWS::EC2::SecurityGroupEgress
    Properties:
      GroupId: !Ref MyEC2SecurityGroup
      IpProtocol: tcp
      FromPort: 443
      ToPort: 443
      DestinationSecurityGroupId: !GetAtt MySSMSecurityGroup.GroupId

  # EC2用セキュリティグループのアウトバウンドルールに、S3への疎通を許可するルールを追加
  MyEC2SecurityGroupEgressAllowToS3: 
    Type: AWS::EC2::SecurityGroupEgress
    Properties:
      GroupId: !Ref MyEC2SecurityGroup
      IpProtocol: tcp
      FromPort: 443
      ToPort: 443
      DestinationPrefixListId: pl-61a54008

3. VPCエンドポイント

パッケージ更新に必要な通信先であるS3へ接続するために、S3のゲートウェイ型VPCエンドポイントを作成します。
このエンドポイントを、EC2が配置されているプライベートサブネットのルートテーブルに紐づけることが重要です。

また、マネジメントコンソール上でEC2へ接続するのに必要な以下のVPCエンドポイントも作成します。
 SSM用VPCエンドポイント
 EC2メッセージング用VPCエンドポイント
 SSMメッセージング用VPCエンドポイント
 S3用VPCエンドポイント

template.yml
  # SSM用VPCエンドポイントの作成
  VPCEndpointSSM:
    Type: AWS::EC2::VPCEndpoint
    Properties:
      ServiceName: !Sub com.amazonaws.${AWS::Region}.ssm
      VpcId: !Ref MyVPC
      SubnetIds: [!Ref PrivateSubnet]
      VpcEndpointType: Interface
      PrivateDnsEnabled: true
      SecurityGroupIds: [!Ref MySSMSecurityGroup]

  # EC2メッセージング用VPCエンドポイントの作成
  VPCEndpointEC2Messages:
    Type: AWS::EC2::VPCEndpoint
    Properties:
      ServiceName: !Sub com.amazonaws.${AWS::Region}.ec2messages
      VpcId: !Ref MyVPC
      SubnetIds: [!Ref PrivateSubnet]
      VpcEndpointType: Interface
      PrivateDnsEnabled: true
      SecurityGroupIds: [!Ref MySSMSecurityGroup]

  # SSMメッセージング用VPCエンドポイントの作成
  VPCEndpointSSMMessage:
    Type: AWS::EC2::VPCEndpoint
    Properties:
      ServiceName: !Sub com.amazonaws.${AWS::Region}.ssmmessages
      VpcId: !Ref MyVPC
      SubnetIds: [!Ref PrivateSubnet]
      VpcEndpointType: Interface
      PrivateDnsEnabled: true
      SecurityGroupIds: [!Ref MySSMSecurityGroup]

  # S3用VPCエンドポイントの作成
  S3VPCEndpoint:
    Type: AWS::EC2::VPCEndpoint
    Properties:
      VpcId: !Ref MyVPC
      ServiceName: !Sub com.amazonaws.${AWS::Region}.s3
      RouteTableIds:
        - !Ref PrivateSubnetRouteTable  # 対象サブネットのルートテーブルを紐づける

4. EC2インスタンス

Amazon Linux 2023のEC2インスタンスをプライベートサブネット内に配置します。

template.yml
  # EC2作成
  MyEC2Instance:
    Type: AWS::EC2::Instance
    Properties:
      InstanceType: t3.micro
      SubnetId: !Ref PrivateSubnet
      BlockDeviceMappings:
        - DeviceName: /dev/xvda  
          Ebs:
            VolumeType: gp3
            VolumeSize: 30  
            Encrypted: true  # 暗号化を有効にする
      SecurityGroupIds:
        - !Ref MyEC2SecurityGroup
      ImageId: resolve:ssm:/aws/service/ami-amazon-linux-latest/al2023-ami-kernel-default-x86_64  # Amazon Linux 2023のAMI IDを指定
      IamInstanceProfile: !Ref MyInstanceProfile
      UserData:
        Fn::Base64: !Sub |
          #!/bin/bash
          sudo yum -y install http://s3-ap-northeast-1.amazonaws.com/amazon-ssm-ap-northeast-1/latest/linux_amd64/amazon-ssm-agent.rpm

5. IAMロール

セッションマネージャー経由でEC2に接続できるよう、EC2に付与するIAMロールにAmazonSSMManagedInstanceCoreのポリシーを設定します。

template.yml
  # インスタンスプロファイル作成
  MyInstanceProfile:
    Type: AWS::IAM::InstanceProfile
    Properties:
      Roles:
        - !Ref SSMRole

  # EC2用IAMロール作成
  SSMRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Version: "2012-10-17"
        Statement:
          - Effect: Allow
            Principal:
              Service: ec2.amazonaws.com
            Action: sts:AssumeRole
      ManagedPolicyArns:
        - arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore

デプロイ

上記テンプレートを用いてCloudFormationによるリソースデプロイを実施します。
デプロイ方法は以下記事で分かりやすく記載されていますので、こちらをご参照ください。
https://blog.serverworks.co.jp/2022/02/09/073000

検証

セッションマネージャーを使ったEC2への接続

AWSマネジメントコンソールでSystems ManagerのセッションマネージャーからEC2に接続し、パッケージインストールを試みます。
接続方法は下記をご参照ください。
https://baresupport.jp/blog/2022/03/14/82/#3-1_AWS_%E3%83%9E%E3%83%8D%E3%82%B8%E3%83%A1%E3%83%B3%E3%83%88%E3%82%B3%E3%83%B3%E3%82%BD%E3%83%BC%E3%83%AB%E3%81%8B%E3%82%89%E6%8E%A5%E7%B6%9A%E3%81%99%E3%82%8B%E5%A0%B4%E5%90%88

パッケージのインストール

接続後、以下のコマンドでパッケージを更新します。

sudo dnf install -y htop

インストールが成功すればOKです!
image.png

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?