
AWS InstanseConnect のサポートOSにRHELが追加されたので使ってみた。
はじめに
こんにちは、SHIFTのAWSエンジニアの佐藤です。
さて、2023年12月より、Amazon EC2 Instance Connect で RHEL、CentOS、macOSのサポートが開始されました。
参考:https://aws.amazon.com/jp/about-aws/whats-new/2023/12/amazon-ec2-instance-connect-rhel-centos-macos/
これまではAmazonLinux2とUbuntuの特定バージョンでしかサポートされておりませんでしたが、今回のアップデートで、RHEL・CentOS・MacOSでも、InstanceConnectのパッケージをインストールすればセキュアにサーバーにログインが出来るようになりました。
私が案件でよく利用するRHELでのサポートが追加されたということで、InstanceConnectでのRHELサーバーへのアクセスを試してみたく思います。
構成イメージ
今回構築する環境は下記のとおりです。
PrivateSubnetに配置したEC2へAWSコンソール上からの操作でInstanceConnectでのSSH接続を行います。
また、InstanceConnectのパッケージをAWSネットワーク上からhttpsコマンドでダウンロードしてインストールしたいので、 EC2からインターネットに出られるようなネットワーク構成を作成します。

通信要件
今回の構成で必要な通信設定は下記のとおりです。

1.ネットワーク構築
ネットワークリソースについては、目新しいところも少ないのでCDKでサクッと作ってしまいます。
使用するコードは下記です。
import * as cdk from 'aws-cdk-lib';
import { Construct } from 'constructs';
import { aws_ec2 as ec2 } from 'aws-cdk-lib';
export class VpcIcStack extends cdk.Stack {
constructor(scope: Construct, id: string, props?: cdk.StackProps) {
super(scope, id, props);
// VPC
const vpc = new ec2.Vpc(this, 'MyVpc', {
ipAddresses: ec2.IpAddresses.cidr('10.0.0.0/16'),
vpcName: 'ic-vpc',
subnetConfiguration: []
});
// Internet Gateway
const Igw = new ec2.CfnInternetGateway(this, 'Igw', {
tags: [ { key: 'Name', value: 'ic-igw' } ]
});
const igwAttach = new ec2.CfnVPCGatewayAttachment(this, 'IgwAttach', {
vpcId: vpc.vpcId,
internetGatewayId: Igw.ref
});
// Public Subnet
const PubSubnet1 = new ec2.Subnet(this, 'PublicSubnet1a', {
availabilityZone: 'ap-northeast-1a',
vpcId: vpc.vpcId,
cidrBlock: '10.0.0.0/20',
});
cdk.Tags.of(PubSubnet1).add('Name', 'ic-pubsubnet1a');
PubSubnet1.addDefaultInternetRoute(Igw.ref, igwAttach);
// NAT Gatgateway
const EIP1 = new ec2.CfnEIP(this, 'EIP1', {});
cdk.Tags.of(EIP1).add('Name', 'ec-eip-nat-a');
const Ngw1 = new ec2.CfnNatGateway(this, 'Ngw1', {
allocationId: EIP1.attrAllocationId,
subnetId: PubSubnet1.subnetId,
tags: [ { key: 'Name', value: 'ic-natgw-1a' } ]
});
// Private Subnet
const PriSubnet1 = new ec2.Subnet(this, 'PrivateSubnet1a', {
availabilityZone: 'ap-northeast-1a',
vpcId: vpc.vpcId,
cidrBlock: '10.0.16.0/20',
});
cdk.Tags.of(PriSubnet1).add('Name', 'ic-prisubnet1a');
PriSubnet1.addDefaultNatRoute(Ngw1.ref);
// SG
const SecurityGroup1 = new ec2.SecurityGroup(this, 'SecurityGroup1', {
vpc: vpc,
description: 'Instance Connect SG',
securityGroupName: `ic-ec2-sg`,
allowAllOutbound: true
});
cdk.Tags.of(SecurityGroup1).add('Name', 'ic-ec2-sg');
const SecurityGroup2 = new ec2.SecurityGroup(this, 'SecurityGroup2', {
vpc: vpc,
description: 'Instance Connect Endpoint SG',
securityGroupName: `ic-ep-sg`,
allowAllOutbound: true
});
cdk.Tags.of(SecurityGroup2).add('Name', 'ic-ep-sg');
SecurityGroup1.addIngressRule(SecurityGroup2, ec2.Port.tcp(22), 'InstanceConnect to EC2');
const Endpoint1 = new ec2.CfnInstanceConnectEndpoint(this, 'Endpoint1', {
subnetId: PriSubnet1.subnetId,
preserveClientIp: false,
securityGroupIds: [SecurityGroup2.securityGroupId],
tags: [{
key: 'Name',
value: 'ic-endpoint',
}],
});
}
}
作成されたVPC

