Use Terraform to create an ACK Serverless cluster

Updated at:

This topic describes how to create an ACK serverless cluster using Terraform, including VPC, vSwitch, and security group setup.

Note

Run the complete example in one click from Terraform Explorer.

Prerequisites

Before you begin, ensure that you have:

Important

Verify your Terraform version with terraform --version. This guide requires version 0.12.28 or later.

Note

Use a RAM user instead of your Alibaba Cloud account to reduce security risks from compromised credentials.

Minimum RAM policy

Attach the following policy to the RAM user. It grants the minimum permissions to create and delete VPCs, vSwitches, security groups, and ACK clusters.

{
    "Version": "1",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "vpc:CreateVpc",
                "vpc:CreateVSwitch",
                "vpc:DescribeVpcAttribute",
                "vpc:DescribeRouteTableList",
                "vpc:DescribeVSwitchAttributes",
                "ecs:CreateSecurityGroup",
                "ecs:ModifySecurityGroupPolicy",
                "ecs:DescribeSecurityGroups",
                "ecs:DescribeSecurityGroupAttribute",
                "ecs:ListTagResources",
                "cs:CreateCluster",
                "cs:DescribeTaskInfo",
                "cs:DescribeClusterDetail",
                "vpc:DeleteVpc",
                "vpc:DeleteVSwitch",
                "cs:DeleteCluster",
                "ecs:DeleteSecurityGroup"
            ],
            "Resource": "*"
        }
    ]
}

Resources

Note

Some resources in this configuration incur charges. Release them when no longer needed.

Create the cluster

Step 1: Write the Terraform configuration

Create a working directory and add a main.tf file with the following configuration:

provider "alicloud" {
  region = var.region_id
}

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

variable "cluster_spec" {
  type        = string
  description = "Cluster specification. Valid values: ack.standard (Standard managed), ack.pro.small (Professional managed)."
  default     = "ack.pro.small"
}

variable "k8s_name_prefix" {
  description = "Name prefix for the ACK serverless cluster."
  default     = "ask-example"
}

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

# Default resource names.
locals {
  k8s_name_ask = substr(join("-", [var.k8s_name_prefix, "ask"]), 0, 63)
  new_vpc_name = "tf-vpc-172-16"
  new_vsw_name = "tf-vswitch-172-16-0"
  new_sg_name  = "tf-sg-172-16"
}

data "alicloud_eci_zones" "default" {}

resource "alicloud_vpc" "vpc" {
  vpc_name   = local.new_vpc_name
  cidr_block = "172.16.0.0/12"
}

resource "alicloud_vswitch" "vsw" {
  vswitch_name = local.new_vsw_name
  vpc_id       = alicloud_vpc.vpc.id
  cidr_block   = cidrsubnet(alicloud_vpc.vpc.cidr_block, 8, 8)
  zone_id      = data.alicloud_eci_zones.default.zones.0.zone_ids.0
}

resource "alicloud_security_group" "group" {
  security_group_name = local.new_sg_name
  vpc_id              = alicloud_vpc.vpc.id
}

resource "alicloud_cs_serverless_kubernetes" "serverless" {
  name                           = local.k8s_name_ask
  version                        = var.ack_version
  cluster_spec                   = var.cluster_spec
  vpc_id                         = alicloud_vpc.vpc.id
  vswitch_ids                    = split(",", join(",", alicloud_vswitch.vsw.*.id))
  new_nat_gateway                = true
  endpoint_public_access_enabled = true
  deletion_protection            = false
  security_group_id              = alicloud_security_group.group.id
  enable_rrsa                    = true
  time_zone                      = "Asia/Shanghai"
  service_cidr                   = "10.13.0.0/16"
  service_discovery_types        = ["CoreDNS"]

  tags = {
    "cluster" = "ack-serverless"
  }

  # Nginx Ingress Controller with internet-facing SLB
  addons {
    name   = "nginx-ingress-controller"
    config = "{\"IngressSlbNetworkType\":\"internet\",\"IngressSlbSpec\":\"slb.s2.small\"}"
    # For internal SLB, use:
    # config = "{\"IngressSlbNetworkType\":\"intranet\",\"IngressSlbSpec\":\"slb.s2.small\"}"
  }
  addons {
    name = "metrics-server"
  }
  addons {
    name = "knative"
  }
  addons {
    name = "managed-arms-prometheus"
  }
  addons {
    name = "logtail-ds"
    # To specify a Simple Log Service (SLS) project:
    # config = "{\"sls_project_name\":\"<your-sls-project-name>\"}"
  }
}

Cluster parameters

