Posted in: Aws云上云维
使用AWS CDK创建用于自动扩容的ECS服务的资源
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()