🌱

SSMでアクセス可能なEC2をCDKで作成する

2022/10/04に公開約5,300字

はじめに

EC2を手軽に作成したいなと思うことはありませんか?
また、「わざわざSSHのキーペアを作って/使って・・・」となるのは煩わしいと思いませんか?

そんな時、お手軽にEC2インスタンスを作成して、接続できる方法があります!
それは、CDKでEC2インスタンスを作成して、SSMで接続する方法です。
この方法だと、コマンド一つでEC2に必要なものを用意しつつ、
不要になったら関連するリソースを全て削除できます。

そのため、長期的に利用するというよりは、ちょっとしたお試し環境とかに最適だと思います。

環境・料金

環境

  • macOS: 12.6
  • Node.js: 16.15
  • AWS CDK: 2.44.0

料金

今回利用するサービスは、EC2のみです。
そのため、EC2を起動している間のみ料金がかかります。

準備

ローカルからEC2インスタンスに接続したい場合のみ、このページより、
プラグインをインストールする必要があります。

ローカルから接続しなくてもブラウザからEC2に接続はできるので、
「ブラウザから接続するよ」という場合は事前の準備は不要です。

プログラム

GitHub

プログラムはGitHub: zenn-ec2-ssmにて公開してあります。
実際に動かしたい場合はcloneして実行してみてください。

ソースコード

今回は単一のStackで完結しているので、コードを載せます。
以下がSSMで接続できるEC2を作成するコードです。
そのほかのコードは、GitHubの方を参照してください。

import {
  App,
  Duration,
  Stack,
  StackProps,
  aws_ec2,
  aws_iam,
} from 'aws-cdk-lib';

export interface IEc2Ssm {
  applicationSuffix: string
  vpcId: `vpc-${string}`
}

export class Ec2SsmStack extends Stack {
  constructor(scope: App, id: string, params: IEc2Ssm, props?: StackProps) {
    super(scope, id, props);

    const vpc = aws_ec2.Vpc.fromLookup(this, "existing-vpc", {
      vpcId: params.vpcId
    })

    const securityGroup = new aws_ec2.SecurityGroup(this, `security-group`, {
      vpc: vpc,
      securityGroupName: `ssm-security-group`,
      allowAllOutbound: true,
    })

    /** instance role  */
    const role = new aws_iam.Role(this, `instance-role`, {
      roleName: `ssm-ec2-instance-role-${params.applicationSuffix}`,
      assumedBy: new aws_iam.ServicePrincipal('ec2.amazonaws.com'),
      managedPolicies: [
        aws_iam.ManagedPolicy.fromManagedPolicyArn(this, "AmazonEC2ContainerServiceforEC2Role", "arn:aws:iam::aws:policy/service-role/AmazonEC2ContainerServiceforEC2Role"),
        /** Add managed policy to use SSM */
        aws_iam.ManagedPolicy.fromManagedPolicyArn(this, "AmazonEC2RoleforSSM", "arn:aws:iam::aws:policy/service-role/AmazonEC2RoleforSSM")
      ]
    })
    new aws_iam.CfnInstanceProfile(this, `instance-profile`, {
      instanceProfileName: `ssm-ec2-instance-profile-${params.applicationSuffix}`,
      roles: [role.roleName]
    })
    /** 実行環境としてのEC2 */
    const machineImage = aws_ec2.MachineImage.latestAmazonLinux({
      generation: aws_ec2.AmazonLinuxGeneration.AMAZON_LINUX_2,
      edition: aws_ec2.AmazonLinuxEdition.STANDARD,
      kernel: aws_ec2.AmazonLinuxKernel.KERNEL5_X,
      virtualization: aws_ec2.AmazonLinuxVirt.HVM,
      storage: aws_ec2.AmazonLinuxStorage.GENERAL_PURPOSE,
      cpuType: aws_ec2.AmazonLinuxCpuType.X86_64,
    });
    new aws_ec2.Instance(this, "ssm-instance", {
      instanceType: new aws_ec2.InstanceType("t3.micro"),
      instanceName: `ssm-example-${params.applicationSuffix}`,
      vpc: vpc,
      machineImage,
      initOptions: {
        configSets: ["default"],
        timeout: Duration.minutes(10)
      },
      init: aws_ec2.CloudFormationInit.fromConfigSets({
        configSets: {
          default: ["yumInstall"]
        },
        configs: {
          yumInstall: new aws_ec2.InitConfig([
            aws_ec2.InitPackage.yum("git"),
            aws_ec2.InitPackage.yum("jq"),
            aws_ec2.InitPackage.yum("docker"),
          ]),
        }
      }),
      role,
      securityGroup,
    })
  }
}

ポイントは、EC2に付与するIAMロールにSSMを実行できるポリシーを付与している点です。
この権限があることによってEC2にSSMでアクセスが可能になっています。

aws_iam.ManagedPolicy.fromManagedPolicyArn(this, "AmazonEC2RoleforSSM", "arn:aws:iam::aws:policy/service-role/AmazonEC2RoleforSSM")

また、独自のパッケージをインストールしたりもできます。
今回は、git, jq, dockerをインストールしています。
ただ、最初から多く追加すると予期せず失敗したり、
起動までの時間が長くなったりするので注意が必要です。

デプロイと動作確認

デプロイ

パラメータとしてvpcIdは必須なのでそれを付与した形で、$ cdk deployを実行してください。
詳しい方法はGitHubのREADMEに書いてあるので、そちらを参照してください。

動作確認(ブラウザ)

ブラウザからEC2に接続する場合は、
EC2のインスタンス一覧より接続したいインスタンスを選択し、「接続」を押下します。

「セッションマネージャー」タブを選択して、「接続」を押下します。

すると、新しいタブが開いてコンソール画面を見ることができます。

あとは、通常のコンソールと遜色ない操作ができます。

動作確認(ローカル)

起動したEC2のインスタンスIDをコピーしておき、以下のコマンドでログインできます。

$ EC2_INSTANCE_ID={...}
$ aws ssm start-session --target $EC2_INSTANCE_ID

tips: ログイン後にec2-userを使いたい

SSMを利用してEC2にログインすると、ssm-userになります。
このssm-userだと、ログイン場所が/usr/binだったり、
コマンド実行のたびにsudoが必要だったりと、
SSHで接続した時に比べて違和感が多くなるのが辛いところでした。

その際は、ここに書いてあるように

$ sudo su --login ec2-user

として、ec2-userでログインし直せば解決します!

ブラウザから実行した例です。

おわりに

CDKとSSMを利用して、お手軽にEC2を立てれるようになりました。
ちょっとしたお試し環境とかにはもってこいだと思うので、
誰かの参考になれば幸いです!

参考

GitHubで編集を提案

Discussion

ログインするとコメントできます