广告位 · 页头(后台-模块管理-新建模块后替换此区域)

AWS CloudFront Blue/Green Deployments:零停机部署新版本

传统CDN更新方式往往是在现有源站上直接覆盖文件,然后等待缓存过期。这种做法风险很高:一旦新版出现问题,边缘节点上可能已经缓存了新内容,回滚时还需要再次等待缓存失效,用户会长时间暴露在故障中。蓝绿部署则从根本上改变了发布策略——为每个版本准备独立的环境,新旧版本并存,通过流量切换完成上线。在AWS CloudFront中,我们可以利用两个源站和一段轻量级边缘函数,把流量按需导向蓝环境或绿环境,实现秒级切换和即时回滚。

AWS CloudFront Blue/Green Deployments:零停机部署新版本

理解CloudFront中的蓝绿部署架构

蓝绿部署的核心思想是准备两套完全相同的生产环境:一套是当前正在服务的“蓝”环境,另一套是部署了新版本的“绿”环境。当绿环境通过测试后,通过路由层把用户流量从蓝切换到绿,完成发布。在CloudFront中,这个路由层可以由CloudFront自身的行为配置结合边缘函数来实现。最典型的做法是创建两个源站(Origin),分别指向存放旧版本和新版本的对象存储桶、负载均衡器或自定义源。然后使用CloudFront Functions或Lambda@Edge,在请求到达边缘节点时根据特定条件(如请求头、Cookie或路径)决定将请求转发到哪个源站。

这种架构的优势在于两个环境完全隔离,互不影响。蓝环境保持原样,绿环境可以自由部署和测试。切换流量时,只需修改函数逻辑或调整路由规则,而不需要触碰源站内容。CloudFront的全球边缘网络会即时应用新的路由策略,用户几乎感受不到变更。此外,回滚也非常简单——把流量切回蓝环境即可,无需重新部署旧版本,因为蓝环境从未被销毁。

要实现这种效果,通常需要两个关键组件。第一是合理的路径规划:如果新版和旧版使用完全相同的URL路径,那么必须依靠请求头或Cookie区分版本;如果允许不同的路径前缀(如/v2/),则可以仅通过CloudFront的缓存行为配置完成路由,不需要函数。第二是边缘函数:当需要根据请求头动态选择源站时,CloudFront Functions是一个轻量且低延迟的选择,适合简单路由;Lambda@Edge功能更强,但成本稍高、冷启动更明显。下面是一段CloudFront Functions的示例代码,它根据请求头X-Deployment的值决定使用哪个源站:

function handler(event) {
    var request = event.request;
    var headers = request.headers;
    // 默认使用蓝环境(旧版本)
    var origin = "blue-origin";
    if (headers["x-deployment"] && headers["x-deployment"].value === "green") {
        origin = "green-origin";
    }
    request.origin = {
        custom: {
            domainName: origin + ".ipipp.com",
            port: 443,
            protocol: "https",
            path: "",
            sslProtocols: ["TLSv1.2"],
            readTimeout: 5,
            keepaliveTimeout: 5,
            customHeaders: {}
        }
    };
    return request;
}

这段代码假设蓝绿环境的源站域名分别是blue-origin.ipipp.com和green-origin.ipipp.com。实际使用时,这两个域名需要已在CloudFront中配置为源站。函数会在请求进入缓存之前运行,因此同一个对象的不同版本请求会被导向不同的源站,并由CloudFront分别缓存,不会互相污染。

实施蓝绿部署的关键步骤

将蓝绿部署落地到CloudFront需要几个明确的操作步骤,每一步都有对应的AWS服务和配置方式。首先,准备两套源站。对于静态网站,最简单的方式是创建两个S3桶,分别存放旧版和新版文件,并且启用静态网站托管或者通过CloudFront的OAI(Origin Access Identity)访问。对于动态应用,则可以使用两个独立的ALB(应用负载均衡器)或EC2自动伸缩组,确保它们能独立提供完整服务。

第二步是在CloudFront分配中创建对应的源站。进入CloudFront控制台,选择目标分配,在“源站”选项卡中添加两个源站,分别命名为blue和green,并配置正确的域名、协议和路径。需要注意的是,如果两个源站使用相同的域名但不同路径,则不能算作独立源站,必须使用不同子域名或不同服务端点。

第三步是配置缓存行为。默认情况下,CloudFront会把所有路径的请求转发到默认源站(通常是第一个创建的源站)。我们需要定义至少一个缓存行为,将其路径模式设置为“*”或特定路径,然后配合边缘函数实现动态源站选择。也可以创建多个路径模式,例如将/v1/*指向蓝源站,将/v2/*指向绿源站,这样连函数都不需要,但需要对应用进行路径改造。

第四步是编写并关联CloudFront Functions。函数需要返回request对象,并设置request.origin字段。在CloudFront控制台的“函数”页面创建函数,编写代码后发布,并在缓存行为的“函数关联”中选择“源站请求”阶段关联该函数。这样每个请求在离开边缘节点前往源站之前都会经过函数处理。

第五步是测试。发布绿环境后,不要立即切换所有流量。可以使用curl命令或Postman发送带有X-Deployment: green请求头的请求,确认返回的是新版本内容。同时观察CloudFront日志,确保请求确实命中了绿源站。这一步至关重要,因为它可以在不实际影响普通用户的情况下验证新环境的正确性。

第六步是切换流量。当绿环境验证通过后,有两种方式切换:一是修改函数逻辑,将默认源站从blue改为green;二是使用权重路由,逐步增加流向绿环境的流量比例。CloudFront Functions可以轻松实现权重路由,例如根据请求头中的随机数或会话ID的哈希值决定源站。切换完成后,普通用户就会开始访问新版本。

最后一步是监控和回滚。切换后要密切关注CloudFront的5xx错误率、源站延迟和业务指标。如果出现异常,可以立即修改函数把默认源站切回blue,或者把权重调回0。由于两个环境都还在,回滚在一分钟内即可全局生效。待一切稳定后,蓝环境可以保留一段时间作为备份,或者用于下一次部署的“绿”环境。

注意事项与最佳实践

缓存是蓝绿部署中最容易踩坑的地方。即使流量已经切换到绿环境,边缘节点上可能仍缓存着来自蓝环境的旧内容。如果对象的TTL很长,用户可能继续收到旧版本。解决这个问题的常用方法是采用版本化URL:在每个版本的资源路径中加入版本号(如/assets/v2/main.js),这样新旧版本的文件路径不同,根本不会发生缓存冲突。如果无法版本化,那么切换流量前需要缩短相关对象的TTL,或者主动执行缓存失效操作,但要注意CloudFront的失效请求有配额限制。

蓝绿环境的管理应当尽量自动化。每次部署时,使用基础设施即代码工具(如Terraform或CloudFormation)创建新的绿环境,并在切换完成后销毁旧的蓝环境。这样既能保证环境一致性,也能避免手动操作带来的错误。同时,将蓝绿切换步骤集成到CI/CD流水线中,例如在GitLab CI或GitHub Actions中增加一个“promote”阶段,通过脚本更新CloudFront Functions或修改CloudFormation参数来完成切换。

成本方面,双环境会带来额外的存储和计算开销,但对于大多数业务来说这部分成本微乎其微,换来的是极低的风险和极高的发布信心。此外,安全策略也要考虑:绿环境在测试期间不应该被普通用户访问,通常需要配合请求头验证或IP白名单,避免未完成测试的版本泄露。最后,定期演练回滚过程,确保团队熟悉操作,当真正需要回滚时能够快速执行。

广告位 · 文章底部(后台-模块管理替换此区域)