プライベートサブネットにあるEC2にEC2 Instance Connectを利用して接続する環境をAWS CDKで構築してみた

プライベートサブネットにあるEC2にEC2 Instance Connectを利用して接続する環境をAWS CDKで構築してみた

2025.08.31

こんにちは!製造ビジネステクノロジー部の小林です。

今回は、プライベートIPアドレスとEC2 Instance Connect(EIC)を使って、EC2インスタンスへ接続する環境をAWS CDKで実装してみました。

EC2 Instance Connectとは?

EC2 Instance Connectは、踏み台ホストやVPNなしで、インターネットからパブリック/プライベートIPアドレスを使用してEC2インスタンスにSSH、RDP接続することをサポートするサービスです。
https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/connect-with-ec2-instance-connect-endpoint.html

EC2 Instance Connect使うと嬉しいこと

EC2 Instance Connectを使用することで、以下のようなメリットがあります。

  • パブリックIPアドレスをEC2インスタンスに割り当てる必要がなくなり、インターネットからの直接アクセスを排除できる
  • キーペアやインスタンスプロファイルの作成が不要
  • EC2 Instance Connect エンドポイントの料金は無料

プライベートIPアドレスとEC2 Instance Connect Endpointを使用した、EC2への接続を行う

プライベートIPアドレスとEC2 Instance Connect Endpointを使用した、EC2への接続は以下のようになります。
スクリーンショット 2025-08-31 1.16.25

やってみた

ではAWS CDKで以下のリソースを構築していきます。

  1. VPCを作成
  2. EC2インスタンス用セキュリティグループを作成
  3. EICエンドポイント用セキュリティグループを作成
  4. セキュリティグループの通信設定
  5. EICエンドポイントを作成
  6. EC2を作成

VPCの作成

まず、VPCを作成し、PRIVATE_ISOLATEDタイプのサブネットを定義します。

/**
 * VPCの作成
 */
const vpc = new ec2.Vpc(this, 'Vpc', {
  maxAzs: 2,
  subnetConfiguration: [
    {
      cidrMask: 24,
      name: 'PrivateIsolated',
      subnetType: ec2.SubnetType.PRIVATE_ISOLATED,
    },
  ],
});

セキュリティグループの作成

EC2インスタンスとEICエンドポイントそれぞれに専用のセキュリティグループを作成します。

EC2インスタンス用セキュリティグループを作成

/**
 * EC2インスタンス用のセキュリティグループ
 * EC2インスタンスへのSSH接続は、EC2 Instance Connect Endpoint エンドポイントのセキュリティグループからのみ許可
 */
const instanceSg = new ec2.SecurityGroup(this, 'Ec2InstanceSg', {
  vpc,
  allowAllOutbound: false, // アウトバウンドトラフィックを制限
});

EICエンドポイント用セキュリティグループを作成

/**
 * EC2 Instance Connect Endpoint 用のセキュリティグループ
 */
 const eicSg = new ec2.SecurityGroup(this, 'EicEndpointSg', {
 vpc,
 allowAllOutbound: false, // アウトバウンドトラフィックを制限
});

セキュリティグループの通信設定

EICエンドポイント用セキュリティグループからのSSH(ポート22)のみをEC2インスタンス用セキュリティグループに許可する設定を行います。これにより、EICエンドポイントを介した接続だけを許可します。

// EC2 Instance Connect Endpoint エンドポイント -> EC2インスタンスへのSSH接続を許可
eicSg.connections.allowTo(
  instanceSg,
  ec2.Port.tcp(22),
);

今回は、Connections という便利な機能を使ってシンプルに記述しています。詳細は以下をご覧ください。
https://dev.classmethod.jp/articles/shoma-using-aws-cdk-connections-class-to-write-security-group-rules-simply/

EICエンドポイントを作成

VPC内にEC2 Instance Connect Endpointを作成します。subnetIdには、先ほど作成したサブネットのIDを指定します。
https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ec2.CfnInstanceConnectEndpoint.html

// EC2 Instance Connect Endpointの作成
const eicEndpoint = new ec2.CfnInstanceConnectEndpoint(this, 'EicEndpoint', {
  subnetId: vpc.isolatedSubnets[0].subnetId,
  securityGroupIds: [eicSg.securityGroupId],
});

EC2を作成

PRIVATE_ISOLATEDサブネット内に、Amazon Linux 2023のEC2インスタンスを作成します。

/**
 * EC2インスタンスの作成
 */
