在一些预安装或者高性能场景下,您可能期望自定义操作系统镜像,以提高复杂场景下弹性伸缩的便捷性。您可以基于镜像构建工具Alicloud Image Builder构建自定义的操作系统镜像,以便基于该镜像构建节点池,加速节点的弹出速度,优化节点自动扩缩容性能。
前提条件
- 已创建ACK集群,请参见创建ACK托管集群。 
- 已通过kubectl工具连接集群。具体操作,请参见获取集群KubeConfig并通过kubectl工具连接集群。 
为什么需要弹性优化的自定义镜像
ACK节点池支持节点自动伸缩,节点池提供的操作系统镜像(Alibaba Cloud Linux、CentOS等)已经能够满足绝大多数场景的使用。但在一些预安装或者高性能场景下,原有的基础镜像可能无法满足业务需求。阿里云提供的Alicloud Image Builder可用于构建属于自定义的操作系统镜像,以提高复杂场景下弹性伸缩的便捷性。
使用Alicloud Image Builder创建自定义镜像时,您可以通过Job或CronJob将镜像构建任务下发到集群,完成构建。
使用ACK Job快速构建自定义操作系统镜像
本文以名为build-config的配置项和名为build的Job工作负载为例,介绍如何使用Alicloud Image Builder快速构建自定义操作系统镜像。
1、配置构建操作系统镜像的参数
您可以创建名为build-config的配置项,以配置构建操作系统镜像的参数。
- 使用以下YAML,创建名为build-config.yaml的文件。 - 上述YAML中涉及参数解释如下。 - 表 1. Alicloud Image Builder配置文件的参数解释 - 参数 - 示例值 - 描述 - variables{"<variable1>":"<value>"}- variables{"access_key":"{{env ALICLOUD_ACCESS_KEY}}"} - 定义了Alicloud Image Builder中会用到的变量( - variables)。说明- 如果将重要信息,例如AccessKey(包括 - access_key和- secret_key)写入配置文件的话,存在信息泄露的风险,但是将其设置成变量后可防止意外,变量的值来源于运行时的输入值。- builders{"type":"<value>"}- builders{"type":"alicloud-ecs"} - 镜像生成器( - builders)。当设置type为aliyun-ecs时,表示构建镜像时,会临时创建一个ECS实例来完成镜像构建。构建完成后,ECS实例会自动销毁。- provisioners{"type":"<value>"}- provisioners{"type":"shell"} - 镜像配置器( - provisioners),用以定义需要在临时实例内执行的操作。当设置type为shell时,说明使用的是Shell Provisioner,表示在连接Linux实例后自动执行一段Shell命令。例如,执行Shell命令- yum install redis.x86_64 -y安装Redis。- 关于Provisioner配置的更多信息,请参见下文的Provisioner配置介绍。 - 表 2. 镜像构建涉及的参数解释 - 参数 - 示例值 - 描述 - 是否必填 - access_key- yourAccessKeyID - 您的AccessKey ID。更多详情,请参见获取AccessKey。 - 必填 - secret_key- yourAccessKeySecret - 您的AccessKey Secret。 - 必填 - region- cn-beijing - 目标自定义镜像的所属地域。 - 必填 - image_name- ack-custom_image - 目标自定义镜像的名称。不允许与已有镜像重名。 - 必填 - source_image- aliyun_2_1903_x64_20G_alibase_20200904.vhd - 具有相同操作系统的阿里云公共镜像ID。详细信息,请参见容器服务Kubernetes版支持的操作系统镜像。 - 必填 - instance_type- ecs.c6.xlarge - 以source_image为镜像生成实例运行指定的预安装任务然后生成自定义镜像。如需要GPU类型镜像此处需要填写GPU类型的实例。 - 必填 - RUNTIME- containerd - 容器运行时,Docker或者containerd。 - 必填 - RUNTIME_VERSION- 1.6.28 - 容器运行时为Docker时,默认RUNTIME_VERSION为19.03.15。 
- 容器运行时为containerd时,默认RUNTIME_VERSION为1.6.20。 
 - 选填 - SKIP_SECURITY_FIX- true - 跳过安全更新。 - 必填 - KUBE_VERSION- 1.30.1-aliyun.1 - 集群版本号。 - 必填 - PRESET_GPU- true - 预置安装GPU,加速启动。 - 选填 - NVIDIA_DRIVER_VERSION- 460.91.03 - 预置GPU版本,不填默认为460.91.03。 - 选填 - OS_ARCH- amd64 - CPU架构,amd64或者arm64。 - 必填 - MOUNT_RUNTIME_DATADISK - true - 自定义镜像缓存了业务镜像后,如需在使用过程中为ECS实例挂载数据盘,则配置为true。 - 选填 重要- 为节点池配置自定义镜像前,请确认节点池的相关配置(集群版本、集群地域、容器运行时、GPU版本适配机型)与构建自定义镜像时的相关配置一致,否则会导致节点无法加入集群。 
- 自定义镜像验证阶段使用和所选参数匹配的普通节点池验证即可,成功加入节点池后在业务上验证是否正常。 
 
