見出し画像

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:UnsplashMarkus Spiske