亚马逊AWS官方博客

借助 Amazon ECS 全新的内置蓝绿部署功能,加速安全的软件发布进程

尽管容器彻底改变了开发团队打包和部署应用程序的方式,但这些团队仍需谨慎监控发布过程并构建自定义工具来降低部署风险,这就会拖慢发布速度。在大规模场景下,开发团队将大量宝贵时间耗费在构建和维护千篇一律的部署工具上,而不是进行业务创新。

从现在起,您可以借助 Amazon Elastic Container Service(Amazon ECS)中内置的蓝绿部署功能,实现更安全、更一致的应用程序部署。这项新功能无需构建自定义部署工具,同时让您能够凭借回滚功能,自信地提高软件更新的发布频率。

以下是在 Amazon ECS 控制台中启用内置蓝绿部署功能的方法。

在现有的“蓝色”环境继续处理实时流量的同时,您可以创建新的“绿色”应用程序环境。对绿色环境进行全面监控和测试后,再将实时流量从蓝色环境路由到绿色环境。借助这项能力,Amazon ECS 现在能够提供能让容器化应用程序的部署更安全、更可靠的内置功能。

下方的图表描述了蓝绿部署如何将应用程序流量从蓝色环境转移到绿色环境。您可以在 Amazon ECS 蓝绿服务部署工作流页面了解更多信息。

Amazon ECS 会协调整个工作流程,同时提供事件钩子,以便在路由生产流量前,通过模拟流量验证新版本。您可以在生产环境中验证新的软件版本,之后再向最终用户开放;如果出现问题,还能近乎即时地回滚。由于此功能直接内置在 Amazon ECS 中,因此您只需更新配置就能添加这些安全保护措施,而无需构建任何自定义工具。

入门

接下来,我将为您演示如何为 ECS 服务配置和使用蓝绿部署。在此之前,我需要完成一些设置步骤,包括配置 AWS Identity and Access Management(IAM)角色,相关内容可在 Amazon ECS 蓝绿部署所需资源文档页面中找到。

在本次演示中,我将采用蓝绿策略部署应用程序的新版本,以最大程度降低风险。首先,我需要将 ECS 服务配置为使用蓝绿部署。这可以通过 ECS 控制台、AWS 命令行界面(AWS CLI)或基础设施即代码来完成。

通过 Amazon ECS 控制台,我像往常一样创建一个新服务并进行配置:

在“部署选项”部分,我选择 ECS 作为部署控制器类型,然后选择蓝绿作为部署策略烘焙时间是指生产流量转移到绿色环境后,可立即回滚到蓝色环境的时间。烘焙时间结束后,蓝色任务将被移除。

我们还引入了部署生命周期挂钩。这是一种事件驱动的机制,可用于扩展部署工作流。我可以选择要用作部署生命周期挂钩的 AWS Lambda 函数。该 Lambda 函数可以执行所需的业务逻辑,但必须返回钩子状态。

在蓝绿部署过程中,Amazon ECS 支持以下生命周期挂钩。您可以在部署生命周期阶段页面了解有关各个阶段的更多信息。

  • 纵向扩展前
  • 纵向扩展后
  • 生产流量转移
  • 测试流量转移
  • 生产流量转移后
  • 测试流量转移后

对于我的应用程序,我希望在测试流量转移完成、绿色服务处理所有测试流量时进行测试。由于此时没有最终用户流量,在此阶段回滚不会对用户造成任何影响。因此,测试流量转移后阶段非常适合我的使用场景,我可以先通过 Lambda 函数进行测试。

暂时转换一下话题,让我们重点看看我用来在部署继续之前验证部署的 Lambda 函数。在作为部署生命周期挂钩的 Lambda 函数中,我可以执行任何业务逻辑,例如模拟测试、调用其他 API 或查询指标。

在 Lambda 函数中,我必须返回一个 hookStatushookStatus 可以是 SUCCESSFUL(成功),此时流程将进入下一步;如果状态为 FAILED(失败),则会回滚到蓝色部署;如果是 IN_PROGRESS(进行中),Amazon ECS 将在 30 秒后重试该 Lambda 函数。

在下面的示例中,我使用了一个 Lambda 函数来设置验证,该函数通过文件上传来执行应用程序的测试套件。

import json
import urllib3
import logging
import base64
import os

# Configure logging
logger = logging.getLogger()
logger.setLevel(logging.DEBUG)

# Initialize HTTP client
http = urllib3.PoolManager()

def lambda_handler(event, context):
    """
    Validation hook that tests the green environment with file upload
    """
    logger.info(f"Event: {json.dumps(event)}")
    logger.info(f"Context: {context}")
    
    try:
        # In a real scenario, you would construct the test endpoint URL
        test_endpoint = os.getenv("APP_URL")
        
        # Create a test file for upload
        test_file_content = "This is a test file for deployment validation"
        test_file_data = test_file_content.encode('utf-8')
        
        # Prepare multipart form data for file upload
        fields = {
            'file': ('test.txt', test_file_data, 'text/plain'),
            'description': 'Deployment validation test file'
        }
        
        # Send POST request with file upload to /process endpoint
        response = http.request(
            'POST',
            test_endpoint,
            fields=fields,
            timeout=30
        )
        
        logger.info(f"POST /process response status: {response.status}")
        
        # Check if response has OK status code (200-299 range)
        if 200 <= response.status < 300:
            logger.info("File upload test passed - received OK status code")
            return {
                "hookStatus": "SUCCEEDED"
            }
        else:
            logger.error(f"File upload test failed - status code: {response.status}")
            return {
                "hookStatus": "FAILED"
            }
            
    except Exception as error:
        logger.error(f"File upload test failed: {str(error)}")
        return {
            "hookStatus": "FAILED"
        }

