AWS CDKで踏み台サーバ(EC2)をデプロイする方法

AWS CDKで踏み台サーバ(EC2)をデプロイする方法

項目バージョン
CDK2.27.0

AWS CDKで踏み台サーバ(EC2)をデプロイする方法です。プライベートサブネットにデプロイしています。

踏み台サーバの場合はEC2のクラスでもOKですが、踏み台サーバ専用のBastionHostLinuxクラスが用意されているようです。

既存のVPCにプライベートサブネットがあればデフォルトではプライベートサブネットにEC2が作成されるようです。

Type: SubnetSelection (optional, default: private subnets of the supplied VPC)

Select the subnets to run the bastion host in.

Set this to PUBLIC if you need to connect to this instance via the internet and cannot use SSM. You have to allow port 22 manually by using the connections field

また、machineImageが未指定の場合は、SSMエージェントがプリインストールされているAMIが選択されるようです。

Type: IMachineImage (optional, default: An Amazon Linux 2 image which is kept up-to-date automatically (the instance may be replaced on every deployment) and already has SSM Agent installed.)

The machine image to use, assumed to have SSM Agent preinstalled.

という事は、あとはVPCエンドポイントとセキュリティグループの設定だけ別途作成が必要になるっぽいです。

VPCエンドポイント作成

VPCエンドポイントで以下3つ作成します。

  • com.amazonaws.ap-northeast-1.ssm
  • com.amazonaws.ap-northeast-1.ssmmessages
  • com.amazonaws.ap-northeast-1.ec2messages

tsファイルで以下のように3つ作成します。

const endpoints : Array<[string, string]> =
  [['com.amazonaws.ap-northeast-1.ssm', 'ssm'],
   ['com.amazonaws.ap-northeast-1.ec2messages', 'ec2messages'],
   ['com.amazonaws.ap-northeast-1.ssmmessages', 'ssmmessages']]

for(const data of endpoints) {
  new ec2.InterfaceVpcEndpoint(this, data[1], {
    vpc,
    service: new ec2.InterfaceVpcEndpointService(data[0], 443),
    privateDnsEnabled: true
  });
}

以下のように3つ作成されます。

AWS CDKで踏み台サーバ(EC2)をデプロイする方法

※既存VPC上にデプロイする場合はsubnetsオプションの指定が必要です

const endpoints : Array<[string, string]> =
  [['com.amazonaws.ap-northeast-1.ssm', 'ssm'],
   ['com.amazonaws.ap-northeast-1.ec2messages', 'ec2messages'],
   ['com.amazonaws.ap-northeast-1.ssmmessages', 'ssmmessages']]

for(const data of endpoints) {
  new ec2.InterfaceVpcEndpoint(this, data[1], {
    vpc,
    service: new ec2.InterfaceVpcEndpointService(data[0], 443),
    subnets: {
      subnetType: ec2.SubnetType.PUBLIC // 明示的に指定
    },
    privateDnsEnabled: true
  });
}

EC2作成(踏み台サーバ)

EC2(踏み台サーバ)をBastionHostLinuxクラスから作成します。

const ec2InstanceSG = new ec2.SecurityGroup(this, 'ec2-instance-sg', {
  vpc, // vpcの変数 CIDR 10.0.0.0/16
  allowAllOutbound: false // アウトバウンドはデフォルトがtrueなのでfalseにしておく
});

ec2InstanceSG.addEgressRule( // アウトバウンド
  ec2.Peer.ipv4('10.0.0.0/16'), // VPCと同じCIDR指定
  ec2.Port.tcp(443)
);

アウトバウンドがvpcと同じCIDRで443解放されています。

AWS CDKで踏み台サーバ(EC2)をデプロイする方法

import { Stack, StackProps } from 'aws-cdk-lib';
import * as ec2 from 'aws-cdk-lib/aws-ec2';
import { Construct } from 'constructs';

