48

当您想在 ELB 后面部署新版本的应用程序时,如何在 AWS 中建立维护页面?我们希望在新的自动扩展实例出现时让 ELB 将流量路由到维护实例,并且只有在它们完全启动后才“翻转”到新实例。我们使用自动缩放来降低现有实例并启动具有新代码的新实例。

我们试图避免的情况是让 ELB 为新 EC2 实例提供流量,同时还提供维护页面。由于我们没有启用粘性会话,我们希望防止用户在维护模式页面和部署在 EC2 实例中的应用程序之间来回切换。我们也不能只是扩大规模(例如从 2 个实例增加到 4 个实例,然后再回到 2 个)来引入新实例,因为代码更改可能涉及数据库更改,这会破坏旧代码的更改。

4

6 回答 6

29

我意识到这是一个老问题,但在今天(2018 年 12 月)面临同样的问题之后,似乎还有另一种方法可以解决这个问题。

今年早些时候,AWS 引入了对应用程序负载均衡器的重定向和固定响应的支持。简而言之:

  • 在控制台中找到您的 ELB。
  • 查看相应侦听器的规则。
  • 为应用程序的主机名添加固定的 503 响应规则。
  • 可选择提供一个text/plaintext/html响应(即您的维护页面 HTML)。
  • 保存更改。

一旦规则传播到 ELB(我花了大约 30 秒),当您尝试在浏览器中访问您的主机时,您将看到 503 维护页面。

部署完成后,只需删除您添加的规则。

于 2018-12-17T13:54:16.353 回答
23

AWS 上最简单的方法是使用他们的 DNS 服务Route 53

您可以使用加权循环的功能。

“您可以使用 WRR 将服务器投入生产,执行 A/B 测试,或平衡跨区域或不同规模数据中心的流量。”

AWS 文档中有关此功能的更多信息

编辑:Route 53 最近添加了一项新功能,允许 DNS 故障转移到 S3。查看他们的文档以获取更多详细信息: http: //docs.aws.amazon.com/Route53/latest/DeveloperGuide/dns-failover.html

于 2012-12-04T10:05:43.143 回答
10

想出了另一个对我们很有效的解决方案。以下是获得简单 503 http 响应所需的步骤:

  1. 复制您的 EB 环境以创建另一个环境,app-environment-maintenance例如将其命名为 。
  2. 更改自动缩放的配置并将最小和最大服务器都设置为零。这不会花费您任何 EC2 服务器,并且环境将变为灰色并位于您的列表中。
  3. 最后,您现在可以使用 AWS CLI 交换环境 CNAME 以使您的主环境进入维护模式。例如:

    aws elasticbeanstalk swap-environment-cnames \
        --profile "$awsProfile" \
        --region "$awsRegion" \
        --output text \
        --source-environment-name app-prod \
        --destination-environment-name app-prod-maintenance
    

这会将您的app-prod环境切换到维护模式。这将导致 ELB 抛出 503,因为没有任何正在运行的 EC2 实例,然后 Cloudfront 可以捕获 503 并返回您的自定义 503 错误页面,如果您愿意,如下所述。


使用 Cloudfront 的自定义错误页面的奖励配置:

我们使用 Cloudfront,就像许多人使用 HTTPS 等一样。Cloudfront 有错误页面。这是一个要求。

  1. 使用您的错误页面创建一个新的 S3 网站托管存储桶。考虑为响应代码、503 等创建单独的文件。有关目录要求和路由,请参见 #6。
  2. 将 S3 存储桶添加到您的 Cloudfront 分配。
  3. 为类似/error/*.
  4. 在 Cloudfront 中设置错误页面以处理 503 响应代码并将其指向您的 S3 存储桶路由,例如/error/503-error.html

现在,当您的 ELB 抛出 503 时,将显示您的自定义错误页面。

就是这样。我知道有很多步骤可以获取自定义错误页面,并且我尝试了很多建议的选项,包括 Route53 等。但是所有这些都存在与 ELB 和 Cloudfront 等的工作方式的问题。

请注意,在您交换环境的主机名后,传播大约需要一分钟左右。

于 2017-09-24T23:47:35.613 回答
9

Route53 不是解决这个问题的好办法。在维护页面显示之前,DNS 条目需要很长时间才能过期(然后在维护完成后更新它们需要同样的时间)。我意识到在提出这个问题时 Lambda 和 CodeDeploy 触发器并不存在,但我想让其他人知道 Lambda 可用于为此创建一个相对干净的解决方案,我在博客文章中对此进行了详细说明: http: //blog.ajhodges.com/2016/04/aws-lambda-setting-temporary.html

该解决方案的要点是将 Lambda 函数订阅到 CodeDeploy 事件,该事件将您的 ASG 替换为在部署期间为负载均衡器中的静态页面提供服务的微型实例。

于 2016-04-26T15:30:36.777 回答
2

据我所知,我们处于上述答案不适用或不理想的情况。

我们有一个在 64 位 Amazon Linux/2.9.0 上运行 Puma 和 Ruby 2.3 的 Rails 应用程序,它似乎带有(经典)ELB。

所以 ALB 503 处理不是一种选择。

我们还有各种硬件客户端,我不相信它们总是尊重 DNS TTL,所以 Route53 是有风险的。

似乎运行良好的是平台附带的 nginx 上的辅助端口。

我将此添加为.ebextensions/maintenance.config

files:
  "/etc/nginx/conf.d/maintenance.conf":
    content: |
      server {
        listen 81;
        server_name _ localhost;
        root /var/app/current/public/maintenance;
      }

container_commands:
  restart_nginx:
    command: service nginx restart

并将https://gist.github.com/pitch-gist/2999707的副本放入public/maintenance/index.html

现在要设置维护,我只需将我的 ELB 侦听器切换为指向端口 81 而不是默认的 80。没有额外的实例、s3 存储桶或等待客户端访问新的 DNS。

beantalk(可能主要等待后端的云形成)只需要大约 15 秒左右即可申请。

于 2019-04-08T03:00:28.240 回答
1

我们的部署过程首先运行一个 cloudformation 来启动一个 ec2 微实例(维护实例),它将预定义的静态页面从 s3 复制到 ec2 上。Cloudformation 随 elb 一起提供,微 ec2 实例连接到该 elb。然后运行脚本(powershell 或 cli)以从 elb 的离开维护实例中删除 Web 实例(ec2)。

这样我们在部署过程中切换到维护实例。

在我们的例子中,我们有两个 elb,一个用于外部,另一个用于内部。在此过程中,我们的内部 elb 不会更新,这也是我们完成产品部署后冒烟测试的方式。测试完成后,我们运行另一个脚本将 Web 实例附加回 elb 并删除维护堆栈。

于 2017-01-20T04:03:57.903 回答