【问题标题】:Terraform & OpenStack - Zero downtime flavor changeTerraform 和 OpenStack - 零停机时间变化
【发布时间】:2020-04-16 08:22:56
【问题描述】:

我正在使用openstack_compute_instance_v2 在 OpenStack 中创建实例。存在生命周期设置create_before_destroy = true。它工作得很好,以防我例如更改需要替换实例的卷大小。

但是。当我进行风味更改时,可以使用 OpenStack 中的resize instance 选项来完成,它就是这样做的,但不关心任何 HA。在调整大小完成之前,集群中的所有实例会在 20-30 秒内不可用。

如何改变这种行为?

一些设置,如来自 Ansible 的 serial,或其他一些选项会派上用场。但我什么也找不到。 任何能让我说“至少有一半的实例需要始终在线”的解决方案。

Terraform 版本:12.20。

TF 计划:https://pastebin.com/ECfWYYX3

【问题讨论】:

  • 进行此更改后,计划输出是什么样的?你能用一些 Terraform 代码创建一个minimal reproducible example 吗?
  • 我在问题中包含了 terraform 计划。我可能很难创建最小的可重现示例,因为我们添加了很多东西来简单地使用我们的 openstack 和 gitlab 管道设置。但在计划中,您可以看到有 2 个实例。唯一的变化是味道。而且它们都不能同时使用。

标签: terraform openstack high-availability terraform-provider-openstack


【解决方案1】:

Openstack Terraform 提供者知道它可以通过使用 resize API call 来更新 flavor,而不必销毁实例并重新创建它。

不幸的是,当与 create_before_destroy 生命周期自定义结合使用时,当前没有强制可变事物执行销毁/创建或创建/销毁的生命周期选项,因此您不能轻易强制它替换实例。

在这些情况下,一个选择是找到一个无法就地修改的参数(这些在资源的底层提供程序源代码中的架构上的 ForceNew 标志标记),然后在可变参数也级联对不可变参数的更改。

这里的一个常见示例是在启动模板(与不可变的启动配置相比是可变的)更改时替换 AWS 自动扩展组,这样您就可以立即推出更改,而不是等待 ASG 慢慢替换实例时间。一个简单的示例如下所示:

variable "ami_id" {
  default = "ami-123456"
}

resource "random_pet" "ami_random_name" {
  keepers = {
    # Generate a new pet name each time we switch to a new AMI id
    ami_id = var.ami_id
  }
}

resource "aws_launch_template" "example" {
  name_prefix            = "example-"
  image_id               = var.ami_id
  instance_type          = "t2.small"
  vpc_security_group_ids = ["sg-123456"]
}

resource "aws_autoscaling_group" "example" {
  name                = "${aws_launch_template.example.name}-${random_pet.ami_random_name.id}"
  vpc_zone_identifier = ["subnet-123456"]
  min_size            = 1
  max_size            = 3

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

  lifecycle {
    create_before_destroy = true
  }
}

在上面的示例中,对 AMI 的更改会触发一个新的random pet name,它会更改作为不可变字段的 ASG 名称,因此这会触发替换 ASG。因为 ASG 具有 create_before_destroy 生命周期自定义,所以它会创建一个新的 ASG,等待最少数量的实例通过 EC2 健康检查,然后销毁旧的 ASG。

对于您的情况,您还可以在 openstack_compute_instance_v2 资源上使用 name 参数,因为它也是一个不可变字段。所以一个基本的例子可能是这样的:

variable "flavor_name" {
  default = "FLAVOR_1"
}

resource "random_pet" "flavor_random_name" {
  keepers = {
    # Generate a new pet name each time we switch to a new flavor
    flavor_name = var.flavor_name
  }
}

resource "openstack_compute_instance_v2" "example" {
  name            = "example-${random_pet.flavor_random_name}"
  image_id        = "ad091b52-742f-469e-8f3c-fd81cadf0743"
  flavor_name     = var.flavor_name
  key_pair        = "my_key_pair_name"
  security_groups = ["default"]

  metadata = {
    this = "that"
  }

  network {
    name = "my_network"
  }
}

【讨论】:

  • 好吧,这看起来很有希望,直到我看到它需要对实例进行一些随机命名。这是我做不到的。因为命名模式和格式是确定的,而且许多其他事情取决于实例名称、主机名等。要检查是否有其他不可变项可以用于此。另请阅读有关使用 terraform 的蓝绿和金丝雀部署:hashicorp.com/blog/…
  • 但在我看来,这有点矫枉过正。有一些更简单的东西会很好。此外,使用此解决方案,团队中的每个人都必须记住,您无法更改口味,您需要进行绿蓝部署。
  • 在这种情况下,您可能会被卡住,除非您可以对其他不可变字段(例如用户数据或个性)进行虚假更改。或者是的,您可以通过配置来回翻转或使用增加复杂性的外部编排器在更高级别执行蓝/绿操作。命名模式是否完全固定?您不能出于任何原因为事物添加后缀?
  • 哦。我已经深入研究了 openstack 提供程序源,名称字段也是 ForceNew=false。有道理,因为在 openstack 中,您可以简单地重命名正在运行的实例而不会出现问题。阅读关于个性。但是找不到任何好的解释它的作用/含义以及它是如何工作的。不妨尝试更改 user_data,因为这可能是最简单的方法。
  • 我不使用 OpenStack,所以可能会遗漏一些东西来完成这里的答案。如果您发现某些内容可以直接按照答案的方式进行编辑,我们将不胜感激,因为它将帮助遇到同样问题的其他用户。如果你走完全不同的路线(例如使用条件变量来做蓝绿色或 Terraform 之外的协调器),那么单独的答案会更好。
【解决方案2】:

所以。起初,我已经开始研究如何按照@ydaetskcoR 的建议使用随机实例名称。

Name 不是一个选项,既因为在 openstack 中它是一个可变参数,又因为我有一个无法更改的确定命名模式。

我已经开始寻找可以修改的其他参数,以强制创建而不是修改实例。我发现了personalityhttps://www.terraform.io/docs/providers/openstack/r/compute_instance_v2.html#instance-with-personality

但它也没有工作。主要是因为不再像看起来那样支持个性:

从 2.57 微版本开始,不推荐使用个性文件。使用 metadata 和 user_data 自定义服务器实例。 https://docs.openstack.org/api-ref/compute/

不确定 terraform 是否不支持,或者还有其他问题。但我选择了user_data。我已经在计算实例模块中使用了 user_data,所以添加一些风味数据应该没有问题。

所以,在user_data 中,我添加了以下内容:

  user_data          = "runcmd:\n - echo ${var.host["flavor"]} > /tmp/tf_flavor"

无需随机宠物名称,无需更改实例名称。只需通过在某处添加风味名称来改变他们的“个性”。这确实会在风味发生变化时强制重新创建实例。

所以。而不是简单地:

  # module.instance.openstack_compute_instance_v2.server[0] will be updated in-place
  ~ resource "openstack_compute_instance_v2" "server" {

我现在有:

-/+ destroy and then create replacement
+/- create replacement and then destroy

Terraform will perform the following actions:

  # module.instance.openstack_compute_instance_v2.server[0] must be replaced
+/- resource "openstack_compute_instance_v2" "server" {

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-01-09
    • 2020-04-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-12
    • 1970-01-01
    相关资源
    最近更新 更多