- 执行以下命令部署Alicloud Image Builder到集群。 - kubectl apply -f build-config.yaml
2、创建Job以完成自定义操作系统镜像的构建
- 使用以下YAML内容,为AK、SK授予相关权限。 
- 使用以下命令生成AK、SK加密字符串。 - echo -n "yourAccessKeyID" | base64 echo -n "yourAccessKeySecret" | base64
- 使用以下YAML内容,创建my-secret。 - apiVersion: v1 kind: Secret metadata: name: my-secret namespace: default type: Opaque data: ALICLOUD_ACCESS_KEY: TFRI**************** // 上一步经过base64加密后的字符串 ALICLOUD_SECRET_KEY: a0zY****************
- 使用以下YAML内容创建名为build.yaml的文件。 - 根据需求配置变量运行Job,过程中会用的source_image在AK、SK所在账号下生成instance_type类型的ECS,然后运行provisioners的配置,运行完成后会将ECS生成镜像推送到AK、SK所在账号下指定REGION的自定义镜像。 
- 将Job部署到集群,以开始构建操作系统镜像。 - kubectl apply -f build.yaml
3、(可选)查看自定义镜像构建日志
构建镜像时会产生操作日志,记录构建过程中执行的步骤,包括校验参数、创建临时资源、预安装软件、创建目标资源和释放临时资源等。您可以执行以下步骤查看镜像构建日志。
- 登录容器服务管理控制台,在左侧导航栏选择集群列表。 
- 在集群列表页面,单击目标集群名称,然后在左侧导航栏,选择。 
- 在任务列表中,找到上步创建的任务(Job),并单击其右侧操作列下的详情,然后单击日志页签,查看镜像构建日志。 
Provisioner配置介绍
Provisioner是在转换为静态操作系统镜像之前,在正在运行的机器中用于安装和配置软件的组件。需执行安装软件到镜像中的主要工作场景包括:
- 安装软件包。 
- 修补内核。 
- 创建用户。 
- 下载应用程序代码。 
- 制作Alibaba Cloud Linux 3自定义镜像。 
执行Shell脚本
  "provisioners": [{
      "type": "shell",
      "script": "script.sh"
  }]使用Ansible执行编排脚本
  "provisioners": [
    {
    "type": "ansible",
    "playbook_file": "./playbook.yml"
    }
  ]安装CPFS客户端
CPFS需要安装的包较多,且一部分安装包涉及现场编译流程,安装过程比较费时。在客户端节点数量较大时,使用自定义镜像可以减少批量安装CPFS客户端节点的成本。
定制Arm架构镜像
定制GPU节点系统镜像,加速启动
自定义GPU镜像和自定义CPU镜像暂不支持混用。
将业务镜像缓存到系统镜像中
挂载了数据盘的ECS实例在加入节点池的过程中会经历磁盘初始化,预先缓存的业务镜像会被清理。如使用自定义镜像生成ECS时有挂载数据盘的需求,可选择在制作自定义镜像的过程中生成数据盘快照,确保业务镜像不会被清理。
{
      "variables": {
        "image_name": "ack-custom_image",
        "source_image": "aliyun_3_x64_20G_alibase_20240528.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",
          "system_disk_mapping": {    
                    "disk_size": 120,
                    "disk_category": "cloud_essd"
                    },
          "image_disk_mappings": {
                    "disk_size": 40,
                    "disk_category": "cloud_auto"
                    },     # 制作自定义镜像时配置数据盘,镜像制作完成后将自动生成数据盘的快照。
          "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-linux3-all.sh",
            "destination": "/root/"
        },
        {
            "type": "shell",
            "inline": [
                "export RUNTIME=containerd",
                "export SKIP_SECURITY_FIX=true",
                "export KUBE_VERSION=1.30.1-aliyun.1",
                "export OS_ARCH=amd64",
                "export MOUNT_RUNTIME_DATADISK=true",     # 将容器运行时的文件路径挂载到数据盘
                "bash /root/ack-optimized-os-linux3-all.sh",
                "ctr -n k8s.io i pull registry-cn-hangzhou-vpc.ack.aliyuncs.com/acs/pause:3.9",        # 将业务镜像固化到系统镜像中。
                "mv /var/lib/containerd /var/lib/container/containerd"       # 将镜像文件移动到数据盘
            ]
        }
      ]
    }配置节点池时,您可以配置包含数据盘快照的自定义镜像,系统会自动关联对应的数据盘快照。

Runtime为Docker时拉取私有仓库镜像
docker login <镜像地址> -u user -p password
docker pull nginxRuntime为containerd时拉取私有仓库镜像
ctr -n k8s.io i pull --user=username:password nginx自定义镜像构建拉取私有仓库镜像
- 在已安装完成Docker的Linux机器上,执行如下 - docker login命令,生成证书。- docker login --username=zhongwei.***@aliyun-test.com --password xxxxxxxxxx registry.cn-beijing.aliyuncs.com- docker login成功后,会在- /root/.docker下生成证书config.json。 
- 将生成的config.json文件制作成ConfigMap。 - 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)" } }
- 修改Job的YAML,将ConfigMap挂载到Pod中。  
- 修改build-config,增加图中所示内容。  
- 执行Job。 
设置镜像上传、下载并发数
- 登录容器服务管理控制台,在左侧导航栏单击集群列表。 
- 在集群列表页面,单击目标集群名称,然后在左侧导航栏,选择。 
- 单击目标节点池名称,然后单击基本信息页签,在节点池信息区域,单击弹性伸缩 ESS 伸缩组 的链接。 
- 单击实例配置来源页签,然后在操作列单击目标伸缩配置右侧的修改,单击确定。 
- 在修改伸缩配置页面,修改相关配置项并展开高级设置,记录实例自定义数据区域的内容。使用Base64编码方式解密实例自定义数据框中的数据。 
- 解密完成后,将以下代码加入解密后代码的后面。 - 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 
- 使用Base64编码方式加密合成的代码,用加密后的代码替换原来实例自定义数据框中的代码,单击修改,然后单击确认修改。 
制作Alibaba Cloud Linux 3自定义镜像
制作Red Hat Enterprise Linux 9自定义镜像
后续操作
- 您可以基于自定义镜像创建节点池,请参见如何基于创建好的ECS实例创建自定义镜像,并使用该镜像创建节点?。 
- 关于如何基于自定义镜像扩容节点,请参见启用节点自动伸缩。