LoginSignup
3
1

More than 1 year has passed since last update.

Amazon Elastic Container Service (Amazon ECS) と AWS CDK で起動テンプレートを利用した Capacity Providers を設定する

Posted at

小ネタです。

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);
  }

以上、ちょっとした小ネタでした〜

3
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
1