使用 Tofu/Terraform 和 SAM 在 AWS 中实现零停机部署

2025-06-08

使用 Tofu/Terraform 和 SAM 在 AWS 中实现零停机部署

我还记得在应用程序部署期间,我们必须设置标志并显示维护页面的日子。为了尽量减少对用户的影响,我们经常在午夜或流量较低的时段部署应用程序,这导致了糟糕的开发者体验。如今,作为客户,我们期望始终获得无缝的用户体验

为何要进行零停机部署

实现零停机部署已成为现代应用程序的必备条件。如今,我们正处于一个软件交付时代,停机时间应最小化,延迟也应降低。作为客户,我们的期望值也随之提升。如果应用程序无法正常运行,我们会认为它不可靠,并很可能会放弃使用它。🤑

今天,我想介绍一些实现零停机部署并与客户建立信任的策略。

GitHub 代码

  • 使用实例刷新来更新 Auto Scaling 组中的实例 (OpenTofu)
  • 不可变基础设施 + 可变应用程序(Terraform + Ansible)
  • 实施蓝/绿部署
  • 金丝雀部署(逐步部署无服务器应用程序)

我们的目标是避免创建不可靠的应用程序,而是采用云原生方法。

停机时间

让我们深入研究这些策略:

使用实例刷新来更新 Auto Scaling 组中的实例 (OpenTofu)

在这个例子中,我们使用OpenTofu。我想强调的是,开源软件非常有益——它们的质量非常高,让我们能够利用众多资源,并在优秀工程师开发的代码基础上进行构建。我们可以从这类项目中学到很多东西。这也是为什么这里的代码是多种思想的综合体,任何想要学习和复用它的人都可以使用它的原因之一。

Terraform 的未来必须是开放的

助理秘书长

我们需要定义三个重要属性:min_elb_capacitylifecycleinstance_refresh。这些属性将用于以下目的:

  • min_elb_capacity:此属性确保仅在至少一些实例通过健康检查后,部署才被视为完成。

  • lifecycle:此属性有助于防止在创建新资源后删除先前的资源。

  • instance_refresh:此属性定义了对自动扩展组 (ASG) 进行更改的策略。



resource "aws_autoscaling_group" "zdd" {

  name                = "${var.cluster_name}-${aws_launch_template.zdd.name}"
  vpc_zone_identifier = var.subnets
  target_group_arns = [aws_lb_target_group.asg.arn]
  health_check_type   = "ELB"

  min_elb_capacity = var.min_size

  min_size = var.min_size
  max_size = var.max_size

  lifecycle {
    create_before_destroy = true
  }

  # Use instance refresh to roll out changes to the ASG
  instance_refresh {
    strategy = "Rolling"
    preferences {
      min_healthy_percentage = 50
    }
  }

  launch_template {
    id      = aws_launch_template.zdd.id
    version = "$Latest"
  }

  tag {
    key                 = "Name"
    value               = var.cluster_name
    propagate_at_launch = true
  }

}



Enter fullscreen mode Exit fullscreen mode

结果是 API 能够可靠地返回数据并且不会变得不可用。

部署示例

在这个例子中,我们依赖于不可变的基础设施,因此每当发生变化时,我们都需要打包并创建一个新的 AMI。



packer build sample-app.pkr.hcl
tofu apply 


Enter fullscreen mode Exit fullscreen mode

不可变基础设施 + 可变应用程序(Terraform + Ansible)

尽管我们可以使用 Terraform 或 CloudFormation 等配置工具完成所有工作,但有时最好将它们与 Ansible 等配置管理工具一起使用。Ansible 旨在管理和安装服务器上的软件,为处理零停机部署提供了一种有用的方法。

Ansible

我们可以使用 Nginx 来服务我们的应用程序



  - name: Install Nginx
    hosts: all
    become: true

    tasks:
    - name: Install Nginx
      apt:
        name: nginx
        state: present

    - name: Add index page
      template:
        src: index.html
        dest: /var/www/html/index.html

    - name: Start Nginx
      service:
        name: nginx
        state: started



Enter fullscreen mode Exit fullscreen mode

结果是可以使用 Ansible 命令轻松更新应用程序,从而实现零停机时间。

Ansible 更新

蓝绿部署

