10 倍效率提升!Packer 解决 UCloud 罗马跨云商镜像复制问题 | U刻
技术分享/

10 倍效率提升!Packer 解决 UCloud 罗马跨云商镜像复制问题

  • 10 倍效率提升!Packer 解决 UCloud 罗马跨云商镜像复制问题

    如今多云部署日趋普遍,它在帮用户提高业务可用性、降低故障风险的同时,也带来了多云平台网络互通的问题。为了给用户提供可无缝连接的多云网络加速服务,UCloud 推出了罗马 Rome 产品。

    在罗马的多云网络建设过程中,我们发现了传统镜像制作在跨云平台环境下的诸多弊端,最终通过结合 Packer 的使用,成功解决了不同云商镜像格式不一致带来的镜像复制成功率不可控、持续交付效率低等问题。使用 Packer 之后,交付时间仅为原来的十分之一,大幅提高了罗马在新地域的接入效率,给用户更好的使用体验。

    此罗马非彼 “罗马”

    罗马 Rome 是 UCloud 覆盖全球多家知名云商 20 多个数据中心的跨云网络加速产品,可用于跨数据中心应用互访、中间件和底层数据库的同步等场景。其底层核心由分布在不同数据中心的若干个转发点组成的一张大网、负责用户就近接入端和动态链路调度等服务组成,旨在为用户提供跨云商高稳定性低延时的网络互通。

    Packer VS 传统镜像制作

    由于罗马全球接入的特性,要求核心转发和接入端服务要多云商、跨地域部署,同时还要保证接入端生产环境代码和镜像代码一致。传统镜像的制作流程非常依赖人工在云厂商的控制台重复手动操作,因此用于租户隔离的接入端服务更新、保证新用户接入端代码和生产环境服务代码的一致等,都需要对罗马的接入端镜像进行重新制作、分发。但是各家云商镜像格式的不一致,导致罗马跨云商镜像复制效率低的问题就显得格外突出。

    而 Packer 的出现,正好能完美解决此类问题。

    Packer 是 HashiCorp 公司推出的自动化打包镜像的轻量级开源工具,云厂商通过构建自己的 Builder 集成至 Packer,即可凭借单一配置文件,高效并行的为多云平台创建一致性的镜像。UCloud 开发的相关代码已被自动化构建镜像工具 Packer 的官方仓库所采纳,8 月 14 日 Hashicorp 官方发布的版本 1.4.3 中就包括了 UCloud Packer Builder。

    | 下图是多云场景下传统镜像制作和 Packer 制作镜像的流程对比:

    | Packer 与传统控制台创建镜像的对比:

    当罗马遇上 Packer

    Packer 目前可以支撑 UCloud 罗马 Rome 产品接入、转发服务跨多家云商几十个地域的镜像制作。针对其跨云商跨数据中心跨地域的场景下,如何将每个开发人员的本地命令行式操作、Packer template 的版本控制以及接入端服务代码编译发布结合起来提供一套完整通用的页面化的自动构建镜像方案呢?

    答案是:GitLab+Jenkins+Packer+Terraform 自动构建镜像方案。

    上图所示的 CI/CD 流程分别是代码编译 -> 镜像打包 -> 应用交付,具体步骤如下:

    1、自动化构建多云镜像流程中,将 Packer template 和业务代码托管到 GitLab;2、触发 Jenkins 构建业务代码 生成发布文件;3、Jenkins 分环境声明多云商的公私钥供 Packer 使用,调用 Packer 并行构建 template ;4、Packer 首先会根据 template 声明的 base image 在目标地域自动创建虚拟主机并绑定弹性 IP 等,然后顺序执行 template 中 provisioners 代码块,最后生成 template 定义的镜像并清理上述临时资源,结果返回目标地域对应的镜像 id;5、Terraform 获取步骤 4 生成目标地域对应的镜像 id 创建主机。

    | 使用 Packer 前后效果对比

    经过我们的测试表明,传统方法完成单个应用跨 2 个云商 20 多个数据中心的镜像制作和复制需要 4-5 个小时,而 Packer 完成上述同等任务只需要 20-30 分钟,效率大幅提升,耗时和效率对比如图所示:

    使用 Packer 在罗马中进行自动化构建镜像的方案,也适用于用户业务的多云部署、跨云灾备的场景。因为使用传统镜像复制,不仅对环境的一致性要求苛刻且操作流程复杂。通过 Packer 创建自定义镜像,就可以将人工在控制台创建虚拟主机和制作镜像的繁琐操作,以简明易懂的配置模板化、自动化,减少部署时间的同时提高可靠性。

    如何在本地使用 Packer

    1、Packer 工具包安装、设置云商准入的 Public/Private Key

    curl -Ls https://releases.hashicorp.com/packer/1.4.4/packer_1.4.4_linux_amd64.zip -o packer.zip && unzip packer.zip && mv packer /usr/local/bin/export UCLOUD_PUBLIC_KEY=“对应UCloud账号API密钥Public Key"export UCLOUD_PRIVATE_KEY="对应UCloud账号API密钥Private Key"export UCLOUD_PROJECT_ID="对应UCloud账号ID"
    

    2、编写 Packer template {example.json} 文件

    template 文件由三部分组成。

    • variables 代码块

    定义云商 Packer 准入权限、使用 export 设置系统环境变量声明云商的 Public/Private Key。

     "variables": { "ucloud_public_key": "{{env `UCLOUD_PUBLIC_KEY`}}", "ucloud_private_key": "{{env `UCLOUD_PRIVATE_KEY`}}", "ucloud_project_id": "{{env `UCLOUD_PROJECT_ID`}}", "access_key": "{{env `ALICLOUD_ACCESS_KEY`}}", "secret_key": "{{env `ALICLOUD_SECRET_KEY`}}" },
    
    • builders 代码块

    定义目标 region、可用区、使用机型、云商源镜像 id 以及 生成镜像的名称等。

     "builders": [{ "name":"cn-bj2", "type":"ucloud-uhost", "public_key":"{{user `ucloud_public_key`}}", "private_key":"{{user `ucloud_private_key`}}", "project_id": "{{user `ucloud_project_id`}}", "region":"cn-bj2", "availability_zone": "cn-bj2-05", “instance_type":"n-basic-2",//云商提供对应操作系统版本的源镜像id,也是Packer创建临时主机所用的基础镜像 “source_image_id":"uimage-y11zpg", //云主机登录的用户名和对应操作系统的权限 “ssh_username":"root", //生成镜像的名称 “image_name":"appName_{{timestamp}}", //对应控制台的镜像复制功能 "image_copy_to_mappings": [ { "project_id":"projectId", "region": "cn-sh2", "name": "appName_{{timestamp}}", "description": "appName_{{timestamp}}" } ] }],
    

    • provisioners 代码块:

    在源镜像基础上定义我们要执行的操作例如初始化环境脚本、和部署服务代码等。

     "provisioners": [ //代码块定义使用provisoners类型为shell,script 声明环境初始化脚本的路径、上传到Packer自动创建的云主机并执行该脚本初始化服务运行所需的环境 { "type": "shell", "script": “scripts/init.sh" },// 代码块 定义我们要上传的部署文件源/目的路径 { "type": "file", "source": "../../deployFile", "destination": "/home/admin/" } ]}
    

    最终,三段代码块组成一个完整的 template 文件,其中 builders 代码块可以按不同云商定义多个。

    3、根据 Packer template 执行 Packer build 生成镜像文件

    • packer build —parallel-builds=100example.json// 并发 100 构建镜像
    • console log 可以清晰的知道 Packer 的执行逻辑,与模板的结构一致。

    (1)校验权限、地域、可用区、源镜像;(2)如模板文件中没有显式指定则使用缺省 vpc、subnet|、security group 创建主机并绑定弹性 ip;(3)执行 provision 代码块 上传服务文件和服务环境初始化脚本同时执行脚本;(4)生成 builders 代码块定义的镜像、镜像制作完成、清理步骤②创建的临时资源;(5)返回目标项目、地域对应的镜像 id。

    过程中遇到的问题及解决

    虽然 Packer 的出现确实解决了罗马跨云跨地域镜像复制的问题,但整个过程也遇到了一些 Bug 并最终得以解决,我们总结下来主要有以下几种:

    1、控制台没有对外暴露 builders 代码块所需的目标地域的源镜像 id

    对应方案:我们可以借助 UCloud 控制台 UAPI 产品 中云主机 UHost 的 DescribeImage 接口获取对应操作系统版本的 Base 镜像 id(需要注意接口的 Limit 参数定义了返回数据的长度,默认为 20 可适当调整)。

    2、由于镜像和主机类型不匹配导致 Packer 使用 Base 镜像创建主机资源异常

    对应方案:云商硬件限制短时间内无法 bugfix, 好在 Packer builders 的 image_copy_to_mappings 选项实现了类似控制台镜像复制的功能可以在没有受限的临近地域生成镜像并拷贝到目标地域,曲线实现目标地域的镜像制作。

    3、因为部分地域不支持 boot_disk_type 为 cloud_ssd 导致的 Packer 创建主机异常

    对应方案:Packer 创建主机默认使用 cloud_ssd 产品,显式指定 Packer builders 的 boot_disk_type 为 local_normal 或 local_ssd。

    4、 Packer 在 Builders 数组代码中定义同一厂商多个地域时模板转换异常

    具体错误为:{builder 2: builder with name ‘Image Builder Type’ already exists}。对应方案:修改 Packer template builders 数组内数据条目,增加 name 属性。

    总 结

    Packer 在罗马多云建设过程中提高了镜像制作和镜像分发的效率和成功率,从而进一步提高了罗马新地域的接入效率,保证了新接入用户限流、路由策略等特性和生产环境的一致。目前,UCloud 已经与 Packer 官方建立了合作,用户可直接使用官方集成的 UCloud Packer Builder,再配合 UCloud Terraform、UCloud CLI 等工具,实现多云 DevOps 场景下的基础设施即代码(IaC)、持续集成和快速交付。