从可用区中断中自动恢复?

Posted

技术标签:

【中文标题】从可用区中断中自动恢复?【英文标题】:Automatic recovery from an availability zone outage? 【发布时间】:2013-04-25 02:17:25 【问题描述】:

如果可用区在 Amazon Web Services/EC2 中出现中断,是否有任何工具或技术可用于在不同的可用区自动创建新实例?

我想我了解如何在可用区 (AZ) 中断的情况下进行自动故障转移,但是如何从中断中自动恢复(在新 AZ 中创建新实例)?这可能吗?

示例场景:

    我们有一个三实例集群。 ELB 循环访问集群的流量。 我们可以丢失集群中的任何一个实例,但不能丢失两个实例,但仍然可以正常工作。 由于 (3),每个实例位于不同的 AZ。称它们为 AZ A、B 和 C。 配置了 ELB 健康检查,以便 ELB 可以确保每个实例都健康。 假设一个实例由于 AZ A 中的 AZ 中断而丢失。

此时,ELB 将看到丢失的实例不再响应运行状况检查,并将停止将流量路由到该实例。所有请求都将转到剩余的两个健康实例。故障转移成功。

恢复是我不清楚的地方。有没有办法自动(即无需人工干预)替换新 AZ(例如 AZ D)中丢失的实例?这将避免出现中断的可用区 (A),而不使用其中已经有实例的可用区(可用区 B 和 C)。

AutoScaling 组?

AutoScaling Groups 似乎是一个很有前途的起点,但我不知道他们是否能正确处理这个用例。

问题:

在 AutoScaling 组中,似乎没有办法指定替换死/不健康实例的新实例应在新 AZ 中创建(例如,在 AZ D 中创建,而不是在 AZ A 中创建)。这是真的吗? 在 AutoScaling 组中,似乎没有办法告诉 ELB 删除失败的 AZ 并自动添加新的 AZ。对吗?

这些是 AutoScaling Groups 中真正的缺点,还是我遗漏了什么?

如果 AutoScaling Groups 无法做到这一点,是否有其他工具可以自动为我做到这一点?

