AWS 配置 AutoScaling 实现高可用的弹性计算服务

先验知识

AWS 是亚马逊云计算平台。

EC2 是 AWS 提供的云主机,一般采用基于 CentOS 的 Amazon Linux 系统,像大多数云主机一样使用。

ELB 是 AWS 提供的负载均衡服务,可以将请求转发到目标组中的某个 EC2 实例,也会对目标组实例进行健康检查,只将请求转发到健康的实例。

目标

AWS AutoScaling 服务允许我们设定 AutoScaling 组(ASG)。ASG 维护了一组 EC2 实例,EC2 实例可以分布在不同的可用区里以保证可用性。AutoScaling 能检查实例健康状况,自动替换不健康的实例,能根据特定规则增减需要的实例数量,并能在启动、销毁 EC2 实例时触发事件调用其他服务。AutoScaling 服务能够与 ELB 弹性负载均衡服务结合使用,实例不需要公网 IP,而且实例在启动后会自动加入 ELB 的目标组,在终止实例前会先等待 ELB 连接耗尽。

我们要实现的结构如图所示:

结构示例图
结构示例图

看上去梦寐以求,但用起来却没有这么舒服。

给 ASG 创建 EC2 的启动配置

我们需要给 ASG 提供启动配置(Launch Configuration),启动配置里指定了 EC2 的实例类型、AMI 镜像、存储设备、IAM 角色、SSH Key、用户数据(User Data)等一系列信息,用于启动新实例。

我们主要关心 IAM 角色和启动脚本,其他的按需配置。

用户数据实际上是启动脚本,当 EC2 实例启动时,在初始化的最后以 root 身份将用户数据作为脚本执行。你可以登录实例,在 /var/log/cloud-init-output.log 日志尾查看其输出。

因为每次修改启动配置都需要重新创建 ASG,而这就需要清空实例等十分繁琐,所以最好将用户数据设置为从外部获取真正的启动脚本来运行,以便修改调试:

#!/usr/bin/env bash
aws s3 cp s3://bucket/key /tmp/myscript.sh &&
chmod +x /tmp/myscript.sh && /tmp/myscript.sh

这需要给 EC2 的 IAM 角色允许 S3 访问权限。

创建 ASG

我们根据启动配置创建 ASG,设定最低、最高、所需的实例数量,将实例连接到特定的 ELB 目标组,以 ELB 的健康检查作为 ASG 中实例的健康依据等等。

不健康的实例在健康检查失败且等待超时后将被终止。具体请参考 ASG 中实例的运行状况检查

ASG 中实例的生命周期

ASG 中实例有生命周期的概念,也就是实例有一个状态,并在不同的状态间转移。

ASG 中实例的生命周期如图所示:

ASG 中实例的生命周期
ASG 中实例的生命周期
生命周期钩子

在启动的 Pending 和终止的 Terminating 状态均可以添加钩子,钩子会触发事件,并等待事件完成再进入下一状态(当没有钩子时实例会自动跳到下一状态)。钩子能设置超时时限、超时结果。

可以使用 aws-cli 或 AWS SDK 等主动完成生命周期事件,或延期它。事件完成需要提供结果,主动完成和超时均有“继续”和“放弃”两种结果可选。

可以给启动或终止阶段添加多个钩子,他们会在上一个钩子完成且结果为“继续”后依次执行。在启动阶段一旦出现“放弃”的结果后,实例会跳过其他钩子,直接开始终止过程,这也会触发终止阶段的钩子;在终止阶段出现“放弃”的结果后,实例会跳过其他钩子,直接终止。

添加钩子

使用 aws autoscaling put-lifecycle-hook 命令添加沟子,有两种可选的 transition 值:

  • autoscaling:EC2_INSTANCE_LAUNCHING 实例启动时
  • autoscaling:EC2_INSTANCE_TERMINATING 实例终止时

下面这个命令的例子演示了添加“启动时钩子,超时时限 600s,超时后放弃该实例”:

aws autoscaling put-lifecycle-hook \
    --auto-scaling-group-name ${ASG} \
    --lifecycle-hook-name ${HOOK} \
    --lifecycle-transition "autoscaling:EC2_INSTANCE_LAUNCHING" \
    --heartbeat-timeout 600 \
    --default-result "ABANDON"

