+86 13541016684Mon. - Fri. 10:00-22:00

使用AWS CDK创建用于自动扩容的ECS服务的资源

使用AWS CDK创建用于自动扩容的ECS服务的资源

使用AWS CDK创建用于自动扩容的ECS服务的资源

AWS CDK(云开发套件)是一种 IaC 工具,可让您通过编写代码来配置基础设施。 使用您最喜欢的编程语言定义您的基础设施并自动生成 CloudFormation 模板。 抽象层次高,因此代码量少。

CDK开发环境Permalink 构建

  • 使用 nvm 安装 Node.js
    $ curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.3/install.sh | bash
    $ . ~/.nvm/nvm.sh
    $ nvm install 16
    
  • cdk 命令行工具 安装 AWS CDK 工具包
    $ npm install -g aws-cdk
    
  • 安装Python的CDK包
    $ pip install aws-cdk-lib
    
  • 将AWS帐户和区域设置为环境变量
    $ echo "export AWS_REGION=$(curl -s 169.254.169.254/latest/dynamic/instance-identity/document | jq -r .region)" >> ~/.bashrc
    $ echo "export AWS_ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text)" >> ~/.bashrc
    

AWS CDK Toolkit (CLI) 命令永久链接

  • 创建CDK项目
    $ cdk init app --language python
    
  • 从 CDK 应用程序生成 CloudFormation 模板
    $ cdk synth
    
  • 部署引导堆栈。 必须在 CDK 应用程序首次部署到 AWS 环境(AWS 账户和区域)之前运行。
    $ cdk bootstrap
    
  • 部署 CDK 应用程序
    $ cdk deploy
    

创建资源Permalink 使用CDK

使用 EC2 启动类型自动扩展您的 ECS 服务。

首先,创建 ECS 集群、Auto Scaling 组和容量提供程序。 它将如下。

import os

import boto3
from aws_cdk import (
    App,
    Tags,
    Stack,
    Duration,
    Environment,
    aws_ecs as ecs,
    aws_ec2 as ec2,
    aws_ecr as ecr,
    aws_iam as iam,
    aws_autoscaling as autoscaling,
    aws_cloudwatch as cloudwatch,
    aws_applicationautoscaling as appscaling
)
from constructs import Construct


class ECSAutoScaling(Stack):
    def __init__(self, scope: Construct, construct_id: str, **kwargs):
        super().__init__(scope, construct_id, **kwargs)

        # 既存のVPC、サブネット、セキュリティグループ、IAMロールを使用
        vpc = ec2.Vpc.from_lookup(self, 'vpc', vpc_id='vpc-xxx')
        security_group = ec2.SecurityGroup.from_security_group_id(
            self, 'SG', 'sg-xxx')
        subnet_ids = [
            'subnet-xxx',
            'subnet-yyy',
        ]
        subnets = [ec2.Subnet.from_subnet_id(
            self, f'subnet{idx}', sid) for idx, sid in enumerate(subnet_ids)]
        asg_role = iam.Role.from_role_name(
            self, 'AsgRole', 'role_name')
        task_role = iam.Role.from_role_name(
            self, 'TaskRole', 'role_name')

        # ECSクラスターの作成
        cluster = ecs.Cluster(
            self, 'Cluster',
            cluster_name='cluster_name',
            vpc=vpc)

        # AutoScalingGroupの作成
        asg = autoscaling.AutoScalingGroup(
            self, "ASG",
            auto_scaling_group_name='auto_scaling_group_name',
            vpc=vpc,
            role=asg_role,
            vpc_subnets=ec2.SubnetSelection(subnets=subnets),
            instance_type=ec2.InstanceType("c6g.16xlarge"),
            machine_image=ecs.EcsOptimizedImage.amazon_linux2(
                ecs.AmiHardwareType.ARM),
            min_capacity=0,
            max_capacity=5,
            desired_capacity=0,
            security_group=security_group
        )
        # キャパシティープロバイダーの作成とクラスターへの関連付け
        capacity_provider = ecs.AsgCapacityProvider(
            self, 'AsgCapacityProvider',
            capacity_provider_name='capacity_provider_name',
            auto_scaling_group=asg
        )
        cluster.add_asg_capacity_provider(capacity_provider)

创建任务定义和服务。


# タスク定義の作成
task_def = ecs.Ec2TaskDefinition(
    self, "TaskDef",
    family='task_family_name',
    network_mode=ecs.NetworkMode.BRIDGE,
    task_role=task_role,
    execution_role=task_role,
)
# 既存のECRリポジトリを使用
repository = ecr.Repository.from_repository_name(
    self, 'Repository', 'repository_name')
task_def.add_container(
    'Container',
    container_name='container_name',
    image=ecs.ContainerImage.from_ecr_repository(
        repository, tag='latest'),
    memory_limit_mib=1024,
    logging=ecs.LogDrivers.aws_logs(stream_prefix='cdk')
)

# サービスのキャパシティープロバイダー戦略
capacity_provider_strategy = ecs.CapacityProviderStrategy(
    capacity_provider=capacity_provider.capacity_provider_name,
    weight=1,
    base=0
)
# ECSサービスの作成
ecs_service = ecs.Ec2Service(
    self, 'Service',
    service_name='service_name',
    cluster=cluster,
    task_definition=task_def,
    desired_count=0,
    capacity_provider_strategies=[capacity_provider_strategy]
)

创建 CloudWatch 指标和警报,逐步制定扩展策略。

指标是在您使用 boto3 或 AWS CLI 发布第一个数据点后创建的。

cw = boto3.client('cloudwatch', region_name=os.getenv('AWS_REGION'))
cw.put_metric_data(
    Namespace='Namespace',
    MetricData=[{
        'MetricName': 'MetricName',
        'Value': 0,
        'Unit': 'Count',
    }]
)

Metric类指的是度量。 它本身并不创建指标。

这个类不代表资源,因此不是一个构造。 相反,指标是一种抽象,可以轻松指定在警报和图表中使用的指标。

参考: https://docs.aws.amazon.com/cdk/api/v2/python/aws_cdk.aws_cloudwatch/Metric.html

# カスタムメトリクスの参照
metric = cloudwatch.Metric(
    namespace='namespace',
    metric_name='metric_name',
    period=Duration.minutes(1),
    unit=cloudwatch.Unit.COUNT
)
# アラームを作成
alarm = metric.create_alarm(
    self, 'Alarm',
    alarm_name='alarm_name',
    evaluation_periods=1,
    threshold=0,
)

# ECSサービスのタスクスケーリングポリシーの追加
scalable_target = ecs_service.auto_scale_task_count(
    max_capacity=5,
    min_capacity=0
)
scaling_steps = [
    appscaling.ScalingInterval(change=0, upper=0),
    appscaling.ScalingInterval(change=1, lower=1, upper=10),
    appscaling.ScalingInterval(change=2, lower=10, upper=20),
    appscaling.ScalingInterval(change=5, lower=20),
]
scalable_target.scale_on_metric(
    'AutoScalingPolicy',
    metric=alarm.metric,
    scaling_steps=scaling_steps,
    adjustment_type=appscaling.AdjustmentType.EXACT_CAPACITY,
    cooldown=Duration.minutes(3)
)
app: App = App()
stack = ECSAutoScaling(
    app, "ECSAutoScaling",
    env=Environment(
        account=os.getenv('AWS_ACCOUNT_ID'),
        region=os.getenv('AWS_REGION')
    )
)
# リソースのタグ付け
Tags.of(stack).add('key', 'value', include_resource_types=['AWS::ECS::TaskDefinition'])

app.synth()