全部产品
Search
文档中心

容器服务 Kubernetes 版 ACK:使用Terraform创建具备自动伸缩功能的节点池

更新时间:Dec 03, 2024

ACK的节点池及托管节点池中的节点默认不具备自动伸缩能力,您也可以通过使用Terraform工具创建开启自动伸缩功能的节点池。本文介绍如何通过Terraform创建开启自动伸缩功能的节点池。

说明

本教程所含示例代码支持一键运行,您可以直接运行代码。一键运行

前提条件

  • 自动伸缩功能依赖弹性伸缩(Auto Scaling,旧称ESS)服务。启动节点自动伸缩前,您需要开通弹性伸缩服务,并完成默认角色授权。具体操作,请参见开通弹性伸缩服务

    说明

    如果您之前已经使用了alicloud_cs_kubernetes_autoscaler组件,默认已开通弹性伸缩服务。

  • 已为系统运维管理 OOS(CloudOps Orchestration Service)服务授权。您可以通过创建AliyunOOSLifecycleHook4CSRole角色,为OOS服务授权。

    1. 单击AliyunOOSLifecycleHook4CSRole

      说明
      • 如果当前账号是阿里云账号,单击AliyunOOSLifecycleHook4CSRole即可授权。

      • 如果当前账号是RAM用户,请先确保对应的阿里云账号已授权AliyunOOSLifecycleHook4CSRole,并为RAM用户授予AliyunRAMReadOnlyAccess系统策略。具体操作,请参见为RAM用户授权

    2. 云资源访问授权页面,单击同意授权

  • 准备Terraform运行环境,您可以选择以下任一方式来使用Terraform。

    • Cloud Shell:阿里云Cloud Shell中预装了Terraform的组件,并已配置好身份凭证,您可直接在Cloud Shell中运行Terraform的命令。适用于低成本、快速、便捷地访问和使用Terraform的场景。

    • 在本地安装和配置Terraform:适用于网络连接较差或需要自定义开发环境的场景。

背景信息

Terraform是一种开源工具,通过Provider来支持新的基础架构,用于安全高效地预览、配置和管理云基础架构和资源。更多信息,请参见Terraform产品介绍

Alibaba Cloud Provider的老版本中,ACK提供了一个名为alicloud_cs_kubernetes_autoscaler的组件。alicloud_cs_kubernetes_autoscaler组件可以实现节点的弹性伸缩,但是其能力受限:

  • 配置复杂,使用成本高。

  • 伸缩的节点都会被放置到默认节点池,自动伸缩的节点未单独维护。

  • 部分配置参数不可更改。

Alibaba Cloud Provider从1.111.0版本开始可通过组件alicloud_cs_kubernetes_node_pool创建开启自动伸缩功能的节点池,优势如下:

  • 配置简单,您只需要配置伸缩组内节点数的上下限。

  • 针对非必须配置,ACK使用默认值的配置,以防误操作带来的基础环境不一致的问题,例如:操作系统镜像。

  • 在ACK控制台中可以直观地观察节点池内节点的变化。

使用的资源

说明

本教程示例包含的部分资源会产生一定费用,请在不需要时及时进行释放或退订。

使用Terraform创建开启自动伸缩功能的节点池

使用过alicloud_cs_kubernetes_autoscaler组件