如果使用了下文的 SNS 或 SQS 接收事件,还需要提供 role-arnnotification-target-arn。AWS 提供了比较完整的文档 添加生命周期钩子 来讲述这一过程。

报告事件完成或延期

使用 aws autoscaling complete-lifecycle-action 命令可以主动完成事件,使生命周期继续(CONTINUE)或放弃(ABANDON),根据你获得的信息,提供 instance-idlifecycle-action-token 任一即可:

下面这个命令的例子演示了“完成 ${ASG} 组的实例 ${INSTANCE_ID} 上的 ${HOOK} 事件,结果为继续”:

aws autoscaling complete-lifecycle-action \
    --auto-scaling-group-name ${ASG} \
    --lifecycle-hook-name ${HOOK} \
    --instance-id ${INSTANCE_ID} \
    --lifecycle-action-result CONTINUE

命令 aws autoscaling record-lifecycle-action-heartbeat 可以重置超时时间,使用方法类似于上文所述的 complete-lifecycle-action

注意,如果希望 EC2 之上的脚本来执行上述操作,需要给 EC2 的 IAM 角色允许 autoscaling:CompleteLifecycleActionautoscaling:RecordLifecycleActionHeartbeat 权限。

EC2 实例如何获取自身的 instance-id 呢?

INSTANCE_ID=$(curl -s http://169.254.169.254/latest/meta-data/instance-id)
ASG=$(aws autoscaling describe-auto-scaling-instances --output text --query 'AutoScalingInstances[?InstanceId==`'${INSTANCE_ID}'`].AutoScalingGroupName')

具体请参考 检索实例元数据控制 aws-cli 的命令输出

钩子事件的传播

AWS 允许钩子触发后向外传播这一事件,有三种方式——通过 CloudWatch Events、SNS 或者 SQS。他们会携带足够的信息,具体的携带数据请参考 AutoScaling 事件

具体配置如果有疑问,请参考 添加生命周期钩子 中《向 Auto Scaling 组添加生命周期挂钩》节的前两步。

事件被传播后,一般使用 Amazon Lambda 或者额外的服务器来处理。同样注意,如果希望 Lambda 报告事件完成或延期,请给 Lambda 的 IAM 角色允许相应权限。

很多时候我们需要在 EC2 实例上执行脚本,这方面的内容请参见这篇博客 AWS 使用 Simple System Manager 向 EC2 发送命令远程执行脚本

事件处理的个人经验

在实例启动时,我们一般不把事件传播出去交由 Lambda 处理,而是由用户数据里的启动脚本在执行结束后自行报告事件完成(继续),或者通知 SQS、SNS、Lambda 等来做。

因为在实例启动时我们需要手动安装 SSM Agent,此时该服务对外界而言不可用。所以我们不能用这种方式来与 EC2 通信。

在实例终止时,我们一般用 Lambda 处理,并用 SSM 通知 EC2 执行回收脚本,回收脚本自行报告事件完成(继续),如果 SSM 失败,再由 Lambda 报告事件完成(放弃)。

扩展 ASG 的大小

AWS 提供了多种 扩展 ASG 的大小 的策略。

这里我们提供两个简单的手工策略来扩展 ASG 的大小:

aws autoscaling put-scaling-policy \
    --auto-scaling-group-name ${ASG} \
    --policy-name "inc" \
    --policy-type "SimpleScaling" \
    --adjustment-type "ChangeInCapacity" \
    --scaling-adjustment 1

aws autoscaling put-scaling-policy \
    --auto-scaling-group-name ${ASG} \
    --policy-name "dec" \
    --policy-type "SimpleScaling" \
    --adjustment-type "ChangeInCapacity" \
    --scaling-adjustment -1

现在我们获得了高可用的弹性计算服务,配置过程很复杂,最好能够采用 CloudFormation 来配置,或者使用 aws-cli 编写脚本来完成。

祝大家使用愉快。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,458评论 4 363
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,454评论 1 294
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,171评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,062评论 0 207
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,440评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,661评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,906评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,609评论 0 200
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,379评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,600评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,085评论 1 261
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,409评论 2 254
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,072评论 3 237
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,088评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,860评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,704评论 2 276
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,608评论 2 270

推荐阅读更多精彩内容