const ec2Instance = new ec2.Instance(this, 'Ec2Instance', {
  vpc,
  vpcSubnets: {
    subnetType: ec2.SubnetType.PRIVATE_ISOLATED,
  },
  instanceType: ec2.InstanceType.of(
    ec2.InstanceClass.T3,
    ec2.InstanceSize.MICRO
  ),
  machineImage: new ec2.AmazonLinuxImage({
    generation: ec2.AmazonLinuxGeneration.AMAZON_LINUX_2023,
  }),
  securityGroup: instanceSg,
  disableApiTermination: false, // 検証用のためインスタンスの削除を許可
});

ここまでに説明したリソースをすべて含んだ、CDKの完全なソースコードは以下の通りです。

CDK全体のソース
import * as cdk from 'aws-cdk-lib';
import { Construct } from 'constructs';
import * as ec2 from 'aws-cdk-lib/aws-ec2';

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

    /**
     * VPCの作成
     */
    const vpc = new ec2.Vpc(this, 'Vpc', {
      maxAzs: 2,
      subnetConfiguration: [
        {
          cidrMask: 24,
          name: 'PrivateIsolated',
          subnetType: ec2.SubnetType.PRIVATE_ISOLATED,
        },
      ],
    });

    /**
     * EC2インスタンス用のセキュリティグループ
     * EC2インスタンスへのSSH接続は、EC2 Instance Connect Endpoint エンドポイントのセキュリティグループからのみ許可
     */
    const instanceSg = new ec2.SecurityGroup(this, 'Ec2InstanceSg', {
      vpc,
      allowAllOutbound: false, // アウトバウンドトラフィックを制限
    });

    /**
     * EC2 Instance Connect Endpoint 用のセキュリティグループ
     */
    const eicSg = new ec2.SecurityGroup(this, 'EicEndpointSg', {
      vpc,
      allowAllOutbound: false, // アウトバウンドトラフィックを制限
    });

    // EC2 Instance Connect Endpoint エンドポイント -> EC2インスタンスへのSSH接続を許可
    eicSg.connections.allowTo(
      instanceSg,
      ec2.Port.tcp(22),
    );

    // EC2 Instance Connect Endpointの作成
    const eicEndpoint = new ec2.CfnInstanceConnectEndpoint(this, 'EicEndpoint', {
      subnetId: vpc.isolatedSubnets[0].subnetId,
      securityGroupIds: [eicSg.securityGroupId],
    });

    /**
     * EC2インスタンスの作成
     */
    const ec2Instance = new ec2.Instance(this, 'Ec2Instance', {
      vpc,
      vpcSubnets: {
        subnetType: ec2.SubnetType.PRIVATE_ISOLATED,
      },
      instanceType: ec2.InstanceType.of(
        ec2.InstanceClass.T3,
        ec2.InstanceSize.MICRO
      ),
      machineImage: new ec2.AmazonLinuxImage({
        generation: ec2.AmazonLinuxGeneration.AMAZON_LINUX_2023,
      }),
      securityGroup: instanceSg,
      disableApiTermination: false, // 検証用のためインスタンスの削除を許可
    });
  }
}

EC2を作成
PRIVATE_ISOLATEDサブネット内に、Amazon Linux 2023のEC2インスタンスを作成します。EC2 Instance Connect経由のSSH接続を可能にするため、SSMと通信するためのIAMロールをインスタンスにアタッチします。

TypeScript

/**

  • EC2インスタンスの作成
    */
    const ec2Instance = new ec2.Instance(this, 'Ec2Instance', {
    vpc,
    vpcSubnets: {
    subnetType: ec2.SubnetType.PRIVATE_ISOLATED,
    },
    instanceType: ec2.InstanceType.of(
    ec2.InstanceClass.T3,
    ec2.InstanceSize.MICRO
    ),
    machineImage: new ec2.AmazonLinuxImage({
    generation: ec2.AmazonLinuxGeneration.AMAZON_LINUX_2023,
    }),
    securityGroup: instanceSg,
    disableApiTermination: false, // 検証用のためインスタンスの削除を許可
    });
    これで、EC2インスタンスが安全なプライベートネットワーク内に配置されました。

全体コード
ここまでに説明したリソースをすべて含んだ、CDKの完全なソースコードは以下の通りです。このコードを実行することで、今回の構成を一度にデプロイできます。

CDK全体のソース

TypeScript

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

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

/**
 * VPCの作成
 */
