All Products
Search
Document Center

Container Service for Kubernetes:Create custom images

Last Updated:Feb 02, 2024

Alicloud Image Builder is an image building tool provided by Alibaba Cloud that simplifies and automates image building. You can use OS images created by using Alicloud Image Builder as custom images to create node pools in Container Service for Kubernetes (ACK) clusters. This allows you to quickly add nodes to ACK clusters. This topic describes how to run Alicloud Image Builder as a Job to create custom OS images in ACK clusters.

Prerequisites

Background information

The node pools in ACK clusters support auto scaling. By default, when you create a node pool, you can select OS images such as CentOS and Alibaba Cloud Linux 2. These OS images meet the requirements of most scenarios. However, in scenarios that require preinstallation or high performance, these images may be unable to meet your requirements. Alibaba Cloud provides Alicloud Image Builder to help you build custom OS images and facilitate auto scaling in complex scenarios.

To use Alicloud Image Builder to create custom images, you can create a Job or a CronJob to distribute the image building task in the cluster.

Create a Job to quickly build a custom OS image

In this example, a ConfigMap named build-config and a Job named build are created to show how to use Alicloud Image Builder to quickly build a custom OS image.

  1. Create a ConfigMap named build-config to specify the parameters for the OS image.

    1. Create a YAML file named build-config.yaml and copy the following content to the file:

      Show YAML content

      apiVersion: v1
      kind: ConfigMap
      metadata:
        name: build-config
      data:
        ack.json: |-
      
          {
            "variables": {
              "image_name": "ack-optimized_image-1.22-{{timestamp}}",
              "source_image": <source_image>,
              "instance_type": <instance_type>,
              "region": "{{env `ALICLOUD_REGION`}}",
              "access_key": "{{env `ALICLOUD_ACCESS_KEY`}}",
              "secret_key": "{{env `ALICLOUD_SECRET_KEY`}}"
            },
            "builders": [
              {
                "type": "alicloud-ecs",
                "system_disk_mapping": {    
                          "disk_size": 120
                          },   # Specify the size of the system disk. Unit: GB. The default value is 40. 
                "access_key": "{{user `access_key`}}",
                "secret_key": "{{user `secret_key`}}",
                "region": "{{user `region`}}",
                "image_name": "{{user `image_name`}}",
                "source_image": "{{user `source_image`}}",
                "ssh_username": "root",
                "vpc_id": "",  # If you do not specify a value for vpc_id, a virtual private cloud (VPC) is automatically created during the image building process. The VPC is automatically deleted after the image is built. 
                "vswitch_id": "",  # If you do not specify a value for vswitch_id, a vSwitch is automatically created during the image building process. The vSwitch is automatically deleted after the image is built. 
                "security_group_id": "",   # If you do not specify a value for security_group_id, a security group is automatically created during the image building process. The security group is automatically deleted after the image is built. 
                "instance_type": "{{user `instance_type`}}",
                "skip_image_validation": "true",
                "io_optimized": "true"
              }
            ],
            "provisioners": [{
             "type": "file",
             "source": "scripts/ack-optimized-os-all.sh",
             "destination": "/root/"
              },
              {
             "type": "shell",
             "inline": [
               "export RUNTIME=docker",    # Specify the runtime that is used. 
               "export SKIP_SECURITY_FIX=true",
               "export KUBE_VERSION=1.22.3-aliyun.1",
               "export OS_ARCH=amd64",    # Specify amd64 or arm64 based on your business requirements. 
               "bash /root/ack-optimized-os-all.sh"
            ]
            }]
          }

      The following table describes the parameters in the YAML file.

      Table 1. Alicloud Image Builder parameters

      Parameter

      Example

      Description

      variables{"<variable1>":"<value>"}

      variables{"access_key":"{{env ALICLOUD_ACCESS_KEY}}"}

      The variables that are used by Alicloud Image Builder.

      Note

      If you write sensitive information such as AccessKey pairs (access_key and secret_key) to the configuration file, the information may be leaked. To ensure data security, you can specify AccessKey pairs as variables. The values of the variables are based on the input values of the runtime.

      builders{"type":"<value>"}

      builders{"type":"alicloud-ecs"}

      The image builders. When type is set to aliyun-ecs, a temporary Elastic Compute Service (ECS) instance is created to build the image. The ECS instance is automatically released after the image is built.

      provisioners{"type":"<value>"}

      provisioners{"type":"shell"}

      The image provisioners that are used to specify the operations that need to be performed on the temporary instance. When type is set to shell, a shell provisioner is used. A shell command is automatically run after the Linux instance is connected. For example, you can run the yum install redis.x86_64 -y command to install Redis.

      For more information about how to configure provisioners, see Provisioner configuration.

      Table 2. Image building parameters

      Parameter

      Example

      Description

      Importance

      access_key

      LTAInPyXXXXQ****

      The AccessKey ID that is used to create the custom image. For more information, see Obtain an AccessKey pair.

      Required

      secret_key

      CM1ycKrrCekQ0dhXXXXXXXXXl7y****

      The AccessKey secret that is used to create the custom image.

      Required

      region

      cn-beijing

      The region where the custom image is to be created.

      Required

      image_name

      ack-custom_image

      The name of the custom image to be created. The name must be globally unique.

      Required

      source_image

      aliyun_2_1903_x64_20G_alibase_20200904.vhd

      The ID of the Alibaba Cloud public image based on which the custom image is created. The created custom image contains the same operating system as the public image.

      Required

      instance_type

      ecs.c6.xlarge

      The instance type of the ECS instance that is created from the base image specified in the source_image parameter. The ECS instance is used to run the preinstallation task and build the custom image. If you want to use a GPU-accelerated image, specify a GPU-accelerated instance type.

      Required

      RUNTIME

      docker

      The container runtime. Valid values: docker and containerd.

      Required

      SKIP_SECURITY_FIX

      true

      Specifies whether to skip security patching.

      Required

      KUBE_VERSION

      1.22.3-aliyun.1

      The Kubernetes version of the cluster.

      Required

      PRESET_GPU

      true

      Specifies whether to preinstall a GPU driver to accelerate startup.

      Optional

      NVIDIA_DRIVER_VERSION

      460.91.03

      The version of the preinstalled GPU driver. The default value is 460.91.03.

      Optional

      OS_ARCH

      amd64

      The CPU architecture. Valid values: amd64 and arm64.

      Required

      Important
      • Before you specify a custom image for a node pool, make sure that the configurations of the node pool are the same as the build settings of the custom image. Otherwise, nodes created from the custom image cannot be added to the cluster. The configurations of the node pool include the cluster version, container runtime, and GPU-accelerated instance type.

      • When you verify the custom image, select a regular node pool that uses the same build settings as the custom image. After you use the custom image to create nodes and add the nodes to the node pool, check whether your application can run on the nodes as expected.

    2. Run the following command to deploy Alicloud Image Builder in the cluster:

      kubectl apply -f build-config.yaml
  2. Create a Job to build a custom OS image.

    1. Use the following YAML template to grant permissions to the account that uses the AccessKey pair.

      Show YAML content

      {
        "Version": "1",
        "Statement": [
          {
            "Action": [
              "ecs:DeleteInstance",
              "ecs:StartInstance",
              "ecs:StopInstance",
              "ecs:DescribeInstances"
            ],
            "Resource": "*",
            "Effect": "Allow"
          },
          {
            "Action": [
              "ecs:CreateInstance",
              "ecs:DescribeImages",
              "ecs:CreateImage",
              "ecs:ModifyImageSharePermission",
              "ecs:CreateKeyPair",
              "ecs:DeleteKeyPairs",
              "ecs:DetachKeyPair",
              "ecs:AttachKeyPair",
              "ecs:CreateSecurityGroup",
              "ecs:DeleteSecurityGroup",
              "ecs:AuthorizeSecurityGroupEgress",
              "ecs:AuthorizeSecurityGroup",
              "ecs:CreateSnapshot",
              "ecs:AttachDisk",
              "ecs:DetachDisk",
              "ecs:DescribeDisks",
              "ecs:CreateDisk",
              "ecs:DeleteDisk",
              "ecs:CreateNetworkInterface",
              "ecs:DescribeNetworkInterfaces",
              "ecs:AttachNetworkInterface",
              "ecs:DetachNetworkInterface",
              "ecs:DeleteNetworkInterface",
              "ecs:DescribeInstanceAttribute"
            ],
            "Resource": "*",
            "Effect": "Allow"
          },
          {
            "Action": [
              "vpc:DescribeVpcs",
              "vpc:DescribeVSwitches",
              "vpc:AllocateEipAddress",
              "vpc:AssociateEipAddress",
              "vpc:UnassociateEipAddress",
              "vpc:DescribeEipAddresses",
              "vpc:ReleaseEipAddress",
              "vpc:CreateVpc",
              "vpc:DeleteVpc",
              "vpc:DescribeVpcs",
              "vpc:CreateVSwitch",
              "vpc:DeleteVSwitch",
              "vpc:DescribeVSwitches",
              "vpc:CreateRouteTable",
              "vpc:DeleteRouteTable",
              "vpc:DescribeRouteTables",
              "vpc:CreateNatGateway",
              "vpc:DeleteNatGateway",
              "vpc:DescribeNatGateways",
              "vpc:CreateSnatEntry",
              "vpc:DeleteSnatEntry",
              "vpc:DescribeSnatTableEntries"
            ],
            "Resource": "*",
            "Effect": "Allow"
          }
        ]
      }
    2. Run the following command to generate encrypted strings for the AccessKey pair.

      echo -n "AKxxxxxxxxxxxxxxx" | base64
      echo -n "SKxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" | base64
    3. Use the following YAML template to create a Secret named my-secret.

      apiVersion: v1
      kind: Secret
      metadata:
        name: my-secret
        namespace: default
      type: Opaque
      data:
        ALICLOUD_ACCESS_KEY: TFRxxxxxxxxxxxxxRTkx      // The Base64-encoded string in the previous substep.
        ALICLOUD_SECRET_KEY: a0zxxxxxxxxxxxxxx2UThl
    4. Create a YAML file named build.yaml and add the following content to the file:

      Configure variables to run the Job. The ECS instance of the specified instance type (instance_type) created from the base image (source_image) is used to build the custom image. The ECS instance belongs to the Alibaba Cloud account to which the AccessKey pair belongs. The system then runs the configurations of the provisioner and pushes the image built by the ECS instance to the specified region as a custom image. The custom image also belongs to the Alibaba Cloud account to which the AccessKey pair belongs.

      Show YAML content

      apiVersion: batch/v1
      kind: Job
      metadata:
        name: image-builder
        namespace: default
      spec:
        template:
          metadata:
            name: image-builder
          spec:
        template:
          metadata:
            name: image-builder
          spec:
            containers:
              - name: image-builder
                image: "registry.cn-hangzhou.aliyuncs.com/acs/image-builder:v2.8"
                imagePullPolicy: Always
              env:            
               - name: ALICLOUD_ACCESS_KEY              
               	 valueFrom:                
              	   secretKeyRef:                  
             		     name: my-secret                  
                     key: ALICLOUD_ACCESS_KEY            
               - name: ALICLOUD_SECRET_KEY              
                 valueFrom:                
                   secretKeyRef:                  
                     name: my-secret                  
                     key: ALICLOUD_SECRET_KEY            
               - name: ALICLOUD_REGION              
                 value: cn-hangzhou   
                command: ["packer"]
                args:  ["build","/config/ack.json"]
                volumeMounts:
                  - name: config
                    mountPath: /config
            volumes:
              - name: config
                configMap:
                  name: build-config
                  items:
                    - key: ack.json
                      path: ack.json
            restartPolicy: Never
    5. Run the following command to deploy the Job and start building the image:

      kubectl apply -f build.yaml
  3. Optional:Log on to the ACK console and check the image building log.

    A log is generated during the image building process. The log records all image building operations, including checking parameters, creating temporary resources, pre-installing software, creating target resources, and releasing temporary resources. You can check the image building log by performing the following steps:

    1. Log on to the ACK console. In the left-side navigation pane, click Clusters.

    2. On the Clusters page, click the name of the cluster that you want to manage and choose Workloads > Jobs in the left-side navigation pane.

    3. On the Jobs page, find the Job that you created and click Details in the Actions column.

    4. On the Job details page, click the Logs tab to check the image building log.

