小ネタです。
CDK の AutoScalingGroup
は、起動テンプレートに対応しておらず、現時点 (2021/12) では起動設定を利用します。
ECS の Capacity Providers を CDK で設定する場合、以下のように AutoScalingGroup
を利用するので、普通にやると起動設定が利用されるわけですね。
private addCapacity(capacity: number) {
// 起動設定で ASG が作成される
const autoScalingGroup = new autoscaling.AutoScalingGroup(this, 'GeneralCapacityASG', {
vpc: this.cluster.vpc,
instanceType: ec2.InstanceType.of(ec2.InstanceClass.M5, ec2.InstanceSize.LARGE),
machineImage: ecs.EcsOptimizedImage.amazonLinux2(),
minCapacity: 0,
maxCapacity: capacity,
});
const capacityProvider = new ecs.AsgCapacityProvider(this, 'GeneralCapacityProvider', {
autoScalingGroup,
});
this.cluster.addAsgCapacityProvider(capacityProvider);
}
ここで、せっかくなので起動テンプレートを利用して、一つの Capacity Provider で オンデマンドとスポットインスタンスを混ぜたり、複数のインスタンスタイプを混ぜたりしてみたいと思います。
元ネタは、以下のソースの合わせ技です。
https://github.com/aws/aws-cdk/issues/6734
https://github.com/aws-containers/ecsdemo-platform/blob/master/cdk/app.py
private addMixedCapacity(capacity: number) {
const instanceTypes = [
ec2.InstanceType.of(ec2.InstanceClass.M6I, ec2.InstanceSize.LARGE),
ec2.InstanceType.of(ec2.InstanceClass.M5, ec2.InstanceSize.LARGE),
ec2.InstanceType.of(ec2.InstanceClass.M5A, ec2.InstanceSize.LARGE),
ec2.InstanceType.of(ec2.InstanceClass.M4, ec2.InstanceSize.LARGE),
];
// ECS のコンテナインスタンスに必要異なロール、 UserData の設定
const launchTemplateRole = new iam.Role(this, 'LaunchTemplateRole', {
assumedBy: new iam.ServicePrincipal('ec2.amazonaws.com'),
managedPolicies: [
iam.ManagedPolicy.fromAwsManagedPolicyName('service-role/AmazonEC2ContainerServiceforEC2Role'),
iam.ManagedPolicy.fromAwsManagedPolicyName('AmazonSSMManagedInstanceCore'),
]
});
const launchTemplateUserData = ec2.UserData.forLinux();
launchTemplateUserData.addCommands(`echo ECS_CLUSTER=${this.node.tryGetContext('clusterName')} >> /etc/ecs/ecs.config`);
// 起動テンプレートの作成
const launchTemplate = new ec2.LaunchTemplate(this, 'LaunchTemplate', {
machineImage: ecs.EcsOptimizedImage.amazonLinux2(),
role: launchTemplateRole,
userData: launchTemplateUserData,
});
// AutoScaling Group の作成
const autoScalingGroup = new autoscaling.AutoScalingGroup(this, 'MixedCapacityASG', {
vpc: this.cluster.vpc,
instanceType: instanceTypes[0],
machineImage: ecs.EcsOptimizedImage.amazonLinux2(),
minCapacity: 0,
maxCapacity: capacity,
});
// 下位レイヤーの CloudFormation 設定を取得し、起動設定を起動テンプレートに置き換える
const cfnAsg = autoScalingGroup.node.defaultChild as autoscaling.CfnAutoScalingGroup;
autoScalingGroup.node.tryRemoveChild('LaunchConfig');
cfnAsg.launchConfigurationName = undefined;
const cfnLaunchTemplate = launchTemplate.node.defaultChild as ec2.CfnLaunchTemplate;
cfnAsg.mixedInstancesPolicy = {
instancesDistribution: {
onDemandBaseCapacity: 1,
onDemandPercentageAboveBaseCapacity: 0,
spotAllocationStrategy: 'capacity-optimized',
},
launchTemplate: {
launchTemplateSpecification: {
launchTemplateId: cfnLaunchTemplate.ref,
version: cfnLaunchTemplate.attrLatestVersionNumber,
},
overrides: instanceTypes.map(instanceType => {
return {
instanceType: instanceType.toString()
}
}),
},
};
const capacityProvider = new ecs.AsgCapacityProvider(this, 'MixedCapacityProvider', {
autoScalingGroup
});
this.cluster.addAsgCapacityProvider(capacityProvider);
}
以上、ちょっとした小ネタでした〜