如何在 AWS 中使用 Terraform 实施蓝/绿部署而不损失容量

Posted

技术标签:

【中文标题】如何在 AWS 中使用 Terraform 实施蓝/绿部署而不损失容量【英文标题】:How to implement blue/green deployments in AWS with Terraform without losing capacity 【发布时间】:2018-11-27 15:20:20 【问题描述】:

我看过多篇讨论蓝/绿部署的文章,它们始终涉及强制重新启动启动配置和自动缩放组。例如:

https://groups.google.com/forum/#!msg/terraform-tool/7Gdhv1OAc80/iNQ93riiLwAJ

除了将 ASG 的所需容量重置为默认值外,这通常效果很好。因此,如果我的集群负载不足,那么容量会突然下降。

我的问题是:有没有办法在不损失容量的情况下执行 Terraform 蓝/绿部署?

【问题讨论】:

【参考方案1】:

对此我没有完整的纯 terraform 解决方案。

我的方法是运行一个小脚本来获取当前所需的容量,设置一个变量,然后在 asg 中使用该变量。

handle-desired-capacity:
    @echo "Handling current desired capacity"
    @echo "---------------------------------"
    @if [ "$(env)" == "" ]; then \
        echo "Cannot continue without an environment"; \
        exit -1; \
    fi
    $(eval DESIRED_CAPACITY := $(shell aws autoscaling describe-auto-scaling-groups --profile $(env) | jq -SMc '.AutoScalingGroups[] | select((.Tags[]|select(.Key=="Name")|.Value) | match("prod-asg-app")).DesiredCapacity'))
    @if [ "$(DESIRED_CAPACITY)" == '' ]; then \
        echo Could not determine desired capacity.; \
        exit -1; \
    fi
    @if [ "$(DESIRED_CAPACITY)" -lt 2 -o "$(DESIRED_CAPACITY)" -gt 10 ]; then \
        echo Can only deploy between 2 and 10 instances.; \
        exit -1; \
    fi
    @echo "Desired Capacity is $(DESIRED_CAPACITY)"
    @sed -i.bak 's!desired_capacity = [0-9]*!desired_capacity = $(DESIRED_CAPACITY)!g' $(env)/terraform.tfvars
    @rm -f $(env)/terraform.tfvars.bak
    @echo ""

显然,这很丑陋,但它确实有效。

我想看看我们是否可以将 ASG 的名称作为远程状态的输出,然后我可以在下一次运行时使用它来获得所需的容量,但我很难理解这一点很有用。

【讨论】:

OOI,限制为 2 到 10 的原因是我们永远不想运行 1 个实例(我们运行多可用区)和 10 个,因为如果负载超过 10,我们最多只能运行 20 个同一类的实例,所以如果它很忙,不要尝试替换任何东西。显然,您可以根据自己的要求进行调整。【参考方案2】:

作为第二个答案,我将 AWSCLI + jq 包装到 Terraform 模块中。

https://registry.terraform.io/modules/digitickets/cli/aws/latest

module "current_desired_capacity" 
  source            = "digitickets/cli/aws"
  assume_role_arn   = "arn:aws:iam::$data.aws_caller_identity.current.account_id:role/OrganizationAccountAccessRole"
  role_session_name = "GettingDesiredCapacityFor$var.environment"
  aws_cli_commands  = ["autoscaling", "describe-auto-scaling-groups"]
  aws_cli_query     = "AutoScalingGroups[?Tags[?Key==`Name`]|[?Value==`digitickets-$var.environment-asg-app`]]|[0].DesiredCapacity"

module.current_desired_capacity.result 为您提供您在 aws_cli_query 中指定的 ASG 当前所需的容量。

再一次,这很丑陋,但它的形式化意味着您现在可以从 AWS 访问大量在 Terraform 中尚不可用的属性。

这是一个温和的技巧。没有资源被传递,它纯粹是为了单个标量值而编写的,所以请小心使用它。

作为作者,我很乐意通过 GitHub 问题页面 https://github.com/digitickets/terraform-aws-cli/issues 解释有关此的任何内容

【讨论】:

以上是关于如何在 AWS 中使用 Terraform 实施蓝/绿部署而不损失容量的主要内容,如果未能解决你的问题,请参考以下文章

terraform 中的 aws_config_remediation_configuration 资源中缺少参数

如何在 local-exec 配置程序中从 terraform 继承 aws 凭据

如何使用 Terraform 在 AWS SSM 参数中存储三元素元组?

如何在 terraform 中使用新引入的 aws_cloudfront_cache_policy 资源

如何在 terraform 路由表中引用 AWS 本地前缀列表?

如何 Terraform 创建和验证 AWS 证书