33、实现高可用性:可用区、自动扩展和 CloudWatch

实现高可用性:可用区、自动扩展和 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 提供的各种工具和服务,不断优化和调整架构,以适应业务的发展和变化。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值