はじめに
Auto Scalingのテスト環境の構築をAWS CDKの勉強も兼ねて行ってみました。
EC2にCPUの負荷を与えて、想定通りにEC2がスケールアウトすることを確認したかったため、作業内容を備忘録のつもりでまとめます。
環境
- OS: macOS Cataline 10.15.5
- VSCode: 1.46.0
- Node.js: v14.4.0
- npm: 6.14.5
- TypeScript: 3.9.5
- CDK: 1.45.0
AWS CDKのインストール
公式の情報を参考にインストールします。
$ npm install -g aws-cdk
インストールできているか、念のため確認します。
$ cdk --version
1.45.0 (build 0cfab15)
プロジェクトの作成
CDKのプロジェクトを公式に沿って作成します。
$ mkdir test-asg
$ cd test-asg
$ cdk init app --language=typescript
コードの実装
必要なCDKのモジュールをインストールします。
$ npm install @aws-cdk/aws-autoscaling @aws-cdk/aws-ec2 @aws-cdk/aws-elasticloadbalancingv2
なお、自分が検証した際にはこのエラーに遭遇したため、package.json
を編集して@aws-cdk/core
と@aws-cdk/assert
のバージョンを合わせます。
{
: (省略)
"devDependencies": {
// 1.45.0 -> 1.46.0
"@aws-cdk/assert": "^1.46.0",
"@types/jest": "^25.2.1",
"@types/node": "10.17.5",
"jest": "^25.5.0",
"ts-jest": "^25.3.1",
"aws-cdk": "1.45.0",
"ts-node": "^8.1.0",
"typescript": "~3.7.2"
},
"dependencies": {
"@aws-cdk/aws-autoscaling": "^1.46.0",
"@aws-cdk/aws-ec2": "^1.46.0",
"@aws-cdk/aws-elasticloadbalancingv2": "^1.46.0",
// 1.45.0 -> 1.46.0
"@aws-cdk/core": "^1.46.0",
"source-map-support": "^0.5.16"
}
}
node_modules
ディレクトリを削除し、再度インストールします。これでエラーが解消され、ビルドも可能になりました。(CDKのバージョンを最初から上げていれば、このようなことはしなくても良かったかもしれません…)
$ rm -rf node_modules
$ npm install
lib/test-asg-stack.ts
を編集します。以下の点に留意して作成しました。
- 予めAWSのコンソールで
TestAsgEnv
という名前のキーペアを作成しておき、SSHでログインできるようにする。 - EC2起動時に
sudo yum update -y
が実行されるようにする。 - CPU使用率が50%でスケールアウトするようにする。
- スタック作成完了時にALBのDNS名が表示されるようにする。
import * as cdk from '@aws-cdk/core';
import * as autoscaling from '@aws-cdk/aws-autoscaling';
import * as ec2 from '@aws-cdk/aws-ec2';
import * as elbv2 from '@aws-cdk/aws-elasticloadbalancingv2';
export class TestAsgStack extends cdk.Stack {
constructor(scope: cdk.Construct, id: string, props?: cdk.StackProps) {
super(scope, id, props);
const cidr = '10.0.0.0/16';
const vpc = new ec2.Vpc(
this,
'test-asg-vpc', {
cidr,
natGateways: 1,
subnetConfiguration: [
{
cidrMask: 18,
name: 'public',
subnetType: ec2.SubnetType.PUBLIC,
},
{
cidrMask: 18,
name: 'private',
subnetType: ec2.SubnetType.PRIVATE,
},
],
}
);
const securityGroup = new ec2.SecurityGroup(
this,
'test-asg-security-group',
{
vpc,
securityGroupName: 'test-asg-security-group',
allowAllOutbound: true
}
);
securityGroup.addIngressRule(ec2.Peer.anyIpv4(), ec2.Port.tcp(22), 'SSH from anywhere');
securityGroup.addEgressRule(ec2.Peer.anyIpv4(), ec2.Port.allTraffic());
const userData = ec2.UserData.forLinux();
userData.addCommands('sudo yum update -y');
const alb = new elbv2.ApplicationLoadBalancer(this, 'TestAsgALB', {
vpc,
vpcSubnets: { subnetType: ec2.SubnetType.PUBLIC },
internetFacing: true,
loadBalancerName: 'test-asg-alb'
});
const asg = new autoscaling.AutoScalingGroup(this, 'TestAutoScalingGroup', {
vpc,
instanceType: ec2.InstanceType.of(ec2.InstanceClass.T2, ec2.InstanceSize.MICRO),
machineImage: new ec2.AmazonLinuxImage(),
desiredCapacity: 1,
maxCapacity: 3,
keyName: 'TestAsgEnv',
associatePublicIpAddress: true,
vpcSubnets: { subnetType: ec2.SubnetType.PUBLIC },
userData,
});
asg.addSecurityGroup(securityGroup);
asg.scaleOnCpuUtilization('CPU50Percent', {
targetUtilizationPercent: 50
});
const listener = alb.addListener('Listener', {
port: 80
});
listener.addTargets('Target', {
targets: [asg],
port: 80
});
new cdk.CfnOutput(this, 'Application LoadBalancer DNS', { value: alb.loadBalancerDnsName });
}
}
デプロイ
アプリケーションをビルドします。
$ npm run build
AWS CloudFormationのスタックをデプロイします。デプロイが完了するまで待ちます。
$ cdk deploy
Auto Scalingのテスト
CloudWatch Alarmに2つ登録されていました。もっと細かく設定すれば、条件をカスタマイズできると思います。
Chaos EngineeringのツールであるGremlinでEC2にCPUの負荷(CPU 51%の攻撃を300秒間実行)を与えてみたところ、無事にスケールアウトできました。
(結果のスクリーンショットを取るのを忘れていました… 既に環境は削除済みで、GremlinのFreeアカウントの制約でターゲット数が限られているようなので事象の再現は控えます…)
おわりに
CloudFormationのyamlファイルよりも、コードで記述できるため作りやすかったですね。
ただ、思いの外「これだ!」といえる情報を見つけられなかったので、公式の仕様のドキュメントを眺めてパラメータを推測しながら、そしてIDEの補完を駆使してゴリ押ししながら作成しました。
EKSの環境もCDKで作れるので、こういうものにもチャレンジしていきたいです。
参考
AWS CDKでAutoScaling環境を作成(Single Stack / Nested Stack)
Deploy your Auto-Scaling Stack with AWS-CDK
Gremlinを使ってCPU負荷を注入する