这种方法的理念是让两个环境运行应用程序的不同版本。您可以逐步部署部分更改,也可以一次性完成所有更改。蓝色环境负责处理来自生产用户的流量,而绿色环境则托管应用程序的新版本,您可以在其中执行测试和验证。绿色环境测试完成后,您可以将流量重定向到绿色环境。如果遇到任何问题,可以通过将流量重定向到蓝色环境来回滚。

蓝绿色

AWS 和 Terraform 最令人赞叹的一点就是它们的社区。正如您所见,我们可以利用公共模块来编写应用程序。在这种情况下,我们可以使用标志在环境之间切换。每次更新应用程序时,新版本都会保持空闲状态并可用,而之前的活跃服务器则会继续接收流量,直到我们确信空闲服务器正常运行并进行切换。



provider "aws" {
region = "us-east-2"
}

variable "production" {
default = "green"
}

module "base" {
source = "terraform-in-action/aws/bluegreen//modules/base"
production = var.production
}

module "green" {
source = "terraform-in-action/aws/bluegreen//modules/autoscaling"
app_version = "v1.0"
label = "green"
base = module.base
}

module "blue" {
source = "terraform-in-action/aws/bluegreen//modules/autoscaling"
app_version = "v2.0"
label = "blue"
base = module.base
}

output "lb_dns_name" {
value = module.base.lb_dns_name
}

Enter fullscreen mode Exit fullscreen mode




金丝雀部署(逐步部署无服务器应用程序)

此策略涉及逐步将软件发布给一小部分用户。通过这种方式,我们可以验证一切是否按预期运行,并持续提高能够使用最新版本应用程序的用户比例。如果发现问题,我们可以轻松地将新版本的流量降至零,从而实现回滚。

借助 SAM,可以使用 CloudWatch 警报开箱即用地执行流量验证和回滚。当逻辑更改可能存在风险时,此功能非常方便。

CodeDeploy

金丝雀部署更注重人员而非服务器。在这种情况下,我们关注的是体验新版 Lambda 函数的用户数量。我们可以监控应用程序,并在需要时自动回滚。请记住,此过程更安全,但速度较慢。以下是 AWS SAM 中可用的选项:

  • Canary10PercentMinutes
  • 每分钟线性10%
  • 一次性


Resources:
AWSCommunityLambda:
Type: AWS::Serverless::Function
Properties:
Handler: index.py
Runtime: python3.11
CodeUri: functions/api/handler
AutoPublishAlias: live
DeploymentPreference:
Type: Canary10Percent10Minutes
Alarms:
- !Ref AliasErrorMetricGreaterThanZeroAlarm
- !Ref LatestVersionErrorMetricGreaterThanZeroAlarm
Hooks:
PostTraffic: !Ref PostTrafficLambdaFunction

Enter fullscreen mode Exit fullscreen mode




结论

  • 零停机部署是建立对高度动态的云原生应用程序世界的信任的关键。
  • SAM 具有强大的选项,可以以安全的方式部署基础设施。
  • Ansible 可以与 Terraform 结合使用,通过仅更新应用程序来减少爆炸半径,从而创造更好的 DevOps 体验。
  • 不可变的基础设施通常是一种更好的方法,因为您可以一致地部署相同的配置,而不是应用了许多更改的服务器,这可能会导致配置差异。
  • 不可变的基础设施也有缺点,例如需要从服务器模板重建图像并重新部署以进行简单的更改。
  • OpenTofu 是部署基础设施的绝佳选择。我之前没有尝试过,但看起来社区做得不错,而且新版本会包含越来越多 Terraform 尚未支持的功能。

参考

  1. Terraform 在行动- 实施 Terraform 的实际用途和策略,Terraform 是一种用于构建、更改和管理基础设施的工具。
  2. Terraform:启动并运行- Terraform 的友好介绍,包括其复杂的概念、大量示例以及如何开始使用它。
  3. 勤奋工作

不久前,生产部署还是一项繁琐的任务,需要多方协作。如今,我们拥有丰富的开源软件和以开发者为中心的工具,这些工具强调不变性、自动化、提升生产力的 AI 以及强大的 IDE。

现在是成为一名工程师并通过软件为社会创造价值的最佳时机。

如果您喜欢这些文章,请访问我的博客jorgetovar.dev

链接:https://dev.to/aws-builders/zero-downtime-deployment-in-aws-with-tofuterraform-and-sam-14d6
PREV
AWS 精英们对 AWS re:Invent 2020 公告的反应 🤯
NEXT
Mono-Lambda 与单函数 API 的区别、原因和时机