SecurityGroup
①EC2用

※InstanceConnectEndpointからのSSH(22番ポート)通信をSecurityGroup指定で許可する。

※InstanceConnectパッケージのインストール用に外向きの通信は許可しておく
②InstanceConnectEndpoint用

※インバウンドルールは不要。

※画像の設定はフルで許可していますが、EC2へのSSH(22番ポート)通信が許可されていればOK。
Endpoint(InstanceConnect用)

※InstanceConnect用のエンドポイントは、エンドポイントタイプが「EC2 Instance Connect Endpoint」と特殊なタイプになっている。
2.EC2構築
作成したプライベートサブネット上にEC2でRHELサーバーを構築します。
OSは個人的に使い慣れているrhel8系を使用します。
※InstanceConnectはRHELですと、8と9のみが対応しています。

ネットワーク設定は作成したVPCとPrivateSubnetを選択し、SecurityGroupも作成したものを使用します。

最後に、[高度な詳細設定]より、ユーザーデータの設定にInstanceConnectパッケージのインストールコマンドを記載します。
RHELを含む、AmazonLinux2及びUbuntsu18以降以外の対応OSの場合は、InstanceConnect利用に専用パッケージのインストールが必須ですが、
InstanceConnectのパッケージインストールのために別の経路を用意してEC2にSSH接続をするのは本末転倒ですので、
ユーザーデータを使用してインストールします。

ユーザーデータ入力コマンド
#!/bin/bash
mkdir /tmp/ec2-instance-connect
curl https://amazon-ec2-instance-connect-us-west-2.s3.us-west-2.amazonaws.com/latest/linux_amd64/ec2-instance-connect.rhel8.rpm -o /tmp/ec2-instance-connect/ec2-instance-connect.rpm
curl https://amazon-ec2-instance-connect-us-west-2.s3.us-west-2.amazonaws.com/latest/linux_amd64/ec2-instance-connect-selinux.noarch.rpm -o /tmp/ec2-instance-connect/ec2-instance-connect-selinux.rpm
sudo yum install -y /tmp/ec2-instance-connect/ec2-instance-connect.rpm /tmp/ec2-instance-connect/ec2-instance-connect-selinux.rpm
※インストールコマンドはAWS公式ドキュメントのものをそのまま使用しています。
以上の設定でインスタンスを起動します。

3.InstanceConnectでの接続
環境の構築が完了しましたので、早速AWSコンソールからEC2インスタンスに接続してみます。
作成したEC2を選択し、[接続]ボタンを押して

ページ遷移するので、[EC2 Instance Connect]タブに切り替えて
[EC2 Instance Connect エンドポイントを使用して接続する]を選択し、
[接続]ボタンを押すと

サーバーにログイン出来ました!

以上で、InstanceConnectを使用したRHELサーバーへの接続は完了です。
4. ふり返り
今までInstanceConnectを利用する機会が無く、今回初めて使用してみましたが、かなりお手軽に使用出来ました。
InstanceConnectと似た機能でSystemsManagerのSessionManager機能があり、そちらは過去の案件で使用する機会がありましたが、個人的な使用感としては、AWSコンソールからの接続に関してはほぼ変わらないように思います。
むしろ設定面ではSessionManagerと比較し、IAMロール(インスタンスプロファイル)が不要なため設定するリソースが少なく若干楽でした。
対象OSにRHELやCentOSが追加された今、EC2への接続にSessionManagerではなく、InstanceConnectを採用するという機会が増えていくかもしれないなと感じました。
執筆者プロフィール:佐藤 和也
AWSエンジニアです。AWSを扱うクラウドシステムの設計~構築・試験ときどき運用までやってきました。
最近はCDKでサクッと構築をこなそうと勉強中。
認定資格もちょくちょく...いつかは12冠に...。
お問合せはお気軽に
https://service.shiftinc.jp/contact/
SHIFTについて(コーポレートサイト)
https://www.shiftinc.jp/
SHIFTのサービスについて(サービスサイト)
https://service.shiftinc.jp/
SHIFTの導入事例
https://service.shiftinc.jp/case/
お役立ち資料はこちら
https://service.shiftinc.jp/resources/
SHIFTの採用情報はこちら
https://recruit.shiftinc.jp/career/
PHOTO:UnsplashのMarkus Spiske