2011 年 FourSquare、Reddit 和其他人因依赖单一可用区 (http://www.informationweek.com/cloud-computing/infrastructure/amazon-outage-multiple-zones-a-smart-str/240009598) 而陷入困境。从那时起,工具似乎已经走了很长一段路。我对缺乏自动恢复解决方案感到惊讶。每家公司是否只是推出自己的解决方案和/或手动进行恢复?或者他们只是在掷骰子并希望它不会再次发生?

更新:

@Steffen Opel,感谢detailed explanation。 Auto Scaling 组看起来更好,但我认为它们在与 ELB 一起使用时仍然存在问题。

假设我创建了一个 Auto Scaling 组,其最小值、最大值和期望值设置为 3,分布在 4 个可用区。 Auto Scaling 将在 3 个不同的 AZ 中创建 1 个实例,第 4 个 AZ 留空。如何配置 ELB?如果它转发到所有 4 个 AZ,那将不起作用,因为一个 AZ 将始终拥有零个实例,而 ELB 仍会将流量路由到它。这将导致当流量进入空 AZ 时返回 HTTP 503。我过去曾亲身经历过。 Here is an example of what I saw before。

这似乎需要手动将 ELB 的可用区更新为仅在其中运行实例的可用区。每次自动缩放导致不同的可用区组合时,都需要发生这种情况。是这样吗,还是我错过了什么?

【问题讨论】:

【参考方案1】:

有很多方法可以解决这个问题。在不知道您的“集群”是什么以及新节点如何活跃的情况下,可能会向主节点注册,加载数据等以进行引导。例如在 hadoop 上,一个新的从节点需要向将为其提供内容的 namenode 注册。但忽略了这一点。只关注新节点的启动。

您可以将 cli 工具用于 windows 或 linux 实例。我从我的两个操作系统的开发盒和两个操作系统的服务器上都将它们发射出去。例如,这里是 linux 的链接:

http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/setting_up_ec2_command_linux.html#set_aes_home_linux

它们由许多命令组成,您可以在 dos 或 linux shell 上执行这些命令来执行诸如启动实例或终止实例之类的操作。它们需要配置环境变量,例如您的 aws 凭据和 java 的路径。这是在 AvailZone=us-east-1d 中创建实例的示例输入和输出

示例命令: ec2-request-spot-instances ami-52009e3b -p 0.02 -z us-east-1d --key DrewKP3 --group linux --instance-type m1.medium -n 1 --type one-time

样本输出: SPOINSTANCEREQUEST sir-0fd0dc32 0.020000 一次性 Linux/UNIX 开放 2013-05-01T09:22:18-0400 ami-52009e3b m1.medium DrewKP3 linux us-east-1d 监控禁用

请注意,我是一个便宜货并使用 2 美分的 Spot 实例,因此您将使用标准实例而不是 Spot。但话又说回来,我正在创建数百台服务器。

好的,所以你有一个数据库。为论证起见,假设您有 AWS RDS mysql,微型实例以 Multi-AvailZone 模式运行,每小时额外收费半美分。也就是每天 72 美分。它包含一个表,称为 zonepref (AZ,preference)。比如

us-west-1b,1

us-west-1c,2

us-west-2b,3

us-east-1d,4

eu-west-1b,5

ap-southeast-1a,6

你明白了。区域的偏好。

RDS 中还有另一个表,类似于“active_nodes”,其中包含 IP addr、instance-id、zone、lastcontact、status 列(字符串、字符串、字符串、日期时间、字符)。假设它包含以下活动节点信息:

'10.70.132.101','i-2c55bb41','us-east-1d','2013-05-01 11:18:09','A'

'10.70.132.102','i-2c66bb42','us-west-1b','2013-05-01 11:14:34','A'

'10.70.132.103','i-2c77bb43','us-west-2b','2013-05-01 11:17:17','A'

'A'=活着和健康,'G'=快死了,'D'=死了

现在您的节点在启动时会建立一个 cron 作业或运行一个服务,让我们称它为使用您喜欢的任何语言(如 java 或 ruby​​)的服务器。这被烘焙到您的 ami 中以在启动时运行,并且在初始化时它会退出并将其数据插入到 active_nodes 表中,因此它的行就在那里。至少它每 5 分钟运行一次(取决于整个任务的关键程度)。 cron 作业将以该时间间隔运行,或者 java/ruby 将创建一个线程,该线程将在该时间段内休眠。当涉及到生命时,它会获取它的 ipaddr、instanceid、AZ,并调用 RDS 来更新它的行,其中 status='A' 使用 UTC 时间作为 lastcontact 时间,这在不同时区是一致的。如果它的状态不是“A”,则不会发生更新。

此外,它会更新其中任何其他 ip addr 行的状态列,即 status='A',将其更改为 status='G'(即将死),就像我说的那样,其他 ipaddr 现在( )-lastcontact 大于 6 或 7 分钟。此外,它可以使用套接字(选择一个端口)联系 Going Dead 服务器并说,嘿,你在吗?如果是这样,也许 Going Dead 服务器无法访问 RDS,尽管它位于多可用区,但仍可以处理其他流量。如果没有联系,则将其他服务器状态更改为“D”=Dead。根据需要进行优化。

在这里编写运行在其节点上的“服务器”的概念是具有一个休眠的管家线程和将阻塞/侦听端口的主线程。整个事情可以用 ruby​​ 用不到 50 到 70 行代码编写。

服务器可以使用 CLI 并终止其他服务器的实例 ID,但在此之前,它会执行一些操作,例如从 table zonepref 发出一个 select 语句,该语句按优先级排序,用于不在 active_nodes 中的第一行。它现在有下一个区域,它使用正确的 ami-id 和下一个区域等运行 ec2-run-instances,并在必要时传递用户数据。您不希望两个 Alive 服务器都创建一个新实例,因此要么在 mysql 中使用行锁包装创建,要么将请求推送到队列或堆栈中,以便只有其中一个执行它。

无论如何,这似乎有点矫枉过正,但我​​做了很多集群工作,其中节点必须直接相互通信。请注意,我并不是建议仅仅因为一个节点似乎已经失去了它的心跳,它的 AZ 已经关闭了:> 也许只是那个实例失去了它的午餐。

【讨论】:

【参考方案2】:

有没有办法在新的 AZ(例如 AZ D)中自动(即无需人工干预)替换丢失的实例?

Auto Scaling 确实是适合您用例的服务 - 回答您各自的问题:

在 AutoScaling 组中,似乎没有办法指定替换死/不健康实例的新实例应在新 AZ 中创建(例如,在 AZ D 中创建,而不是在 AZ A 中创建)。这是真的吗?在 AutoScaling 组中,似乎没有办法告诉 ELB 删除失败的 AZ 并自动添加新的 AZ。对吗?

您不必明确指定/告诉任何内容,它隐含在 Auto Scaling 的工作原理中(请参阅 Auto Scaling Concepts and Terminology) - 您只需配置一个 Auto Scaling 组,其中包含 a)您要运行的实例数( 通过定义组必须具有的运行 EC2 实例的最小、最大和所需数量)和 b) 哪些 AZ 是您的实例的合适目标(通常/理想情况下,一个区域内您的账户中可用的所有 AZ )。