const vpc = new ec2.Vpc(this, 'Vpc', {
  maxAzs: 2,
  subnetConfiguration: [
    {
      cidrMask: 24,
      name: 'PrivateIsolated',
      subnetType: ec2.SubnetType.PRIVATE_ISOLATED,
    },
  ],
});

/**
 * EC2インスタンス用のセキュリティグループ
 * EC2インスタンスへのSSH接続は、EC2 Instance Connect Endpoint エンドポイントのセキュリティグループからのみ許可
 */
const instanceSg = new ec2.SecurityGroup(this, 'Ec2InstanceSg', {
  vpc,
  allowAllOutbound: false, // アウトバウンドトラフィックを制限
});

/**
 * EC2 Instance Connect Endpoint 用のセキュリティグループ
 */
const eicSg = new ec2.SecurityGroup(this, 'EicEndpointSg', {
  vpc,
  allowAllOutbound: false, // アウトバウンドトラフィックを制限
});

// EC2 Instance Connect Endpoint エンドポイント -> EC2インスタンスへのSSH接続を許可
eicSg.connections.allowTo(
  instanceSg,
  ec2.Port.tcp(22),
);

// EC2 Instance Connect Endpointの作成
const eicEndpoint = new ec2.CfnInstanceConnectEndpoint(this, 'EicEndpoint', {
  subnetId: vpc.isolatedSubnets[0].subnetId,
  securityGroupIds: [eicSg.securityGroupId],
});

/**
 * EC2インスタンスの作成
 */
const ec2Instance = new ec2.Instance(this, 'Ec2Instance', {
  vpc,
  vpcSubnets: {
    subnetType: ec2.SubnetType.PRIVATE_ISOLATED,
  },
  instanceType: ec2.InstanceType.of(
    ec2.InstanceClass.T3,
    ec2.InstanceSize.MICRO
  ),
  machineImage: new ec2.AmazonLinuxImage({
    generation: ec2.AmazonLinuxGeneration.AMAZON_LINUX_2023,
  }),
  securityGroup: instanceSg,
  disableApiTermination: false, // 検証用のためインスタンスの削除を許可
});

}
}

以上でリソースの作成は完了です!ターミナルで cdk deploy コマンドを実行して、リソースをデプロイしましょう。

動作確認

それでは、AWSコンソールとAWS CLIを使って、実際に接続できるか確認してみましょう。

AWSコンソールでの接続

AWSマネージメントコンソールからEC2の画面に移動し、作成したインスタンスを選択します。
スクリーンショット 2025-08-31 0.18.10

画面右上の「接続」を選択し、EC2 Instance Connectタブに移動します。「プライベート IP を使用して接続」にチェックが入っていることを確認し、「接続」ボタンを選択します。
スクリーンショット 2025-08-31 1.22.02
スクリーンショット 2025-08-31 1.23.18
スクリーンショット 2025-08-31 1.24.36
これで、ブラウザベースのターミナルが開き、無事接続できることを確認できました!

AWS CLIでの接続

次に、AWS CLIを使って接続してみましょう。今回は aws ec2-instance-connect ssh コマンドを使用します。
https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/connect-using-eice.html#eic-connect-using-cli

# 環境変数の設定
export INSTANCE_ID="i-XXXXXXXXXXXXXXXX"

# プライベートIPで接続(最大20同時接続、最大1時間セッション)
aws ec2-instance-connect ssh \
    --instance-id $INSTANCE_ID \

スクリーンショット 2025-08-31 1.29.42
無事接続できましたね!

おわりに

今回は、EC2 Instance Connect Endpointを使って、EC2への接続環境をAWS CDKで構築する方法をご紹介しました。キーペアやEC2インスタンスプロファイルが不要で簡単にEC2に接続できる環境を構築できるのは魅力的だと思いました。

この記事が少しでも皆様の参考になれば幸いです。

参考資料

https://dev.classmethod.jp/articles/ec2-instance-connect-endpoint-private-access/
https://dev.classmethod.jp/articles/update-ec2-instance-connect-endpoint/
https://dev.classmethod.jp/articles/compare-eic-endpoint-and-session-manager/
https://dev.classmethod.jp/articles/connecting-to-ec2-instance-built-with-aws-cdk-using-ec2-instance-connect/
https://qiita.com/utsunomiya_ff/items/02890654faa01b5a34f1

この記事をシェアする

facebookのロゴhatenaのロゴtwitterのロゴ

© Classmethod, Inc. All rights reserved.