如果您的集群之前已经使用alicloud_cs_kubernetes_autoscaler组件,在完成上述为当前集群添加弹性伸缩服务授权后,您需要执行以下步骤平滑切换alicloud_cs_kubernetes_autoscaler至alicloud_cs_kubernetes_node_pool,以创建开启自动伸缩功能的节点池。

  1. 修改集群的autoscaler-meta配置项。

    1. 登录容器服务管理控制台,在左侧导航栏选择集群

    2. 集群列表页面,单击目标集群名称,然后在左侧导航栏,选择配置管理 > 配置项

    3. 配置项页面左上角的命名空间下拉框中,选择kube-system,然后在autoscaler-meta配置项右侧操作列下,单击编辑

    4. 编辑面板中,修改autoscaler-meta配置项的值。

      您需将taints值的String类型改成数组类型,即在文本框中,修改"taints":"""taints":[]

    5. 单击确定

  2. 同步节点池。

    1. 在集群管理页左侧导航栏,选择节点管理 > 节点池

    2. 节点池页面右上方,单击同步节点池

未使用过alicloud_cs_kubernetes_autoscaler组件

您可以使用Terraform创建开启自动伸缩功能的节点池。

  1. 创建节点池的配置文件。

    为已有集群创建开启自动伸缩功能的节点池

    在已有集群中创建开启自动伸缩功能的节点池,配置示例如下。

    provider "alicloud" {
    }
    # 为已有集群创建开启自动伸缩功能的节点池。
    resource "alicloud_cs_kubernetes_node_pool" "at1" {
      # 目标集群ID。
      cluster_id           = ""
      name                 = "np-test"
      # 节点池内节点使用的vswitch,至少提供一个。
      vswitch_ids          = ["vsw-bp1mdigyhmilu2h4v****"]
      instance_types       = ["ecs.e3.medium"]
      password             = "Hello1234"
     
      scaling_config {
        # 最小节点数。
        min_size     = 1
        # 最大节点数。
        max_size     = 5
      }
    
    }

    创建新的具备自动伸缩功能的节点池集群

    创建一个包含自动伸缩节点池的集群,配置示例如下。

    provider "alicloud" {
      region = var.region_id
    }
    
    variable "region_id" {
      type    = string
      default = "cn-shenzhen"
    }
    
    variable "cluster_spec" {
      type        = string
      description = "The cluster specifications of kubernetes cluster,which can be empty. Valid values:ack.standard : Standard managed clusters; ack.pro.small : Professional managed clusters."
      default     = "ack.pro.small"
    }
    
    variable "ack_version" {
      type        = string
      description = "Desired Kubernetes version. "
      default     = "1.28.9-aliyun.1"
    }
    
    # 指定虚拟交换机(vSwitches)的可用区。
    variable "availability_zone" {
      description = "The availability zones of vswitches."
      default     = ["cn-shenzhen-c", "cn-shenzhen-e", "cn-shenzhen-f"]
    }
    
    # 用于创建新vSwitches的CIDR地址块列表。
    variable "node_vswitch_cidrs" {
      type        = list(string)
      default     = ["172.16.0.0/23", "172.16.2.0/23", "172.16.4.0/23"]
    }
    
    # 用于创建Terway使用的vSwitch的CIDR地址块。
    variable "terway_vswitch_cidrs" {
      type        = list(string)
      default     = ["172.16.208.0/20", "172.16.224.0/20", "172.16.240.0/20"]
    }
    
    # 定义了用于启动工作节点的ECS实例类型。
    variable "worker_instance_types" {
      description = "The ecs instance types used to launch worker nodes."
      default     = ["ecs.g6.2xlarge", "ecs.g6.xlarge"]
    }
    
    # 设置工作阶段的密码
    variable "password" {
      description = "The password of ECS instance."
      default     = "Test123456"
    }
    
    # 指定创建ACK托管集群名称的前缀。
    variable "k8s_name_prefix" {
      description = "The name prefix used to create managed kubernetes cluster."
      default     = "tf-ack-shenzhen"
    }
    
    variable "vpc_name" {
      default = "tf-vpc"
    }
    
    variable "autoscale_nodepool_name" {
      default = "autoscale-node-pool"
    }
    
    # 指定ACK集群安装的组件。包括Terway(网络组件)、csi-plugin(存储组件)、csi-provisioner(存储组件)、logtail-ds(日志组件)、Nginx Ingress Controller、ack-arms-prometheus(监控组件)以及ack-node-problem-detector(节点诊断组件)。
    variable "cluster_addons" {
      type = list(object({
        name   = string
        config = string
      }))
    
      default = [
        {
          "name"   = "terway-eniip",
          "config" = "",
        },
        {
          "name"   = "logtail-ds",
          "config" = "{\"IngressDashboardEnabled\":\"true\"}",
        },
        {
          "name"   = "nginx-ingress-controller",
          "config" = "{\"IngressSlbNetworkType\":\"internet\"}",
        },
        {
          "name"   = "arms-prometheus",
          "config" = "",
        },
        {
          "name"   = "ack-node-problem-detector",
          "config" = "{\"sls_project_name\":\"\"}",
        },
        {
          "name"   = "csi-plugin",
          "config" = "",
        },
        {
          "name"   = "csi-provisioner",
          "config" = "",
        }
      ]
    }
    
    # 默认资源名称。
    locals {
      k8s_name_terway = substr(join("-", [var.k8s_name_prefix, "terway"]), 0, 63)
    }
    
    # 节点ECS实例配置。将查询满足CPU、Memory要求的ECS实例类型。
    data "alicloud_instance_types" "default" {
      cpu_core_count       = 8
      memory_size          = 32
      availability_zone    = var.availability_zone[0]
      kubernetes_node_role = "Worker"
    }
    
    # 专有网络。
    resource "alicloud_vpc" "default" {
      vpc_name   = var.vpc_name
      cidr_block = "172.16.0.0/12"
    }
    
    # Node交换机。
    resource "alicloud_vswitch" "vswitches" {
      count      = length(var.node_vswitch_cidrs)
      vpc_id     = alicloud_vpc.default.id
      cidr_block = element(var.node_vswitch_cidrs, count.index)
      zone_id    = element(var.availability_zone, count.index)
    }
    
    # Pod交换机。
    resource "alicloud_vswitch" "terway_vswitches" {
      count      = length(var.terway_vswitch_cidrs)
      vpc_id     = alicloud_vpc.default.id
      cidr_block = element(var.terway_vswitch_cidrs, count.index)
      zone_id    = element(var.availability_zone, count.index)
    }
    
    # Kubernetes托管版。
    resource "alicloud_cs_managed_kubernetes" "default" {
      name                         = local.k8s_name_terway # Kubernetes集群名称。
      cluster_spec                 = var.cluster_spec      # 创建Pro版集群。
      version                      = var.ack_version
      worker_vswitch_ids           = split(",", join(",", alicloud_vswitch.vswitches.*.id))        # 节点池所在的vSwitch。指定一个或多个vSwitch的ID,必须在availability_zone指定的区域中。
      pod_vswitch_ids              = split(",", join(",", alicloud_vswitch.terway_vswitches.*.id)) # Pod虚拟交换机。
      new_nat_gateway              = true                                                          # 是否在创建Kubernetes集群时创建新的NAT网关。默认为true。
      service_cidr                 = "10.11.0.0/16"                                                # Pod网络的CIDR块。当cluster_network_type设置为flannel,你必须设定该参数。它不能与VPC CIDR相同,并且不能与VPC中的Kubernetes集群使用的CIDR相同,也不能在创建后进行修改。集群中允许的最大主机数量:256。
      slb_internet_enabled         = true                                                          # 是否为API Server创建Internet负载均衡。默认为false。
      enable_rrsa                  = true
      control_plane_log_components = ["apiserver", "kcm", "scheduler", "ccm"] # 控制平面日志。
      dynamic "addons" {                                                      # 组件管理。
        for_each = var.cluster_addons
        content {
          name   = lookup(addons.value, "name", var.cluster_addons)
          config = lookup(addons.value, "config", var.cluster_addons)
        }
      }
    }
    
    # 创建自动伸缩节点池,节点池最多可以扩展到 10 个节点,最少保持 1 个节点。
    resource "alicloud_cs_kubernetes_node_pool" "autoscale_node_pool" {
      cluster_id     = alicloud_cs_managed_kubernetes.default.id
      node_pool_name = var.autoscale_nodepool_name
      vswitch_ids    = split(",", join(",", alicloud_vswitch.vswitches.*.id))
    
      scaling_config {
        min_size = 1
        max_size = 10
      }
    
      instance_types        = var.worker_instance_types
      runtime_name          = "containerd"
      runtime_version       = "1.6.20"
      password              = var.password # SSH登录集群节点的密码。
      install_cloud_monitor = true         # 是否为kubernetes的节点安装云监控。
      system_disk_category  = "cloud_efficiency"
      system_disk_size      = 100
      image_type            = "AliyunLinux3"
    
      data_disks {              # 节点数据盘配置。
        category = "cloud_essd" # 节点数据盘种类。
        size     = 120          # 节点数据盘大小。
      }
    }
  2. 执行如下命令,初始化Terraform运行环境。

    terraform init

    返回信息如下,Terraform初始化成功。

    Terraform has been successfully initialized!
    
    You may now begin working with Terraform. Try running "terraform plan" to see
    any changes that are required for your infrastructure. All Terraform commands
    should now work.
    
    If you ever set or change modules or backend configuration for Terraform,
    rerun this command to reinitialize your working directory. If you forget, other
    commands will detect it and remind you to do so if necessary.
  3. 执行terraform apply命令完成创建。

  4. 验证结果。

    完成创建节点池后,在节点池列表中可以看到新建的节点池,该节点池名称下会标注已开启自动伸缩

清理资源

当您不再需要上述通过Terraform创建或管理的资源时,请运行terraform destroy命令以释放资源。关于terraform destroy的更多信息,请参见Terraform常用命令

terraform destroy

完整示例

说明

当前示例代码支持一键运行,您可以直接运行代码。一键运行

provider "alicloud" {
  region = var.region_id
}

variable "region_id" {
  type    = string
  default = "cn-shenzhen"
}

variable "cluster_spec" {
  type        = string
  description = "The cluster specifications of kubernetes cluster,which can be empty. Valid values:ack.standard : Standard managed clusters; ack.pro.small : Professional managed clusters."
  default     = "ack.pro.small"
}

variable "ack_version" {
  type        = string
  description = "Desired Kubernetes version. "
  default     = "1.28.9-aliyun.1"
}

# 指定虚拟交换机(vSwitches)的可用区。
variable "availability_zone" {
  description = "The availability zones of vswitches."
  default     = ["cn-shenzhen-c", "cn-shenzhen-e", "cn-shenzhen-f"]
}

# 用于创建新vSwitches的CIDR地址块列表。
variable "node_vswitch_cidrs" {
  type        = list(string)
  default     = ["172.16.0.0/23", "172.16.2.0/23", "172.16.4.0/23"]
}

# 用于创建Terway使用的vSwitch的CIDR地址块。
variable "terway_vswitch_cidrs" {
  type        = list(string)
  default     = ["172.16.208.0/20", "172.16.224.0/20", "172.16.240.0/20"]
}

# 定义了用于启动工作节点的ECS实例类型。
variable "worker_instance_types" {
  description = "The ecs instance types used to launch worker nodes."
  default     = ["ecs.g6.2xlarge", "ecs.g6.xlarge"]
}

# 设置工作阶段的密码
variable "password" {
  description = "The password of ECS instance."
  default     = "Test123456"
}

# 指定创建ACK托管集群名称的前缀。
variable "k8s_name_prefix" {
  description = "The name prefix used to create managed kubernetes cluster."
  default     = "tf-ack-shenzhen"
}

variable "vpc_name" {
  default = "tf-vpc"
}

variable "autoscale_nodepool_name" {
  default = "autoscale-node-pool"
}

# 指定ACK集群安装的组件。包括Terway(网络组件)、csi-plugin(存储组件)、csi-provisioner(存储组件)、logtail-ds(日志组件)、Nginx Ingress Controller、ack-arms-prometheus(监控组件)以及ack-node-problem-detector(节点诊断组件)。
variable "cluster_addons" {
  type = list(object({
    name   = string
    config = string
  }))

  default = [
    {
      "name"   = "terway-eniip",
      "config" = "",
    },
    {
      "name"   = "logtail-ds",
      "config" = "{\"IngressDashboardEnabled\":\"true\"}",
    },
    {
      "name"   = "nginx-ingress-controller",
      "config" = "{\"IngressSlbNetworkType\":\"internet\"}",
    },
    {
      "name"   = "arms-prometheus",
      "config" = "",
    },
    {
      "name"   = "ack-node-problem-detector",
      "config" = "{\"sls_project_name\":\"\"}",
    },
    {
      "name"   = "csi-plugin",
      "config" = "",
    },
    {
      "name"   = "csi-provisioner",
      "config" = "",
    }
  ]
}

# 默认资源名称。
locals {
  k8s_name_terway = substr(join("-", [var.k8s_name_prefix, "terway"]), 0, 63)
}

# 节点ECS实例配置。将查询满足CPU、Memory要求的ECS实例类型。
data "alicloud_instance_types" "default" {
  cpu_core_count       = 8
  memory_size          = 32
  availability_zone    = var.availability_zone[0]
  kubernetes_node_role = "Worker"
}

# 专有网络。
resource "alicloud_vpc" "default" {
  vpc_name   = var.vpc_name
  cidr_block = "172.16.0.0/12"
}

# Node交换机。
resource "alicloud_vswitch" "vswitches" {
  count      = length(var.node_vswitch_cidrs)
  vpc_id     = alicloud_vpc.default.id
  cidr_block = element(var.node_vswitch_cidrs, count.index)
  zone_id    = element(var.availability_zone, count.index)
}

# Pod交换机。
resource "alicloud_vswitch" "terway_vswitches" {
  count      = length(var.terway_vswitch_cidrs)
  vpc_id     = alicloud_vpc.default.id
  cidr_block = element(var.terway_vswitch_cidrs, count.index)
  zone_id    = element(var.availability_zone, count.index)
}

# Kubernetes托管版。
resource "alicloud_cs_managed_kubernetes" "default" {
  name                         = local.k8s_name_terway # Kubernetes集群名称。
  cluster_spec                 = var.cluster_spec      # 创建Pro版集群。
  version                      = var.ack_version
  worker_vswitch_ids           = split(",", join(",", alicloud_vswitch.vswitches.*.id))        # 节点池所在的vSwitch。指定一个或多个vSwitch的ID,必须在availability_zone指定的区域中。
  pod_vswitch_ids              = split(",", join(",", alicloud_vswitch.terway_vswitches.*.id)) # Pod虚拟交换机。
  new_nat_gateway              = true                                                          # 是否在创建Kubernetes集群时创建新的NAT网关。默认为true。
  service_cidr                 = "10.11.0.0/16"                                                # Pod网络的CIDR块。当cluster_network_type设置为flannel,你必须设定该参数。它不能与VPC CIDR相同,并且不能与VPC中的Kubernetes集群使用的CIDR相同,也不能在创建后进行修改。集群中允许的最大主机数量:256。
  slb_internet_enabled         = true                                                          # 是否为API Server创建Internet负载均衡。默认为false。
  enable_rrsa                  = true
  control_plane_log_components = ["apiserver", "kcm", "scheduler", "ccm"] # 控制平面日志。
  dynamic "addons" {                                                      # 组件管理。
    for_each = var.cluster_addons
    content {
      name   = lookup(addons.value, "name", var.cluster_addons)
      config = lookup(addons.value, "config", var.cluster_addons)
    }
  }
}

# 创建自动伸缩节点池,节点池最多可以扩展到 10 个节点,最少保持 1 个节点。
resource "alicloud_cs_kubernetes_node_pool" "autoscale_node_pool" {
  cluster_id     = alicloud_cs_managed_kubernetes.default.id
  node_pool_name = var.autoscale_nodepool_name
  vswitch_ids    = split(",", join(",", alicloud_vswitch.vswitches.*.id))

  scaling_config {
    min_size = 1
    max_size = 10
  }

  instance_types        = var.worker_instance_types
  runtime_name          = "containerd"
  runtime_version       = "1.6.20"
  password              = var.password # SSH登录集群节点的密码。
  install_cloud_monitor = true         # 是否为kubernetes的节点安装云监控。
  system_disk_category  = "cloud_efficiency"
  system_disk_size      = 100
  image_type            = "AliyunLinux3"

  data_disks {              # 节点数据盘配置。
    category = "cloud_essd" # 节点数据盘种类。
    size     = 120          # 节点数据盘大小。
  }
}