ParameterDescriptionDefault
region_idRegion for resource deploymentcn-shenzhen
cluster_specCluster edition. ack.standard for Standard, ack.pro.small for Professionalack.pro.small
ack_versionKubernetes version1.32.7-aliyun.1
new_nat_gatewayCreate a NAT Gateway for internet accesstrue
endpoint_public_access_enabledExpose the API server endpoint publiclytrue
enable_rrsaEnable RAM Roles for Service Accounts (RRSA)true
service_cidrCIDR block for Kubernetes Services10.13.0.0/16
service_discovery_typesService discovery mechanism["CoreDNS"]

Addons

AddonPurpose
nginx-ingress-controllerIngress traffic routing through an internet-facing Server Load Balancer (SLB) instance (spec: slb.s2.small)
metrics-serverPod resource metrics for Horizontal Pod Autoscaler
knativeServerless workload framework
managed-arms-prometheusManaged Prometheus monitoring
logtail-dsLog collection agent for Simple Log Service (SLS)

Step 2: Initialize Terraform

terraform init

Expected output:

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.

Step 3: Preview the execution plan

terraform plan

Review the output to confirm that 4 resources will be created:

Plan: 4 to add, 0 to change, 0 to destroy.

Step 4: Apply the configuration

terraform apply

When prompted, type yes and press Enter. Cluster creation typically takes 8--10 minutes.

Expected output upon completion:

alicloud_cs_serverless_kubernetes.serverless: Creation complete after 8m26s [id=************]

Apply complete! Resources: 4 added, 0 changed, 0 destroyed.

Verify the result

Use either method to confirm that the cluster was created:

Clean up resources

To release all resources created in this guide, run:

terraform destroy

When prompted, type yes to confirm. For more information, see Common Terraform commands.

Complete example

Note

You can run the sample code in this topic with a single click. Run with one click

provider "alicloud" {
  region = var.region_id
}

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

variable "cluster_spec" {
  type        = string
  description = "Cluster specification. Valid values: ack.standard (Standard managed), ack.pro.small (Professional managed)."
  default     = "ack.pro.small"
}

variable "k8s_name_prefix" {
  description = "Name prefix for the ACK serverless cluster."
  default     = "ask-example"
}

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

# Default resource names.
locals {
  k8s_name_ask = substr(join("-", [var.k8s_name_prefix, "ask"]), 0, 63)
  new_vpc_name = "tf-vpc-172-16"
  new_vsw_name = "tf-vswitch-172-16-0"
  new_sg_name  = "tf-sg-172-16"
}

data "alicloud_eci_zones" "default" {}

resource "alicloud_vpc" "vpc" {
  vpc_name   = local.new_vpc_name
  cidr_block = "172.16.0.0/12"
}

resource "alicloud_vswitch" "vsw" {
  vswitch_name = local.new_vsw_name
  vpc_id       = alicloud_vpc.vpc.id
  cidr_block   = cidrsubnet(alicloud_vpc.vpc.cidr_block, 8, 8)
  zone_id      = data.alicloud_eci_zones.default.zones.0.zone_ids.0
}

resource "alicloud_security_group" "group" {
  security_group_name = local.new_sg_name
  vpc_id              = alicloud_vpc.vpc.id
}

resource "alicloud_cs_serverless_kubernetes" "serverless" {
  name                           = local.k8s_name_ask
  version                        = var.ack_version
  cluster_spec                   = var.cluster_spec
  vpc_id                         = alicloud_vpc.vpc.id
  vswitch_ids                    = split(",", join(",", alicloud_vswitch.vsw.*.id))
  new_nat_gateway                = true
  endpoint_public_access_enabled = true
  deletion_protection            = false
  security_group_id              = alicloud_security_group.group.id
  enable_rrsa                    = true
  time_zone                      = "Asia/Shanghai"
  service_cidr                   = "10.13.0.0/16"
  service_discovery_types        = ["CoreDNS"]

  tags = {
    "cluster" = "ack-serverless"
  }

  # Nginx Ingress Controller with internet-facing SLB
  addons {
    name   = "nginx-ingress-controller"
    config = "{\"IngressSlbNetworkType\":\"internet\",\"IngressSlbSpec\":\"slb.s2.small\"}"
    # For internal SLB, use:
    # config = "{\"IngressSlbNetworkType\":\"intranet\",\"IngressSlbSpec\":\"slb.s2.small\"}"
  }
  addons {
    name = "metrics-server"
  }
  addons {
    name = "knative"
  }
  addons {
    name = "managed-arms-prometheus"
  }
  addons {
    name = "logtail-ds"
    # To specify a Simple Log Service (SLS) project:
    # config = "{\"sls_project_name\":\"<your-sls-project-name>\"}"
  }
}