export class Sample001Stack extends Stack {
  constructor(scope: Construct, id: string, props?: StackProps) {
    super(scope, id, props);

    // create the VPC
    const vpc = new ec2.Vpc(this, 'vpc-sample-cdk', {
      cidr: '10.0.0.0/16',
      natGateways: 0,
      maxAzs: 2,
      subnetConfiguration: [
        {
          name: 'public-subnet',
          subnetType: ec2.SubnetType.PUBLIC,
          cidrMask: 24,
        },
        {
          name: 'isolated-subnet',
          subnetType: ec2.SubnetType.PRIVATE_ISOLATED,
          cidrMask: 24,
        }
      ]
    });

    const endpoints : Array<[string, string]> =
      [['com.amazonaws.ap-northeast-1.ssm', 'ssm'],
       ['com.amazonaws.ap-northeast-1.ec2messages', 'ec2messages'],
       ['com.amazonaws.ap-northeast-1.ssmmessages', 'ssmmessages']]

    for(const data of endpoints) {
      new ec2.InterfaceVpcEndpoint(this, data[1], {
        vpc,
        service: new ec2.InterfaceVpcEndpointService(data[0], 443),
        privateDnsEnabled: true // プライベートDNS有効化しておく
      });
    }
    const subnetSelection: ec2.SubnetSelection = {
      subnetType: ec2.SubnetType.PRIVATE_ISOLATED, onePerAz: true
    };
    new ec2.GatewayVpcEndpoint(this, 's3gateway', {
      vpc,
      service: ec2.GatewayVpcEndpointAwsService.S3,
      subnets: [subnetSelection]
    });
    // create a security group for the EC2 instance
    const ec2InstanceSG = new ec2.SecurityGroup(this, 'ec2-instance-sg', {
      vpc,
      allowAllOutbound: false // アウトバウンドはデフォルトがtrueなのでfalseにしておく
    });

    ec2InstanceSG.addEgressRule( // アウトバウンド
      ec2.Peer.ipv4('0.0.0.0/0'),
      ec2.Port.tcp(80)
    );
    ec2InstanceSG.addEgressRule( // アウトバウンド
      ec2.Peer.ipv4('0.0.0.0/0'),
      ec2.Port.tcp(443)
    );

    // 踏み台サーバ
    const host = new ec2.BastionHostLinux(this, 'BastionHost', {
      vpc,
      instanceName: "bastion",
      instanceType: ec2.InstanceType.of(ec2.InstanceClass.T3, ec2.InstanceSize.MEDIUM),
      subnetSelection: {
        subnetType: ec2.SubnetType.PRIVATE_ISOLATED // プライベートサブネットにEC2配置
      },
      securityGroup: ec2InstanceSG
    });

  }
}

これでデプロイします。

cdk deploy

デプロイに199.12sかかりました、EC2が作成されます。

AWS CDKで踏み台サーバ(EC2)をデプロイする方法

SSMで接続確認OKです。

AWS CDKで踏み台サーバ(EC2)をデプロイする方法

AWS CDKで踏み台サーバ(EC2)をデプロイする方法

yumが使えるように「com.amazonaws.ap-northeast-1.s3」のVPCエンドポイント(Gatewayタイプ)を作成する、またアウトバウンド80と443を開放する必要があります。

yumコマンドが実行できることが確認できます。

AWS CDKで踏み台サーバ(EC2)をデプロイする方法

参考サイト

class BastionHostLinux (construct) · AWS CDK
# class BastionHostLinux (construct)
class InterfaceVpcEndpoint (construct) · AWS CDK
# class InterfaceVpcEndpoint (construct)
Deploy bastion hosts into private subnets with AWS CDK | Amazon Web Services
Learn how to use AWS CDK to deploy bastion hosts into private subnets of a VPC.
Create a bastion with AWS CDK
And access to it with AWS Systems Manager Session Manager
セッションマネージャーでEC2に接続できない時に確認した点 | DevelopersIO
はじめに こんにちは、川村です。 SSMを利用してEC2に接続しようとした時に、うまく接続できないことがありました。 その時に確認した点をまとめました。 前提 今回接続したEC2はプライベートサブネット配下 …
プライベートサブネットにあるEC2インスタンスを Systems Manager で管理する | DevelopersIO
困っていた内容 プライベートサブネットにあるEC2インスタンスがSSMのマネージドインスタンスに表示されない。 どう対応すればいいの? プライベートサブネットにあるインターネットアクセス出来ないEC2インスタンスをSSM …
SecurityGroup.addEgressRule doesn't add rules · Issue #5458 · aws/aws-cdk
When using addEgressRule, no matter what rules I seem to put in I only ever get the default "All outbound traffic" rule: "Type": "AWS::...
インターネットにアクセスせずに自分の AL1 または AL2 EC2 インスタンスで yum を更新する

コメント

タイトルとURLをコピーしました