实现高可用性:可用区、自动扩展和 CloudWatch
在云计算环境中,确保服务的高可用性至关重要。当数据中心出现故障时,如何快速恢复服务是一个关键问题。本文将介绍如何利用 AWS 的可用区、自动扩展和 CloudWatch 来实现高可用性,以及如何从数据中心故障中恢复。
1. 从数据中心故障中恢复
当底层软件或硬件出现故障时,可以使用系统状态检查和 CloudWatch 来恢复 EC2 实例。但如果整个数据中心因停电、火灾或其他问题而发生故障,之前的恢复方法将失效,因为它试图在同一数据中心启动 EC2 实例。
AWS 是为应对故障而构建的,即使在整个数据中心出现故障的罕见情况下,也能提供一定的恢复能力。AWS 区域由多个数据中心组成,这些数据中心被划分为可用区。自动扩展可以帮助在数据中心故障时,以较短的停机时间启动虚拟机进行恢复。
在构建跨多个可用区的高可用性设置时,有两个需要注意的问题:
-
网络附加存储(EBS)数据不可用
:默认情况下,故障转移到另一个可用区后,存储在 EBS 上的数据将不可用。在该可用区恢复在线之前,将无法访问存储在 EBS 卷上的数据(但数据不会丢失)。
-
IP 地址问题
:不能在另一个可用区以相同的私有 IP 地址启动新的虚拟机。子网与可用区绑定,每个子网都有唯一的 IP 地址范围。默认情况下,恢复后无法自动保留相同的公共 IP 地址。
2. 可用区:隔离的数据中心组
AWS 在全球多个地点运营,这些地点被称为区域。例如,US East (N. Virginia) 区域,也称为 us - east - 1。目前,在北美、南美、欧洲和亚太地区共有 15 个公开可用的区域。
每个区域由多个可用区(AZ)组成。可以将可用区视为一组隔离的数据中心,而区域则是多个可用区分布在一定距离范围内的区域。例如,us - east - 1 区域由六个可用区(us - east - 1a 到 us - east - 1f)组成。可用区 us - east - 1a 可能是一个数据中心,也可能是多个,因为 AWS 不公开其数据中心的详细信息,所以从 AWS 用户的角度来看,只知道区域和可用区。
可用区通过低延迟链路连接,因此不同可用区之间的请求在延迟方面不像跨互联网的请求那样高。同一可用区内的延迟(例如,同一子网中的一个 EC2 实例到另一个 EC2 实例)比跨可用区的延迟低。可用区的数量因区域而异,大多数区域有三个或更多可用区。在选择区域时,要注意有些区域只有两个可用区,这对于依赖共识决策的分布式系统可能会是一个问题。
一些 AWS 服务默认具有高可用性甚至容错能力,而其他服务则提供构建高可用架构的基础组件。可以使用多个可用区甚至多个区域来构建高可用架构,不同的 AWS 服务具有不同的可用性模式:
-
全局服务
:Route 53(DNS)和 CloudFront(CDN)在多个区域全局运行。
-
区域内多可用区服务
:S3(对象存储)和 DynamoDB(NoSQL 数据库)使用区域内的多个可用区,以便在可用区故障时进行恢复。
-
多可用区部署服务
:关系数据库服务(RDS)提供主 - 备设置,即多可用区(Multi - AZ)部署,必要时可以在短时间内故障转移到另一个可用区。
-
单可用区服务
:虚拟机通常在单个可用区中运行,但 AWS 提供了基于 EC2 实例构建可故障转移到另一个可用区的架构的工具。
可用区的标识符由区域标识符(如 us - east - 1)和一个字符(a, b, c, …)组成。为了在不同可用区之间分配资源,每个 AWS 账户的可用区标识符是随机生成的,这意味着 us - east - 1a 在不同的 AWS 账户中指向不同的可用区。
可以使用以下命令发现 AWS 账户可用的所有区域:
$ aws ec2 describe-regions
{
"Regions": [
{
"Endpoint": "ec2.ap-south-1.amazonaws.com",
"RegionName": "ap-south-1"
},
{
"Endpoint": "ec2.eu-west-2.amazonaws.com",
"RegionName": "eu-west-2"
},
{
"Endpoint": "ec2.eu-west-1.amazonaws.com",
"RegionName": "eu-west-1"
},
[...]
{
"Endpoint": "ec2.us-west-2.amazonaws.com",
"RegionName": "us-west-2"
}
]
}
要列出某个区域的所有可用区,可以执行以下命令,并将
$Region
替换为上一个命令中的
RegionName
:
$ aws ec2 describe-availability-zones --region $Region
{
"AvailabilityZones": [
{
"State": "available",
"ZoneName": "us-east-1a",
"Messages": [],
"RegionName": "us-east-1"
},
{
"State": "available",
"ZoneName": "us-east-1b",
"Messages": [],
"RegionName": "us-east-1"
},
[...]
{
"State": "available",
"ZoneName": "us-east-1f",
"Messages": [],
"RegionName": "us-east-1"
}
]
}
在使用 VPC 服务在 AWS 中定义私有网络时,需要了解以下信息:
-
VPC 与区域绑定
:VPC 始终与一个区域绑定。
-
子网与可用区关联
:VPC 内的子网与可用区关联。
-
虚拟机在单个子网中启动
:虚拟机在单个子网中启动。
以下是这些关系的示意图:
graph LR
classDef process fill:#E5F6FF,stroke:#73A6FF,stroke-width:2px
A(Region):::process --> B(VPC):::process
B --> C(Subnet A<br>Availability zone 1):::process
B --> D(Subnet B<br>Availability zone 1):::process
B --> E(Subnet C<br>Availability zone 2):::process
B --> F(Subnet D<br>Availability zone 2):::process
3. 使用自动扩展确保 EC2 实例始终运行
自动扩展是 EC2 服务的一部分,它可以帮助确保即使在可用区不可用时,也有指定数量的 EC2 实例在运行。可以使用自动扩展来启动虚拟机,并确保在原始实例发生故障时启动新的实例。自动扩展还可以在多个子网中启动虚拟机,因此在整个可用区发生故障时,可以在另一个可用区的另一个子网中启动新的实例。
配置自动扩展需要创建两部分配置:
-
启动配置
:包含启动 EC2 实例所需的所有信息,如实例类型(虚拟机大小)和启动镜像(AMI)。
-
自动扩展组
:告诉 EC2 服务应该使用特定的启动配置启动多少台虚拟机,如何监控实例,以及应该在哪些子网中启动 EC2 实例。
以下是使用自动扩展确保单个 EC2 实例始终运行的配置示例:
LaunchConfiguration:
Type: 'AWS::AutoScaling::LaunchConfiguration'
Properties:
ImageId: 'ami-6057e21a'
InstanceType: 't2.micro'
AutoScalingGroup:
Type: 'AWS::AutoScaling::AutoScalingGroup'
Properties:
LaunchConfigurationName: !Ref LaunchConfiguration
DesiredCapacity: 1
MinSize: 1
MaxSize: 1
VPCZoneIdentifier:
- !Ref SubnetA
- !Ref SubnetB
HealthCheckGracePeriod: 600
HealthCheckType: EC2
所需参数的详细说明如下表所示:
| 上下文 | 属性 | 描述 | 值 |
| ---- | ---- | ---- | ---- |
| LaunchConfiguration | ImageId | 虚拟机应从其启动的 AMI 的 ID | 账户可访问的任何 AMI ID |
| LaunchConfiguration | InstanceType | 虚拟机的大小 | 所有可用的实例大小,如 t2.micro、m3.medium 和 c3.large |
| AutoScalingGroup | DesiredCapacity | 当前自动扩展组中应运行的虚拟机数量 | 任何正整数。如果希望基于启动配置启动单个虚拟机,则使用 1 |
| AutoScalingGroup | MinSize | DesiredCapacity 的最小值 | 任何正整数。如果希望基于启动配置启动单个虚拟机,则使用 1 |
| AutoScalingGroup | MaxSize | DesiredCapacity 的最大值 | 任何正整数(大于或等于 MinSize 值)。如果希望基于启动配置启动单个虚拟机,则使用 1 |
| AutoScalingGroup | VPCZoneIdentifier | 要在其中启动虚拟机的子网 ID | 账户中 VPC 的任何子网 ID。子网必须属于同一个 VPC |
| AutoScalingGroup | HealthCheckType | 用于识别故障虚拟机的健康检查。如果健康检查失败,自动扩展组将用新的虚拟机替换该虚拟机 | EC2(使用虚拟机的状态检查)或 ELB(使用负载均衡器的健康检查) |
自动扩展的工作流程如下:
graph LR
classDef process fill:#E5F6FF,stroke:#73A6FF,stroke-width:2px
A(启动配置):::process --> B(自动扩展组):::process
B --> C(监控虚拟机健康检查):::process
C -->|健康虚拟机不足| D(根据启动配置启动新实例):::process
4. 使用自动扩展将故障虚拟机恢复到另一个可用区
在之前的示例中,使用 CloudWatch 警报在虚拟机运行 Jenkins CI 服务器发生故障时触发恢复。但这种机制只能在同一可用区中启动原始虚拟机的相同副本,因为虚拟机的私有 IP 地址和 EBS 卷与单个子网和单个可用区绑定。如果团队希望在不太可能发生的可用区故障时仍能使用 Jenkins 服务器进行测试、构建和部署新软件,可以使用自动扩展实现故障转移到另一个可用区。
可以在 GitHub 和 S3 上找到此示例的 CloudFormation 模板。可以从 http://mng.bz/x6RP 下载存储库的快照,相关文件位于 chapter14/multiaz.yaml。在 S3 上,相同的文件位于 http://mng.bz/994D。
执行以下命令创建一个在必要时可以在另一个可用区恢复的虚拟机。将
$Password
替换为一个由 8 - 40 个字符组成的密码:
$ aws cloudformation create-stack --stack-name jenkins-multiaz \
--template-url https://s3.amazonaws.com/ \
awsinaction-code2/chapter14/multiaz.yaml \
--parameters ParameterKey=JenkinsAdminPassword,ParameterValue=$Password
在 CloudFormation 模板中,有一个启动配置和一个自动扩展组。启动配置的一些重要参数与之前使用 CloudWatch 恢复警报启动单个虚拟机时相同:
-
ImageId
:虚拟机的镜像(AMI)ID。
-
InstanceType
:虚拟机的大小。
-
KeyName
:SSH 密钥对的名称。
-
SecurityGroupIds
:安全组的链接。
-
UserData
:在启动时执行的脚本,用于安装 Jenkins CI 服务器。
与单个 EC2 实例定义的一个重要区别是,虚拟机的子网不是在启动配置中定义的,而是在自动扩展组中定义的。
以下是 CloudFormation 模板的示例:
LaunchConfiguration:
Type: 'AWS::AutoScaling::LaunchConfiguration'
Properties:
InstanceMonitoring: false
ImageId: 'ami-6057e21a'
KeyName: mykey
SecurityGroups:
- !Ref SecurityGroup
AssociatePublicIpAddress: true
InstanceType: 't2.micro'
UserData:
'Fn::Base64': !Sub |
#!/bin/bash -x
bash -ex << "TRY"
wget -q -T 60 https://.../jenkins-1.616-1.1.noarch.rpm
rpm --install jenkins-1.616-1.1.noarch.rpm
# [...]
service jenkins start
TRY
/opt/aws/bin/cfn-signal -e $? --stack ${AWS::StackName} \
--resource AutoScalingGroup --region ${AWS::Region}
AutoScalingGroup:
Type: 'AWS::AutoScaling::AutoScalingGroup'
Properties:
LaunchConfigurationName: !Ref LaunchConfiguration
Tags:
- Key: Name
Value: 'jenkins-multiaz'
PropagateAtLaunch: true
DesiredCapacity: 1
MinSize: 1
MaxSize: 1
VPCZoneIdentifier:
- !Ref SubnetA
- !Ref SubnetB
HealthCheckGracePeriod: 600
HealthCheckType: EC2
CreationPolicy:
ResourceSignal:
Timeout: PT10M
创建 CloudFormation 堆栈需要几分钟时间。执行以下命令获取虚拟机的公共 IP 地址:
$ aws ec2 describe-instances --filters "Name=tag:Name,Values=jenkins-multiaz" "Name=instance-state-code,Values=16" \
--query "Reservations[0].Instances[0].[InstanceId, PublicIpAddress, PrivateIpAddress, SubnetId]"
如果没有显示 IP 地址,说明虚拟机尚未启动,等待一分钟后再试。将输出中的公共 IP 地址替换为
$PublicIP
,在浏览器中打开
http://$PublicIP:8080
,即可看到 Jenkins 服务器的 Web 界面。
执行以下命令终止虚拟机并测试自动扩展的恢复过程。将
$InstanceId
替换为上一个描述命令输出中的实例 ID:
$ aws ec2 terminate-instances --instance-ids $InstanceId
几分钟后,自动扩展组会检测到虚拟机已终止,并启动一个新的虚拟机。重新运行描述实例的命令,直到输出中包含一个新的运行中的虚拟机:
$ aws ec2 describe-instances --filters "Name=tag:Name,Values=jenkins-multiaz" "Name=instance-state-code,Values=16" \
--query "Reservations[0].Instances[0].[InstanceId, PublicIpAddress, PrivateIpAddress, SubnetId]"
新实例的实例 ID、公共 IP 地址、私有 IP 地址,甚至子网 ID 可能都会发生变化。再次将输出中的公共 IP 地址替换为
$PublicIP
,在浏览器中打开
http://$PublicIP:8080
,仍然可以看到 Jenkins 服务器的 Web 界面。
通过以上步骤,可以利用 AWS 的可用区、自动扩展和 CloudWatch 实现高可用性,并在数据中心故障时快速恢复服务。
实现高可用性:可用区、自动扩展和 CloudWatch
5. 高可用性架构的优势总结
使用 AWS 的可用区、自动扩展和 CloudWatch 构建高可用性架构具有诸多显著优势,以下为您详细阐述:
-
快速故障恢复
:当某个可用区出现故障时,自动扩展功能能够迅速在其他可用区启动新的实例,大大缩短了服务的停机时间,确保业务的连续性。例如,在上述 Jenkins 服务器的例子中,当原实例所在的可用区出现问题,自动扩展组会及时在其他可用区启动新实例,保障 Jenkins 服务尽快恢复。
-
资源合理分配
:自动扩展可以根据实际需求动态调整运行的实例数量。在业务高峰期增加实例以应对高负载,在业务低谷期减少实例以节省成本。比如,对于一些电商网站,在促销活动期间可以自动增加 EC2 实例数量,活动结束后再减少实例,实现资源的高效利用。
-
全局服务覆盖
:借助 AWS 的多个区域和可用区,以及像 Route 53 和 CloudFront 这样的全局服务,可以为全球用户提供低延迟的服务。Route 53 可以将用户的请求路由到最近的可用区,CloudFront 则可以缓存内容并在全球边缘节点分发,提升用户体验。
6. 高可用性架构实施的注意事项
在实施高可用性架构时,还需要注意以下几个方面:
-
数据一致性
:由于数据存储在不同的可用区甚至不同的区域,需要确保数据的一致性。例如,对于使用 RDS 进行多可用区部署的数据库,要考虑主备节点之间的数据同步问题,避免出现数据不一致的情况影响业务。
-
网络配置
:合理的网络配置是实现高可用性的关键。要确保不同可用区之间的网络连接稳定且低延迟,同时要配置好 VPC、子网和安全组,保障虚拟机的网络安全。例如,在创建 VPC 时,要为不同的可用区分配合适的子网,并设置好安全组规则,防止非法访问。
-
成本控制
:虽然高可用性架构可以提升服务的可靠性,但也会带来一定的成本增加。需要根据业务需求和预算,合理选择实例类型、可用区数量等资源,避免不必要的成本浪费。例如,对于一些非关键业务系统,可以适当减少可用区的使用数量,降低成本。
7. 自动扩展的高级应用场景
除了上述基本的自动扩展应用,自动扩展还有一些高级应用场景:
-
基于负载的自动扩展
:可以根据系统的负载指标,如 CPU 使用率、内存使用率等,动态调整实例数量。当系统负载超过设定的阈值时,自动扩展组会自动增加实例;当负载降低时,会减少实例。以下是一个基于 CPU 使用率进行自动扩展的配置示例:
ScalingPolicy:
Type: 'AWS::AutoScaling::ScalingPolicy'
Properties:
AutoScalingGroupName: !Ref AutoScalingGroup
AdjustmentType: ChangeInCapacity
ScalingAdjustment: 1
Cooldown: 300
PolicyType: SimpleScaling
Alarm:
Type: 'AWS::CloudWatch::Alarm'
Properties:
AlarmName: CPUHighAlarm
AlarmDescription: Alarm when CPU utilization is high
MetricName: CPUUtilization
Namespace: AWS/EC2
Statistic: Average
Period: 300
EvaluationPeriods: 2
Threshold: 80
ComparisonOperator: GreaterThanThreshold
Dimensions:
- Name: AutoScalingGroupName
Value: !Ref AutoScalingGroup
AlarmActions:
- !Ref ScalingPolicy
在这个示例中,当 EC2 实例的 CPU 使用率连续 2 个周期(每个周期 300 秒)超过 80% 时,会触发自动扩展策略,自动扩展组会增加 1 个实例。
- 多维度自动扩展 :可以结合多个指标进行自动扩展,如同时考虑 CPU 使用率、网络流量等。这样可以更全面地反映系统的负载情况,实现更精准的自动扩展。例如,可以设置一个规则,当 CPU 使用率超过 70% 且网络流量超过一定阈值时,才触发自动扩展操作。
8. 总结与展望
通过本文的介绍,我们了解了如何利用 AWS 的可用区、自动扩展和 CloudWatch 实现高可用性架构。从数据中心故障恢复到自动扩展的配置和应用,以及高级应用场景的探讨,我们看到了高可用性架构在保障业务连续性、提升服务质量和降低成本方面的重要作用。
随着云计算技术的不断发展,未来高可用性架构将更加智能化和自动化。例如,利用机器学习算法预测系统的负载变化,提前进行自动扩展操作,进一步减少人工干预。同时,云服务提供商也会不断优化可用区的布局和网络架构,为用户提供更可靠、更高效的云计算服务。
在实际应用中,我们可以根据业务的特点和需求,灵活运用这些技术和方法,构建适合自己的高可用性架构,为业务的稳定发展提供有力保障。
以下是一个自动扩展基于负载调整实例数量的 mermaid 流程图:
graph LR
classDef process fill:#E5F6FF,stroke:#73A6FF,stroke-width:2px
A(监控系统负载指标):::process --> B{负载是否超过阈值?}:::process
B -->|是| C(自动扩展组增加实例):::process
B -->|否| D{负载是否低于阈值?}:::process
D -->|是| E(自动扩展组减少实例):::process
D -->|否| A
表 2:自动扩展高级配置参数说明
| 参数 | 描述 | 示例值 |
| ---- | ---- | ---- |
| AdjustmentType | 调整实例数量的方式,如 ChangeInCapacity 表示按实例数量变化调整 | ChangeInCapacity |
| ScalingAdjustment | 调整的实例数量 | 1 |
| Cooldown | 冷却时间,避免频繁调整实例数量 | 300 |
| PolicyType | 扩展策略类型,如 SimpleScaling 表示简单扩展策略 | SimpleScaling |
综上所述,实现高可用性架构需要综合考虑多个因素,合理运用 AWS 提供的各种工具和服务,不断优化和调整架构,以适应业务的发展和变化。
超级会员免费看
1035

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