当部署到达与钩子关联的生命周期阶段时,Amazon ECS 会自动调用带有部署上下文的 Lambda 函数。我的验证函数可以对绿色版本运行全面测试 — 检查应用程序运行状况、运行集成测试或验证性能指标。然后,该函数会向 ECS 发出信号,指示是继续部署还是中止部署。

由于我选择了蓝绿部署策略,因此还需要配置负载均衡器和/或 Amazon ECS Service Connect。在负载均衡部分,我选择了我的应用程序负载均衡器

侦听器部分,我使用端口 80 上的现有侦听器,并选择了两个目标组

完成满意的配置后,我创建了服务,然后等待 ECS 配置我的新服务。

测试蓝绿部署

现在,是时候测试我的蓝绿部署了。在本次测试中,Amazon ECS 会在测试流量转移完成后触发我的 Lambda 函数。在这种情况下,我的 Lambda 函数会返回 FAILED(失败),因为它要向我的应用程序执行文件上传操作,而我的应用程序不具备此功能。

我更新了服务,并勾选了强制执行新部署,因为我知道,如果检测到失败,蓝绿部署功能会进行回滚。我选择这个选项是因为我没有修改任务定义,但仍需要触发新的部署。

在此阶段,蓝色环境和绿色环境都在运行,绿色版本处理所有测试流量。同时,根据我的 Lambda 函数的 Amazon CloudWatch Logs,我还看到部署生命周期挂钩按预期工作,并发出了以下有效载荷:

[INFO]	2025-07-10T13:15:39.018Z	67d9b03e-12da-4fab-920d-9887d264308e	Event: 
{
    "executionDetails": {
        "testTrafficWeights": {},
        "productionTrafficWeights": {},
        "serviceArn": "arn:aws:ecs:us-west-2:123:service/EcsBlueGreenCluster/nginxBGservice",
        "targetServiceRevisionArn": "arn:aws:ecs:us-west-2:123:service-revision/EcsBlueGreenCluster/nginxBGservice/9386398427419951854"
    },
    "executionId": "a635edb5-a66b-4f44-bf3f-fcee4b3641a5",
    "lifecycleStage": "POST_TEST_TRAFFIC_SHIFT",
    "resourceArn": "arn:aws:ecs:us-west-2:123:service-deployment/EcsBlueGreenCluster/nginxBGservice/TFX5sH9q9XDboDTOv0rIt"
}

正如预期的那样,我的 AWS Lambda 函数返回的 hookStatusFAILED(失败),因为测试执行失败。

[ERROR]	2025-07-10T13:18:43.392Z	67d9b03e-12da-4fab-920d-9887d264308e	File upload test failed: HTTPConnectionPool(host='xyz.us-west-2.elb.amazonaws.com', port=80): Max retries exceeded with url: / (Caused by ConnectTimeoutError(<urllib3.connection.HTTPConnection object at 0x7f8036273a80>, 'Connection to xyz.us-west-2.elb.amazonaws.com timed out. (connect timeout=30)'))

由于验证未成功完成,因此 Amazon ECS 尝试回滚到蓝色版本,也就是之前可正常运行的部署版本。我可以通过事件部分的 ECS 事件监控此过程,该部分会详细显示部署进度。

Amazon ECS 成功将部署回滚到之前可正常运行的版本。回滚几乎是即时的,因为蓝色版本仍在运行,随时可以接收生产流量。在此过程中,不会对终端用户造成任何影响,因为生产流量从未切换到新的应用程序版本 — ECS 只是将测试流量回滚到原来的稳定版本。这样可以消除传统滚动部署中常见的部署停机时间问题。

我还可以在上次部署部分查看回滚状态。

在整个测试过程中,我发现蓝绿部署策略具有一致且可预测的行为。此外,部署生命周期挂钩为控制部署行为提供了更大的灵活性。每个服务版本都维护不可变的配置,包括任务定义、负载均衡器设置和 Service Connect 配置。这意味着回滚会精确恢复到之前运行的相同环境。

需要了解的其他事项

请注意以下几点:

  • 定价 — 蓝绿部署功能已包含在 Amazon ECS 中,不额外收费。您只需为部署过程中使用的计算资源付费。
  • 可用性 — 此功能在所有 AWS 商业区域均可用。

通过在 Amazon ECS 控制台中更新您的 Amazon ECS 服务配置,开始使用蓝绿部署。

祝大家部署快乐!
Donnie


*前述特定亚马逊云科技生成式人工智能相关的服务目前在亚马逊云科技海外区域可用。亚马逊云科技中国区域相关云服务由西云数据和光环新网运营,具体信息以中国区域官网为准。