如何扩容 Terraformed EKS 节点的体积

How to upsize volume of Terraformed EKS node

我们已经使用 Terraform 近一年来管理 AWS 上的各种资源,从堡垒主机到 VPC、RDS 和 EKS。

我们有时真的对 EKS 模块感到困惑。然而,这可能是由于缺乏理解(和文档),所以这里是:

问题:升迁磁盘(卷)


module "eks" {
  source  = "terraform-aws-modules/eks/aws"
  version = "12.2.0"

  cluster_name    = local.cluster_name
  cluster_version = "1.19"
  subnets         = module.vpc.private_subnets

  #...

  node_groups = {
    first = {
      desired_capacity = 1
      max_capacity     = 5
      min_capacity     = 1

      instance_type = "m5.large"
    }
  }

我认为这个 (dev) k8s 集群节点的默认值可以很容易地成为默认的 20GB,但它很快就会被填满,所以我知道想将 disk_size 更改为 40GB。

=> 我想我可以添加 disk_size=40 之类的东西然后完成。

terraform plan 告诉我需要更换节点。这是一个 1 节点集群,所以不好。即使是我也不想排水节点。这就是为什么我认为我们正在使用像 EKS 这样的托管 k8。

预期行为: 因为这些是弹性卷,所以我应该可以放大但不能缩小,为什么这不可能?我可以定义。从 AWS UI.

当然有一个有点可怕的警告:

您确定要修改音量 vol-xx 吗? 性能更改可能需要一些时间才能完全生效。 您可能需要扩展卷上的 OS 文件系统以使用任何新分配的 space

但我可以使用提供的文档来解决这个问题:https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/recognize-expanded-volume-linux.html?icmpid=docs_ec2_console

关于如何增加存储空间的任何指南?如果我使用 UI 这样做但不触摸 Terraform,那么我的 EKS 状态将是 nuked/out 同步。

据我所知,目前无法在不使用 Terraform 重新创建节点的情况下调整 EKS 节点卷的大小。

幸运的是,有一个解决方法:正如您还发现的那样,您可以通过 AWS UI 或 API 直接更改节点大小。之后要更新您的状态文件,您可以 运行 terraform apply -refresh-only 下载最新数据(例如,增加的节点卷大小)。之后,您可以更改 Terraform 计划中的节点大小,以保持计划和状态同步。

对于未来,您可能希望考虑迁移到临时节点,因为(至少我的)经验表明您会不时对集群和节点进行不可预见的更改。已经考虑到可更换节点的计划将使这些更改变得更加容易。

通过使用 terraform-aws-eks terraform 模块,您实际上遵循了“临时节点”范例,因为对于创建实例的两种方式 (self-managed workers or managed node groups),该模块正在创建创建 EC2 实例的自动缩放组从启动模板中退出。

ASG 和 Launch Templates 是专门设计的,让您不再关心具体的节点,而只关心节点的数量。这意味着要更新节点,您只需将它们替换为新节点,这将使用新更新的启动模板(例如,使用更多 GB,或使用新更新的 AMI,或新实例类型)。

这称为“滚动更新”,可以手动完成(添加新实例,然后耗尽节点,然后删除旧节点),使用脚本(参见:eks-rolling-update in github by Hellofresh),或者如果您使用 AWS 托管节点(您在指定“node_groups”时实际使用的节点),也可以自动完成,这就是为什么如果您添加更多 GB,它将替换该节点当你 运行 申请时自动)。

这种范式在云中操作 Kubernetes 时最为常见(在使用虚拟化时在本地数据中心也很常见)。

选项 1) 自我管理员工

对于自我管理的节点,当您更改 disk_size 或 instance_type 等参数时,它会更改启动模板。它将更新 $latest 版本标签,这通常是 ASG 指向的位置(尽管可以更改)。这意味着旧实例不会看到任何变化,但新实例将具有更新的配置。

如果你想改变现有的实例,你实际上是想用新的实例替换它们。这就是这种临时节点范例。

您可以一个接一个地耗尽旧实例,同时增加 ASG 上 desired_instances 的数量,或者让集群自动缩放器完成这项工作。或者,您可以使用自动脚本为每个 ASG 执行此操作:https://github.com/hellofresh/eks-rolling-update

在 terraform_aws_eks 模块中,您可以使用 worker_groups 或 worker_groups_launch_template(推荐)字段创建自我管理的工作人员

选项 2) 托管节点

托管节点是 EKS 特定的功能。您对它们的配置非常相似,但实际上,它是一种抽象,AWS 将创建实际的底层 ASG。

您可以指定 ASG 使用的启动模板及其版本。可以在托管节点级别(即 AMI 和 instance_types)和启动模板(如果未在前者中指定)指定一些配置。

节点组级别配置或启动模板版本的任何更改都将触发自动滚动更新,这将替换所有旧实例。

您可以 delay the rolling update 不指向 $latest 版本(或指向 $default,并且在更改 LT 时不更新 $default 标签)。

在 terraform_aws_eks 模块中,您可以使用 node_groups 字段创建自我管理的工作人员。您还可以使用这些设置:create_launch_template=true 和 set_instance_types_on_lt=true 如果您希望模块为您创建 LT(或者您可以不使用它,或将引用传递给一);并在上述指定的 LT 上设置 instance_type。

但行为类似于工人群体。在任何情况下,您都不会更改现有实例。您只能手动更改它们。

不过,还有一个选择:手动方式

您可以使用 EKS 模块创建控制平面,然后使用 terraform (https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/instance) 中的常规 EC2 资源创建一个或多个(使用计数或 for_each)实例。

如果您使用 aws_instance 资源创建实例,那么 Terraform 将在允许任何更改(即增加根卷 GB 或实例类型)时修补这些实例(就地更新);而更改 AMI 将强制更换)。

唯一棘手的部分是您需要配置 cloud-init 脚本以使实例加入集群(使用 self/managed 节点组时 EKS 模块会自动完成此操作)。

不过,这是很有可能的,你可以从模块中借用脚本,将其插入到aws_instance的user_data字段中(https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/instance#user_data)

在这种情况下(在谈论 disk_size 时),您仍然需要手动(通过 SSH,或通过 运行使用 terraform 的 hacky exec)来修补 XFS 文件系统所以它看到增加的磁盘 space.

另一种选择:考虑 Kubernetes 存储

也就是说,对于某些用例,还有另一种选择。如果你想增加这些实例的磁盘 space 因为你的应用程序之一使用 hostPath,那么你可能会使用使用 EBS CSI 驱动程序的 kubernetes 内置存储解决方案。

例如,我在 Kubernetes 中管理一个 ElasticSearch 集群(并使用 helm 模块从 terraform 部署它),它使用动态存储配置来请求 EBS 卷(注意性能是一样的,因为 root 和这个其他卷是 EBS 卷)。 EBS CSI 驱动支持卷扩展,所以我可以通过改变一个 terraform 变量来增加这个磁盘。


总而言之,我不推荐 aws_instance 方式,除非您了解它并且确定您真的想要它。在某些情况下可能有意义,但绝对不常见