Provisioner configuration

A provisioner is a component used to install and configure software in a running operating system before the operating system is packaged into an OS image. A provisioner is often used to install software in images in the following scenarios:

  • Install software.

  • Patch kernels.

  • Create a user.

  • Download application code.

  • Build a custom Alibaba Cloud Linux 3 image.

Common operations by using provisioners:

  • Execute shell scripts.

      "provisioners": [{
          "type": "shell",
          "script": "script.sh"
      }]
  • Execute orchestration scripts by using Ansible.

      "provisioners": [
        {
        "type": "ansible",
        "playbook_file": "./playbook.yml"
        }
      ]
  • Install the Cloud Paralleled File System (CPFS) client.

    The installation of CPFS requires multiple installation packages, some of which involve real-time compilation and may require an extended period of time to install. The use of a custom image can greatly reduce the cost of installing the CPFS client on a large number of nodes. The following code block provides a sample configuration.

    Show YAML content

        {
          "variables": {
            "region": "{{env `REGION`}}",
            "image_name": "ack-custom_image",
            "source_image": "centos_7_04_64_20G_alibase_201701015.vhd",
            "access_key": "{{env `ALICLOUD_ACCESS_KEY`}}",
            "instance_type": "ecs.c6.xlarge",
            "secret_key": "{{env `ALICLOUD_SECRET_KEY`}}"
          },
        "builders": [
            {
              "type": "alicloud-ecs",
              "access_key": "{{user `access_key`}}",
              "secret_key": "{{user `secret_key`}}",
              "region": "{{user `region`}}",
              "image_name": "{{user `image_name`}}",
              "source_image": "{{user `source_image`}}",
              "ssh_username": "root",
              "instance_type": "{{user `instance_type`}}",
              "skip_image_validation": "true",
              "io_optimized": "true"
            }
          ],
       "provisioners": [{
            "type": "shell",
            "inline": [
                "cd $HOME",
                "wget https://cpfs-client.oss-cn-beijing.aliyuncs.com/kernel/kernel-devel-`uname -r`.rpm",
                "rpm -ivh --replacefiles kernel-devel-`uname -r`.rpm"
            ]
          }]
  • Customize the OS image of a GPU-accelerated node.

    Important

    You cannot deploy images with GPU drivers preinstalled on CPU-accelerated nodes.

    Show YAML content

    {
          "variables": {
            "region": "{{env `REGION`}}",
            "image_name": "ack-custom_image",
            "source_image": "aliyun_2_1903_x64_20G_alibase_20221102.vhd",
            "instance_type": "ecs.gn6i-c4g1.xlarge",   # To use an image that has a GPU driver preinstalled, you must specify a GPU-accelerated instance type. 
            "access_key": "{{env `ALICLOUD_ACCESS_KEY`}}",
            "secret_key": "{{env `ALICLOUD_SECRET_KEY`}}"
          },
        "builders": [
            {
              "type": "alicloud-ecs",
              "access_key": "{{user `access_key`}}",
              "secret_key": "{{user `secret_key`}}",
              "region": "{{user `region`}}",
              "image_name": "{{user `image_name`}}",
              "source_image": "{{user `source_image`}}",
              "instance_type": "{{user `instance_type`}}",
              "ssh_username": "root",
              "skip_image_validation": "true",
              "io_optimized": "true"
            }
          ],
       "provisioners": [
            {
                "type": "file",
                "source": "scripts/ack-optimized-os-all.sh",
                "destination": "/root/"
            },
            {
                "type": "shell",
                "inline": [
                    "export RUNTIME=containerd",
                    "export SKIP_SECURITY_FIX=true",
                    "export PRESET_GPU=true",          # To use an image that has a GPU driver preinstalled, set PRESET_GPU to true. If you do not want to preinstall the GPU driver, leave this parameter empty or set it to false. 
                    "export NVIDIA_DRIVER_VERSION=510.47.03",         # Specify the GPU driver version. If you leave this parameter empty, the 460.91.03 version is installed by default. 
                    "export KUBE_VERSION=1.22.3-aliyun.1",
                    "export OS_ARCH=amd64",
                    "bash /root/ack-optimized-os-all.sh"
                ]
            }
          ]
        }
  • Add the application image to the system image.

    Show YAML content

    {
          "variables": {
            "image_name": "ack-custom_image",
            "source_image": "aliyun_2_1903_x64_20G_alibase_20221102.vhd",
            "instance_type": "ecs.c6.xlarge",
            "access_key": "{{env `ALICLOUD_ACCESS_KEY`}}",
            "region": "{{env `ALICLOUD_REGION`}}",
            "secret_key": "{{env `ALICLOUD_SECRET_KEY`}}"
          },
        "builders": [
            {
              "type": "alicloud-ecs",
              "access_key": "{{user `access_key`}}",
              "secret_key": "{{user `secret_key`}}",
              "region": "{{user `region`}}",
              "image_name": "{{user `image_name`}}",
              "source_image": "{{user `source_image`}}",
              "instance_type": "{{user `instance_type`}}",
              "ssh_username": "root",
              "skip_image_validation": "true",
              "io_optimized": "true"
            }
          ],
       "provisioners": [
            {
                "type": "file",
                "source": "scripts/ack-optimized-os-all.sh",
                "destination": "/root/"
            },
            {
                "type": "shell",
                "inline": [
                    "export RUNTIME=docker",
                    "export SKIP_SECURITY_FIX=true",
                    "export OS_ARCH=amd64"
                    "export KUBE_VERSION=1.22.3-aliyun.1",
                    "bash /root/ack-optimized-os-all.sh",
                    "docker pull nginx"        #Add the NGINX image to the system image. 
                ]
            }
          ]
        }
    • Pull an image from a private repository when the runtime is Docker:

      docker login <Image address> -u user -p password
      docker pull nginx
    • Pull an image from a private repository when the runtime is containerd:

      ctr -n k8s.io i pull --user=username:password nginx
  • Pull an image from a private repository after the custom image is built.

    1. Run the following docker login command on a Linux server that has Docker installed to generate a certificate:

      docker login --username=zhongwei.***@aliyun-test.com --password xxxxxxxxxx registry.cn-beijing.aliyuncs.com

      After the docker login command succeeds, a certificate named config.json is created in the /root/.docker directory.96

    2. Create a ConfigMap based on the certificate named config.json.

      apiVersion: v1
      kind: ConfigMap
      metadata:
        name: docker-config
      data:
        config.json: |-
      
          {
              "auths": {
                      "registry.cn-beijing.aliyuncs.com": {
                              "auth": "xxxxxxxxxxxxxx"
                      }
              },
              "HttpHeaders": {
                      "User-Agent": "Docker-Client/19.03.15 (linux)"
              }
      
          }
    3. Modify the YAML file of the Job to mount the ConfigMap to the pod.95

      Show YAML content

      apiVersion: batch/v1
      kind: Job
      metadata:
        name: image-builder
        namespace: default
      spec:
        template:
          metadata:
            name: image-builder
          spec:
            containers:
              - name: image-builder
                image: "registry.cn-hangzhou.aliyuncs.com/acs/image-builder:v2.8"
                imagePullPolicy: Always
                env:
                  - name: ALICLOUD_ACCESS_KEY
                    value: xxxxxxxxxxxxxx
                  - name: ALICLOUD_SECRET_KEY
                    value: xxxxxxxxxxxxx
                  - name: ALICLOUD_REGION
                    value: cn-heyuan
                command: ["packer"]
                args:  ["build","/config/ack.json"]
                volumeMounts:
                  - name: config
                    mountPath: /config
                  - name: docker
                    mountPath: /dockerconfig
            volumes:
              - name: config
                configMap:
                  name: build-config
                  items:
                    - key: ack.json
                      path: ack.json
              - name: docker
                configMap:
                  name: docker-config
                  items:
                    - key: config.json
                      path: config.json
            restartPolicy: Never
    4. Add the content in the following figure to the build-config ConfigMap.94

      Show YAML content

      apiVersion: v1
      kind: ConfigMap
      metadata:
        name: build-config
      data:
        ack.json: |-
      
          {
            "variables": {
              "image_name": "ack-optimized_image-1.20-{{timestamp}}",
              "source_image": "aliyun_2_1903_x64_20G_alibase_20221102.vhd",
              "instance_type": "ecs.c6.xlarge",
              "region": "{{env `ALICLOUD_REGION`}}",
              "access_key": "{{env `ALICLOUD_ACCESS_KEY`}}",
              "secret_key": "{{env `ALICLOUD_SECRET_KEY`}}"
            },
            "builders": [
              {
                "type": "alicloud-ecs",
                "access_key": "{{user `access_key`}}",
                "secret_key": "{{user `secret_key`}}",
                "region": "{{user `region`}}",
                "image_name": "{{user `image_name`}}",
                "source_image": "{{user `source_image`}}",
                "ssh_username": "root",
                "instance_type": "{{user `instance_type`}}",
                "skip_image_validation": "true",
                "io_optimized": "true"
              }
            ],
            "provisioners": [{
             "type": "file",
             "source": "scripts/ack-optimized-os-all.sh",
             "destination": "/root/"
              },
              {
             "type": "file",
             "source": "dockerconfig/config.json",
             "destination": "/root/"
              },
              {
             "type": "shell",
             "inline": [
               "export OS_ARCH=amd64",
               "export RUNTIME=docker",
               "export SKIP_SECURITY_FIX=true",
               "export KUBE_VERSION=1.22.15-aliyun.1",
               "bash /root/ack-optimized-os-all.sh",
               "mkdir -p /root/.docker",
               "cp /root/config.json /root/.docker",
               "docker pull registry.cn-beijing.aliyuncs.com/ringtail/kruise-game:0.1"
      
            ]
            }]
          }
    5. Run the Job.

  • Specify the maximum numbers of concurrent uploads and downloads for the image.

    1. Log on to the ACK console and click Clusters in the left-side navigation pane.

    2. On the Clusters page, click the name of the cluster that you want to manage and choose Nodes > Node Pools in the left-side navigation pane.

    3. Click the name of the node pool that you want to manage. Click the Overview tab. In the Node Pool Information section, click the link next to Scaling Group.

    4. Click the Instance Configuration Sources tab. Find the scaling configuration that you want to manage and click Edit in the Actions column.

    5. In the Note message, click OK.

    6. On the Modify Scaling Configuration page, modify the parameters and click Advanced Settings to show the advanced settings. Record the data in the Instance User Data box. Decode the data in the Instance User Data box by using Base64.

    7. After you decode the data, append the following code to the end of the decoded data.

      yum install -y jq
      echo "$jq '. += {"max-concurrent-downloads": 20,"max-concurrent-uploads": 20}' /etc/docker/daemon.json" > /etc/docker/daemon.json
      service docker restart

      加

    8. Encode the modified data in Base64 and overwrite the original data in the Instance User Data box with the modified data.

    9. Click Modify. In the dialog box that appears, click Modify.

  • Use the following template to build a custom Alibaba Cloud Linux 3 image:

    Show YAML content

    apiVersion: v1
    kind: ConfigMap
    metadata:
      name: build-config
    data:
      ack.json: |-
        
        {
          "variables": {
            "image_name": "ack-optimized_image-1.22-{{timestamp}}",
            "source_image":"aliyun_3_x64_20G_alibase_20230110.vhd",  # The base image for Alibaba Cloud Linux 3. 
            "instance_type": "ecs.c6.xlarge",
            "region": "{{env `ALICLOUD_REGION`}}",
            "access_key": "{{env `ALICLOUD_ACCESS_KEY`}}",
            "secret_key": "{{env `ALICLOUD_SECRET_KEY`}}",
          },
          "builders": [
            {
              "type": "alicloud-ecs",
              "access_key": "{{user `access_key`}}",
              "secret_key": "{{user `secret_key`}}",
              "region": "{{user `region`}}",
              "image_name": "{{user `image_name`}}",
              "source_image": "{{user `source_image`}}",
              "ssh_username": "root",  
              "instance_type": "{{user `instance_type`}}",
              "skip_image_validation": "true",
              "io_optimized": "true"
            }
          ],
          "provisioners": [{
           "type": "file",
           "source": "scripts/ack-optimized-os-linux3-all.sh",
           "destination": "/root/"
            },
            {
           "type": "shell",
           "inline": [
             "export RUNTIME=containerd",
             "export SKIP_SECURITY_FIX=true",
             "export OS_ARCH=amd64",
             "export KUBE_VERSION=1.22.3-aliyun.1",
             "bash /root/ack-optimized-os-linux3-all.sh",
          ]
          }]
        }

  • Use the following template to build a custom Red Hat Enterprise Linux 9 (RHEL 9) image:

    Show YAML content

    apiVersion: v1
    kind: ConfigMap
    metadata:
      name: build-config
    data:
      ack.json: |-
        
        {
          "variables": {
            "image_name": "ack-optimized_image-1.26-{{timestamp}}",
            "source_image": "m-bp1c7zuf8mcabc99babc",       # The base image for RHEL 9. 
            "instance_type": "ecs.c6.xlarge",
            "region": "{{env `ALICLOUD_REGION`}}",
            "access_key": "{{env `ALICLOUD_ACCESS_KEY`}}",
            "secret_key": "{{env `ALICLOUD_SECRET_KEY`}}",
            "runtime": "{{env `RUNTIME`}}",
            "skip_secrutiy_fix": "{{env `SKIP_SECURITY_FIX`}}"
          },
          "builders": [
            {
              "type": "alicloud-ecs",
              "access_key": "{{user `access_key`}}",
              "secret_key": "{{user `secret_key`}}",
              "region": "{{user `region`}}",
              "image_name": "{{user `image_name`}}",
              "source_image": "{{user `source_image`}}",
              "ssh_username": "root",
              # "vpc_id": "",
              # "vswitch_id": "",
              # "security_group_id": "",      
              "instance_type": "{{user `instance_type`}}",
              "skip_image_validation": "true",
              "io_optimized": "true"
            }
          ],
          "provisioners": [{
           "type": "file",
           "source": "scripts/ack-optimized-os-rhel9-all.sh",
           "destination": "/root/"
            },
            {
           "type": "shell",
           "inline": [
             "export RUNTIME=containerd",
             "export SKIP_SECURITY_FIX=true",
             "export OS_ARCH=amd64",
             "export KUBE_VERSION=1.26.3-aliyun.1",
             "bash /root/ack-optimized-os-rhel9-all.sh"
          ]
          }]
        }

What to do next

After you create a custom image by using Alicloud Image Builder, you can create an elastic node pool based on the custom image to quickly add nodes to the cluster. For more information about how to create an elastic node pool, see Auto scaling of nodes.