Auto Scaling 然后负责 a) 启动请求数量的实例,以及 b) 在配置的 AZ 中平衡这些实例。自动处理 AZ 中断,请参阅 Availability Zones and Regions:

Auto Scaling 让您可以通过跨区域内多个可用区的 Auto Scaling 组来利用地理冗余的安全性和可靠性。 当一个可用区运行状况不佳或不可用时,Auto Scaling 会在未受影响的可用区中启动新实例。当不正常的可用区恢复正常时,Auto Scaling 会自动在所有指定的可用区中均匀地重新分配应用程序实例。 [强调我的]

后续部分跨多个区域的实例分布和平衡进一步解释了该算法:

Auto Scaling 尝试在为您的 Auto Scaling 组启用的可用区之间平均分配实例。 Auto Scaling 通过尝试在具有最少实例的可用区中启动新实例来做到这一点。但是,如果尝试失败,Auto Scaling 将尝试在其他区域中启动,直到成功。 [强调我的]

请查看链接文档以了解更多详细信息以及如何处理边缘情况。

更新

关于您关于可用区数量高于实例数量的后续问题, 我认为您需要采取务实的方法:

您应该简单地选择数量等于或小于您要运行的实例数量的 AZz;如果发生 AZ 中断,Auto Scaling 会很高兴地在剩余的健康 AZ 之间平衡您的实例,这意味着您将能够在示例中 3 个 AZ 中的 2 个中断的情况下幸存下来,并且仍然拥有所有 3 个实例在剩余 AZ 中运行。

请注意,虽然使用尽可能多的可用 AZ 可能很有趣,但新客户可以访问美国东部(弗吉尼亚北部)的三个 EC2 可用区和美国西部(加利福尼亚北部)的两个可用区 无论如何都只能访问(参见Global Infrastructure),即只有较旧的帐户可能实际上可以访问us-east-1 中的所有5 个可用区,有些只有4 个,而较新的最多3 个。

我认为这是一个遗留问题,即 AWS 显然正在让较旧的 AZ 停止运行。例如,即使您可以访问us-east-1 中的所有 5 个可用区,但实际上某些实例类型可能并非在所有这些可用区中都可用(例如,New EC2 Second Generation Standard Instances m3.xlargem3.2xlarge 仅在其中 3 个可用我正在使用的其中一个帐户中有 5 个可用区)。

换句话说,2-3 个可用区被认为是一个区域内容错的相当好的折衷方案,如果有任何跨区域容错可能是我接下来要担心的事情。

【讨论】:

嗨@Steffen,感谢您的详细解释。我已对问题添加了更新。 谢谢,@Steffen。感谢您提供关于 AZ 数量与实例相比的建议。我没有意识到新客户的可用区数量正在减少。我的帐户已经有一段时间了——我可以在 us-east-1 中看到 4 个 AZ,在 us-west-1 中看到 3 个。我想我会继续计划在 Auto Scaling 组中使用 3 个可用区和 3 个或 4 个实例。【参考方案3】:

没有足够的代表发表评论。

我想补充一点,ELB 不会将流量路由到空 AZ。这是因为 ELB 将流量路由到实例,而不是 AZ。

将 AZ 附加到 ELB 仅在子网中创建弹性网络接口在该 AZ 中,以便在添加该 AZ 中的实例时可以路由流量。它正在添加创建路由的实例(AZ 与实例相关联,但也与 ELB 相关联)。

【讨论】:

以上是关于从可用区中断中自动恢复?的主要内容,如果未能解决你的问题,请参考以下文章

腾讯云广州区全面断网!只因运营商光缆物理中断(现已恢复)

linux 自动检测 IRQ 号

通过中断的连接从 Internet 下载文件

压力测试术语之熔断降级限流

Oracle 11g 使用RMAN备份数据库

MySQL高可用群集--MMM高可用架构