自动伸缩与 CloudWatch:灵活应对负载变化
1. 伸缩概念引入
想象你正在组织一场生日派对,确定需要购买多少食物和饮料是一件困难的事情。因为你不确定会有多少人参加,也不清楚客人们的食量和饮水量。为了确保每位客人都不会挨饿或口渴,你需要多准备一些食物和饮料。
在云计算出现之前,规划 IT 基础设施的容量也面临类似的挑战。在为数据中心采购硬件时,我们需要根据未来的需求来购买硬件,但这些需求往往存在很多不确定性。为了避免资源短缺,我们不得不购买比实际需求更多或更快的硬件,这会导致不必要的开支。
而在 AWS 上,你可以按需使用服务,按需伸缩。你可以从一个 EC2 实例扩展到数千个实例,存储容量也可以从千兆字节增长到拍字节。这种按需伸缩的能力被 AWS 称为弹性。
公共云提供商(如 AWS)可以在短时间内提供所需的容量。例如,如果你突然需要 100 个额外的虚拟机,AWS 可以在几分钟内为你提供。这使得你能够应对典型的流量模式,如白天和晚上、工作日和周末、圣诞节前后的流量差异。
2. 动态 EC2 实例池管理
在 AWS 上,你可以使用自动伸缩组(ASG)和伸缩策略来调整虚拟机的数量。自动伸缩是 EC2 服务的一部分,它可以帮助你根据系统的当前负载来调整所需的 EC2 实例数量。
要实现应用程序的水平伸缩(即根据当前工作负载增加或减少虚拟机的数量),需要满足两个先决条件:
- EC2 实例必须是无状态的 :你可以通过使用 RDS(SQL 数据库)、DynamoDB(NoSQL 数据库)、EFS(网络文件系统)或 S3(对象存储)等服务来存储数据,而不是将数据存储在仅单个 EC2 实例可用的磁盘(实例存储或 EBS)上。
- 需要一个动态 EC2 实例池的入口点 :以便将工作负载分配到多个 EC2 实例上。EC2 实例可以通过负载均衡器进行同步解耦,也可以通过队列进行异步解耦。
2.1 自动伸缩组的组成
自动伸缩由三个部分组成:
1. 启动配置 :定义虚拟机的大小、镜像和配置。
2. 自动伸缩组 :根据启动配置指定需要运行的虚拟机数量。
3. 伸缩计划 :根据计划或动态调整自动伸缩组中所需的 EC2 实例数量。
因为自动伸缩组需要启动配置,所以在创建自动伸缩组之前,你需要先创建一个启动配置。如果你使用模板,这个依赖关系将由 CloudFormation 自动解决。
graph LR
classDef process fill:#E5F6FF,stroke:#73A6FF,stroke-width:2px
A(启动配置):::process --> B(自动伸缩组):::process
C(伸缩计划):::process --> B
B --> D(启动虚拟机):::process
B --> E(终止虚拟机):::process
2.2 启动配置参数
| 名称 | 描述 | 可能的值 |
|---|---|---|
| ImageId | 用于启动虚拟机的镜像 | 亚马逊机器镜像(AMI)的 ID |
| InstanceType | 新虚拟机的大小 | 实例类型(如 t2.micro) |
| UserData | 用于在启动时执行脚本的虚拟机用户数据 | Base64 编码的字符串 |
| KeyName | 用于通过 SSH 进行身份验证的密钥对 | EC2 密钥对的名称 |
| AssociatePublicIpAddress | 是否为虚拟机分配公共 IP 地址 | true 或 false |
| SecurityGroups | 附加到新虚拟机的安全组 | 安全组名称列表 |
| IamInstanceProfile | 附加到与 IAM 角色关联的 IAM 实例配置文件 | IAM 实例配置文件的名称或亚马逊资源名称(ARN,一个 ID) |
2.3 自动伸缩组参数
| 名称 | 描述 | 可能的值 |
|---|---|---|
| DesiredCapacity | 所需的健康虚拟机数量 | 整数 |
| MaxSize | 虚拟机的最大数量,即伸缩上限 | 整数 |
| MinSize | 虚拟机的最小数量,即伸缩下限 | 整数 |
| HealthCheckType | 自动伸缩组检查虚拟机健康状况的方式 | EC2(实例健康状况)或 ELB(由负载均衡器执行的实例健康检查) |
| HealthCheckGracePeriod | 新实例启动后暂停健康检查的时间段,以等待实例完全启动 | 秒数 |
| LaunchConfigurationName | 用于启动新虚拟机的启动配置的名称 | 启动配置的名称 |
| TargetGroupARNs | 负载均衡器的目标组,自动伸缩会自动将新实例注册到这些目标组 | 目标组 ARN 列表 |
| VPCZoneIdentifier | 用于启动 EC2 实例的子网列表 | VPC 的子网标识符列表 |
如果你需要对启动配置进行更改,例如更改实例类型、机器镜像(AMI)或安全组,需要按照以下步骤操作:
1. 创建一个新的启动配置。
2. 编辑自动伸缩组,并引用新的启动配置。
3. 删除旧的启动配置。
以下是一个使用 CloudFormation 模板设置动态 EC2 实例池的示例:
# [...]
LaunchConfiguration:
Type: 'AWS::AutoScaling::LaunchConfiguration'
Properties:
ImageId: 'ami-6057e21a'
InstanceMonitoring: false
InstanceType: 't2.micro'
SecurityGroups:
- webapp
KeyName: mykey
AssociatePublicIpAddress: true
UserData:
'Fn::Base64': !Sub |
#!/bin/bash -x
yum -y install httpd
AutoScalingGroup:
Type: 'AWS::AutoScaling::AutoScalingGroup'
Properties:
TargetGroupARNs:
- !Ref LoadBalancerTargetGroup
LaunchConfigurationName: !Ref LaunchConfiguration
MinSize: 2
MaxSize: 4
DesiredCapacity: 2
HealthCheckGracePeriod: 300
HealthCheckType: ELB
VPCZoneIdentifier:
- 'subnet-a55fafc'
- 'subnet-fa224c5a'
# [...]
3. 使用指标或计划触发伸缩
你可以手动更改自动伸缩组的所需容量,新实例将根据需要启动或终止。但为了提供可伸缩的基础设施,你需要使用伸缩策略自动调整自动伸缩组的所需容量。
有两种不同的方式可以更改虚拟机的数量:
- 定义计划 :根据重复的负载模式(如晚上减少虚拟机数量)增加或减少虚拟机的数量。
- 使用 CloudWatch 警报 :根据指标(如 CPU 使用率或负载均衡器上的请求数量)触发伸缩策略,以增加或减少虚拟机的数量。
3.1 基于计划的伸缩
在运营博客平台时,你可能会注意到以下负载模式:
- 一次性操作 :例如,晚上播放电视广告后,注册页面的请求会大幅增加。
- 重复操作 :许多人似乎在午餐时间(上午 11 点到下午 1 点)阅读文章。
你可以使用不同类型的计划操作来应对这些负载模式。
以下是一个一次性计划操作的示例,在 2018 年 1 月 1 日 12:00 UTC 增加 Web 服务器的数量:
OneTimeScheduledActionUp:
Type: 'AWS::AutoScaling::ScheduledAction'
Properties:
AutoScalingGroupName: !Ref AutoScalingGroup
DesiredCapacity: 4
StartTime: '2018-01-01T12:00:00Z'
你也可以使用 cron 语法来安排重复的伸缩操作。以下示例展示了如何使用两个计划操作在每天的工作时间(08:00 到 20:00 UTC)增加所需的容量:
RecurringScheduledActionUp:
Type: 'AWS::AutoScaling::ScheduledAction'
Properties:
AutoScalingGroupName: !Ref AutoScalingGroup
DesiredCapacity: 4
Recurrence: '0 8 * * *'
RecurringScheduledActionDown:
Type: 'AWS::AutoScaling::ScheduledAction'
Properties:
AutoScalingGroupName: !Ref AutoScalingGroup
DesiredCapacity: 2
Recurrence: '0 20 * * *'
cron 语法格式如下:
* * * * *
| | | | |
| | | | +- 星期几 (0 - 6) (0 表示星期日)
| | | +--- 月份 (1 - 12)
| | +----- 日期 (1 - 31)
| +------- 小时 (0 - 23)
+--------- 分钟 (0 - 59)
我们建议在基础设施的容量需求可预测时使用计划伸缩操作,例如仅在工作时间使用的内部系统或计划在特定时间进行的营销活动。
3.2 基于 CloudWatch 指标的伸缩
预测未来的流量是困难的,流量可能会超出已知模式而增加或减少。例如,如果博客平台上的一篇文章在社交媒体上被大量分享,你需要能够应对这种意外的负载变化并调整 EC2 实例的数量。
你可以使用 CloudWatch 警报和伸缩策略来根据当前工作负载调整 EC2 实例的数量。CloudWatch 可以帮助你监控 AWS 上的虚拟机和其他服务。通常,服务会将使用指标发布到 CloudWatch,帮助你评估可用容量。
有三种类型的伸缩策略:
- 步进伸缩 :支持更高级的伸缩,根据你设置的阈值超出的程度进行多次伸缩调整。
- 目标跟踪 :你只需定义一个目标(如 CPU 利用率为 70%),系统会相应地调整 EC2 实例的数量。
- 简单伸缩 :这是一种旧的选项,已被步进伸缩取代。
所有类型的伸缩策略都使用指标和警报到根据当前工作负载调整 EC2 实例的数量。虚拟机会不断将指标发布到 CloudWatch,CloudWatch 警报会监控其中一个指标,并在达到定义的阈值时触发伸缩操作。伸缩策略会增加或减少自动伸缩组的所需容量。
一个 EC2 实例默认会向 CloudWatch 发布几个指标,最重要的是 CPU、网络和磁盘利用率。目前没有虚拟机内存使用情况的指标。你可以使用这些指标在达到瓶颈时调整虚拟机的数量。例如,如果 CPU 达到满负荷,你可以添加 EC2 实例。
以下参数描述了一个 CloudWatch 指标:
- 命名空间 :定义指标的来源(如 AWS/EC2)。
- 维度 :定义指标的范围(如属于某个自动伸缩组的所有虚拟机)。
- 指标名称 :指标的唯一名称(如 CPUUtilization)。
CloudWatch 警报基于 CloudWatch 指标。以下是一个基于所有属于 ASG 的虚拟机的 CPU 利用率触发伸缩的 CloudWatch 警报的参数表:
| 上下文 | 名称 | 描述 | 可能的值 |
| — | — | — | — |
| 条件 | Statistic | 应用于指标的统计函数 | Average、Sum、Minimum、Maximum、SampleCount |
| 条件 | Period | 定义指标的基于时间的值切片 | 秒(60 的倍数) |
| 条件 | EvaluationPeriods | 检查警报时要评估的周期数 | 整数 |
| 条件 | Threshold | 警报的阈值 | 数字 |
| 条件 | ComparisonOperator | 用于将阈值与统计函数结果进行比较的运算符 | GreaterThanOrEqualToThreshold、GreaterThanThreshold、LessThanThreshold、LessThanOrEqualToThreshold |
| 指标 | Namespace | 指标的来源 | AWS/EC2(来自 EC2 服务的指标) |
| 指标 | Dimensions | 指标的范围 | 取决于指标;对于聚合所有关联 EC2 实例的指标,引用 ASG |
| 指标 | MetricName | 指标的名称 | 例如,CPUUtilization |
| 操作 | AlarmActions | 达到阈值时触发的操作 | 伸缩策略的引用 |
你可以在许多不同的指标上定义警报。你可以在 http://mng.bz/8E0X 找到 AWS 提供的所有命名空间、维度和指标的概述。例如,你可以根据负载均衡器的每个目标的请求数量指标或 EC2 实例的网络吞吐量进行伸缩。你还可以发布自定义指标,例如来自应用程序的线程池使用情况、处理时间或用户会话等指标。
需要注意的是,一些虚拟机(如 t2 实例系列)提供突发性能。这些虚拟机提供基线 CPU 性能,并可以在短时间内基于信用额度突发性能。如果所有信用额度用完,实例将以基线性能运行。对于 t2.micro 实例,基线性能是底层物理 CPU 性能的 10%。
使用具有突发性能的虚拟机可以帮助你应对负载高峰。在低负载时节省信用额度,在高负载时使用信用额度来突发性能。但基于 CPU 负载对具有突发性能的虚拟机进行伸缩是比较棘手的,因为你的伸缩策略必须考虑到实例是否有足够的信用额度来突发性能。你可以考虑寻找其他指标进行伸缩(如会话数量)或使用没有突发性能的实例类型。
自动伸缩与 CloudWatch:灵活应对负载变化
4. 同步和解耦应用的伸缩
在实际应用中,我们常常需要对同步和解耦的应用进行伸缩,以确保系统能够高效地处理不同类型的工作负载。
4.1 负载均衡器后同步解耦应用的伸缩
当应用采用同步解耦架构时,通常会使用负载均衡器(ALB)来分发流量到多个 EC2 实例。自动伸缩组可以与负载均衡器协同工作,根据负载情况动态调整 EC2 实例的数量。
操作步骤如下:
1. 创建启动配置 :定义 EC2 实例的基本配置,如镜像、实例类型等。
LaunchConfiguration:
Type: 'AWS::AutoScaling::LaunchConfiguration'
Properties:
ImageId: 'ami-6057e21a'
InstanceType: 't2.micro'
SecurityGroups:
- webapp
KeyName: mykey
AssociatePublicIpAddress: true
UserData:
'Fn::Base64': !Sub |
#!/bin/bash -x
yum -y install httpd
- 创建自动伸缩组 :指定最小、最大和期望的实例数量,并关联负载均衡器的目标组。
AutoScalingGroup:
Type: 'AWS::AutoScaling::AutoScalingGroup'
Properties:
TargetGroupARNs:
- !Ref LoadBalancerTargetGroup
LaunchConfigurationName: !Ref LaunchConfiguration
MinSize: 2
MaxSize: 4
DesiredCapacity: 2
HealthCheckType: ELB
HealthCheckGracePeriod: 300
VPCZoneIdentifier:
- 'subnet-a55fafc'
- 'subnet-fa224c5a'
- 配置伸缩策略 :可以基于 CloudWatch 指标或计划来调整实例数量。例如,基于 CPU 利用率的步进伸缩策略:
StepScalingPolicy:
Type: 'AWS::AutoScaling::ScalingPolicy'
Properties:
AdjustmentType: ChangeInCapacity
AutoScalingGroupName: !Ref AutoScalingGroup
PolicyType: StepScaling
StepAdjustments:
- MetricIntervalLowerBound: 0
MetricIntervalUpperBound: 50
ScalingAdjustment: -1
- MetricIntervalLowerBound: 50
ScalingAdjustment: 1
Cooldown: 300
EstimatedInstanceWarmup: 300
MetricAggregationType: Average
MinAdjustmentMagnitude: 1
TargetTrackingConfiguration:
PredefinedMetricSpecification:
PredefinedMetricType: ASGAverageCPUUtilization
TargetValue: 70
4.2 使用队列异步解耦应用的伸缩
对于异步解耦的应用,可以使用 Amazon Simple Queue Service(SQS)来处理任务。自动伸缩组可以根据队列中的消息数量来调整 EC2 实例的数量。
操作步骤如下:
1. 创建 SQS 队列 :在 AWS 控制台或使用 AWS CLI 创建 SQS 队列。
2. 修改 EC2 实例配置 :让 EC2 实例从 SQS 队列中获取任务并处理。可以在启动配置的用户数据中添加相关脚本。
LaunchConfiguration:
Type: 'AWS::AutoScaling::LaunchConfiguration'
Properties:
ImageId: 'ami-6057e21a'
InstanceType: 't2.micro'
SecurityGroups:
- webapp
KeyName: mykey
AssociatePublicIpAddress: true
UserData:
'Fn::Base64': !Sub |
#!/bin/bash -x
yum -y install httpd
# 添加从 SQS 队列获取任务的脚本
aws sqs receive-message --queue-url https://sqs.us-east-1.amazonaws.com/123456789012/my-queue
- 配置伸缩策略 :基于 SQS 队列的深度(消息数量)来调整实例数量。例如,使用目标跟踪伸缩策略:
TargetTrackingScalingPolicy:
Type: 'AWS::AutoScaling::ScalingPolicy'
Properties:
AdjustmentType: ChangeInCapacity
AutoScalingGroupName: !Ref AutoScalingGroup
PolicyType: TargetTrackingScaling
TargetTrackingConfiguration:
PredefinedMetricSpecification:
PredefinedMetricType: ASGAverageCPUUtilization
TargetValue: 70
CustomizedMetricSpecification:
Dimensions:
- Name: QueueName
Value: my-queue
MetricName: ApproximateNumberOfMessagesVisible
Namespace: AWS/SQS
5. 自动伸缩的最佳实践
为了更好地使用自动伸缩功能,以下是一些最佳实践建议:
- 合理设置最小和最大实例数量 :根据应用的负载情况和预算,合理设置自动伸缩组的最小和最大实例数量。确保在低负载时也有足够的实例来处理基本请求,同时避免在高负载时过度扩展导致成本过高。
- 选择合适的伸缩策略 :根据应用的负载模式选择合适的伸缩策略。如果负载模式可预测,如每天的特定时间段负载较高,可以使用基于计划的伸缩策略;如果负载变化较为随机,建议使用基于 CloudWatch 指标的伸缩策略。
- 监控和调整 :定期监控自动伸缩组的性能和指标,根据实际情况调整伸缩策略和参数。例如,如果发现某个指标不能准确反映负载情况,可以考虑更换指标或调整阈值。
- 测试和验证 :在生产环境中使用自动伸缩之前,先在测试环境中进行充分的测试和验证。确保伸缩策略能够按预期工作,并且不会对应用的性能和稳定性造成影响。
6. 总结
自动伸缩和 CloudWatch 是 AWS 提供的强大工具,可以帮助我们根据系统的负载情况动态调整 EC2 实例的数量,从而实现弹性计算。通过合理使用自动伸缩组、伸缩策略和 CloudWatch 指标,我们可以应对各种负载模式,提高系统的性能和可用性,同时降低成本。
在实际应用中,我们需要根据具体的业务需求和负载情况,选择合适的伸缩方式和策略,并遵循最佳实践进行配置和管理。希望本文介绍的内容能够帮助你更好地理解和使用自动伸缩和 CloudWatch 功能。
下面是一个简单的 mermaid 流程图,展示了自动伸缩的基本流程:
graph LR
classDef process fill:#E5F6FF,stroke:#73A6FF,stroke-width:2px
A(监控指标):::process --> B{指标是否达到阈值?}:::process
B -- 是 --> C(触发伸缩操作):::process
B -- 否 --> A
C --> D(调整自动伸缩组容量):::process
D --> E(启动或终止 EC2 实例):::process
表格总结不同伸缩策略的特点:
| 伸缩策略类型 | 特点 |
| — | — |
| 步进伸缩 | 支持根据阈值超出程度进行多次伸缩调整,更灵活 |
| 目标跟踪 | 只需定义目标,系统自动调整实例数量,简单易用 |
| 简单伸缩 | 旧选项,已被步进伸缩取代 |
通过以上内容,我们对自动伸缩和 CloudWatch 有了更深入的了解,希望这些知识能在实际应用中发挥作用。
超级会员免费看
16

被折叠的 条评论
为什么被折叠?



