SSMでアクセス可能なEC2をCDKで作成する
はじめに
EC2を手軽に作成したいなと思うことはありませんか?
また、「わざわざSSHのキーペアを作って/使って…」となるのは煩わしくないですか?
そんな時、お手軽にEC2インスタンスを作成して、接続できる方法があります!
それは、CDKでEC2インスタンスを作成して、SSMで接続する方法です。
この方法だと、コマンド1つで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
ec2-user
を使いたい
tips: ログイン後にSSMを利用してEC2にログインすると、ssm-user
になります。
このssm-user
だと、ログイン場所が/usr/bin
だったり、コマンド実行のたびにsudo
が必要だったりするところが、SSHで接続した時に比べて違和感があるところでした。
その際は、ここに書いてあるように、以下のコマンドを実行してec2-user
としてログインし直せば解決します!
$ sudo su --login ec2-user
ブラウザから実行した例です。
おわりに
CDKとSSMを利用して、お手軽にEC2を立てられるようになりました。ちょっとしたお試し環境とかにはもってこいだと思うので、誰かの参考になれば幸いです!
参考
Discussion
参考にさせていただきました、ありがとうございます。
どうやら略称には、機能拡充をする前(“Simple” だったころ)の旧名称を使っているからだそうです。
AWS Systems Manager とは? - AWS Systems Manager
そうなんですね!ありがとうございます!!
すっきりしました!!