镜像即代码:使用 Packer 实现自动化构建镜像

2019 年 11 月 10 日

镜像即代码:使用 Packer 实现自动化构建镜像

云主机是用户使用最高频的云产品之一。随着云主机数量的增多,如何在云主机中保证版本化部署的一致性,成为用户常见的难题。在现有情况下,用户首先需要手动或使用脚本连接主机,然后再进行部署安装,操作流程复杂且对环境要求苛刻,难以保证一致性和可用性。


为了解决此类问题,UCloud 开发了相关代码,并被自动化构建镜像工具 Packer 的官方仓库所采纳。通过 Packer 创建自定义镜像,可以减少部署时间并提高可靠性,提高了用户自动化部署的能力。8 月 14 日,Hashicorp 官方正式发布了版本 1.4.3 ,其中包括了 UCloud Packer Builder。



Packer 是什么?


Packer 是 Hashicorp 公司推出的自动化打包镜像的轻量级开源工具,云厂商通过构建自己的 Builder 集成到 Packer 中去,即可凭借单一配置文件,高效并行的为多云平台创建一致性的镜像。目前 Packer 已经形成完整生态,并与多家主流云厂商建立合作。



UCloud Packer 可以运行在常用的主流操作系统上,它不是 Chef、Puppet 等软件的替代品,而是集成并使用这些自动化配置工具在镜像上预装软件等。再配合 UCloud Terraform、UCloud CLI 等工具,可以在多云的 DevOps 场景下,实现基础设施即代码(IaC)、持续集成和快速交付。


如下图所示,Packer 通过在 Provisioner 中集成 Chef、Shell、Puppet 等工具,制作包含各类软件的不可变镜像,供多云平台的云主机、Docker 等使用。



Hashicorp 官方将 Packer 的优势描述如下:


  1. 基础架构迅速部署:Packer 镜像可以在几秒钟内启动完全配置的云主机,有利于生产和开发;


  1. 多提供商可移植性:Packer 可以为多云平台创建了相同的镜像,每个环境都能运行相同的机器镜像,提供最终的可移植性;

  2. 稳定性高:Packer 在构建镜像时会为机器安装和配置所有软件。如果脚本中存在错误,可以被提前捕获,而不是在启动计算机几分钟后;

  3. 可测试性高:Packer 在构建机器镜像后,可以快速启动该机器镜像并进行冒烟测试,以验证镜像是否正常工作。如果是正常工作,则可以确信从该镜像启动的任何其他计算机都能正常运行;

  4. 可扩展性高:Packer 的插件机制使得它能够自如的根据需求集成工具和拓展功能。


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



生命周期


利用 Packer 打包镜像的完整周期如下:



  1. 用户通过构建 JSON 模版,执行 packer build 命令调用 UCloud Builder;

  2. 参数提前校验保证可用性;

  3. 创建云主机、EIP 等相关临时资源(若配置为内网环境则无需 EIP);

  4. 通过 SSH 或 WinRM 等连接主机,执行 Provisioner 进程;

  5. 关闭云主机,并创建镜像;

  6. 复制镜像;

  7. 删除主机、EIP 等临时资源;

  8. 执行后处理进程(如本地镜像导入等)。


使用演示


下面通过一个视频来形象地展示 Packer 的使用方式。目标是构建一个装有 nginx 应用的镜像,我们首先创建一个 test.json 文件,然后执行如下命令一键构建镜像:


packer build test.json
复制代码


Packer 对多云管理的价值


在此次 Hashicorp 官方发布前,UCloud 内部已经积累了一定的 Packer 使用经验。从中发现,如果需要管理多云环境,或者要在公有云与私有云间维护相同的系统,又或者构建的是虚拟机而不是容器,Packer 都是一个很好的选择。


通过一个具体例子来说明。下面这段代码定义了一个 UCloud 公有云上的虚拟机镜像,Packer 利用 ucloud-uhost Builder 配置的参数,先创建一个干净的 CentOS 7 系统,再 ssh 执行 provisioner 定义中指定的三段 shell 脚本,最终成功创建镜像并返回镜像 ID。


{  "variables": {    "ucloud_public_key": "{{env `UCLOUD_PUBKEY`}}",    "ucloud_private_key": "{{env `UCLOUD_SECRET`}}",    "ssh_user": "root",    "ssh_password": "password",    "ucloud_project_id": "org-projectid",    "image_id": "uimage-dpdgyw",    "consul_version": "1.5.1",    "region": "cn-bj2",    "az": "cn-bj2-02"  },  "builders": [    {      "type": "ucloud-uhost",      "public_key": "{{user `ucloud_public_key`}}",      "private_key": "{{user `ucloud_private_key`}}",      "project_id": "{{user `ucloud_project_id`}}",      "region": "{{user `region`}}",      "availability_zone": "{{user `az`}}",      "instance_type": "n-basic-2",      "source_image_id": "{{user `image_id`}}",      "ssh_username": "{{user `ssh_user`}}",      "ssh_password": "{{user `ssh_password`}}",      "image_name": "consul-server-{{user `consul_version`}}"    }  ],  "provisioners": [    {      "type": "shell",      "scripts": [        "scripts/config-yum.sh",        "scripts/consul-service.sh",        "scripts/consul-server.sh"      ],      "environment_vars": [        "CONSUL_VERSION={{user `consul_version`}}"      ]    }  ]}
复制代码


此时若有额外需求,要求将其也部署到私有云的 Kubernetes 上,该怎么办?一种方法是把 shell 脚本改写成对应的 Dockerfile,但若是构建过程非常复杂,那么改写的过程也会很复杂,并且可能引入错误。


但用 Packer,只需要修改一下 builder 配置的细节:


{  "variables": {    "consul_version": "1.5.1"  },  "builders": [    {      "type": "docker",      "image": "centos:7",      "commit": true,      "changes": [        "CMD [\"tail -f /dev/null\"]",        "ENTRYPOINT [\"\"]"      ]    }  ],  "provisioners": [    {      "type": "shell",      "scripts": [        "scripts/config-yum.sh",        "scripts/consul-service.sh",        "scripts/consul-server.sh"      ],      "environment_vars": [        "CONSUL_VERSION={{user `consul_version`}}"      ]    }  ],  "post-processors": [    [      {        "type": "docker-tag",        "repository": "lonegunmanb/consulServer",        "tag": "0.1"      },      "docker-push"    ]  ]}
复制代码


在公有云平台上已经过测试的构建脚本,就可以直接用来构建 Docker 镜像,并且在构建完成后,自动打上 tag,push 到 Docker Hub 仓库去。并且,由于 Packer 是执行完 provisioner 后,通过 docker commit 的方式构建镜像,所以 Packer 的构建只会增加额外的一个层,避免不恰当的 Dockerfile 增加多个层的问题。


Packer +Terraform,1+1>2


Packer 配合 Git、Terraform、UCloud CLI 等使用,可以实现 DevOps 下的基础设施即代码(IaC),达到持续集成和快速交付。


如下图,Packer 配合 Git 对镜像的配置文件做版本化控制,从而来实现服务的版本化,保证了实例的最终一致性,然后利用 Packer 和 Terraform 自动化构建服务的目的。



  1. 在自动化流程中,首先变更镜像配置仓库,触发执行 Terraform 命令;

  2. Terraform 执行 packer build 命令构建镜像;

  3. 将制作成功的镜像查询给 Terraform 使用;

  4. 最后由 Terraform 构建并启动新实例替换原有的旧实例,完成服务自动化部署。


UCloud 此前已提供对 Terraform 的官方集成,可通过产品文档了解更多详情。文档链接:https://docs.ucloud.cn/compute/terraform/index


总结


UCloud 通过对 Packer 的接入,提供了一种在云主机中自动化配置环境的能力,而且它可以配合 cloud-init 及一些常用的自动化部署软件使用,进一步拓展功能。另外,通过配合 UCloud Terraform 、UCloud CLI 等工具,可以实现对基础架构的版本化和代码化管理,达到精准交付和快速部署以及最终一致性。


本文转载自公众号 UCloud 技术(ID:ucloud_tech)。


原文链接:


https://mp.weixin.qq.com/s/4uLr4ley0pe3RgUEqq8TBw


2019 年 11 月 10 日 23:30519

评论

发布
暂无评论
发现更多内容

中年架构师,悲催的一天,全靠忍!

四猿外

Java 程序员 程序人生 架构师

一个你不得不重视的趋势,而且数据会让你很诧异

非著名程序员

个人成长 短视频 自媒体

个人精简xml,实现mybatis存取blob类型数据(Mysql)

小Q

Java MySQL 学习 面试 mybatis

浅析 Golang 垃圾回收机制

郭旭东

go golang

MySQL-技术专题-主从复制原理

李浩宇/Alex

阿里P8架构师得意弟子,应聘华为Java岗居然一面就失败了?

Java架构师迁哥

上线GitHub七天后就标星87.6K的Java大牛成长宝典,啃完之后成功面进字节!

Java架构追梦

Java 学习 架构 面试 核心知识点

上周,我密集面试了若干位Java后端的候选人,工作经验在3到5年间

Java架构师迁哥

MySQL-技术专题-MySQL中的锁机制

李浩宇/Alex

十一、给小白看的最后一篇Python基础教程

刘润森

Python

亿级数据库毫秒级查询?看完这一篇,海量数据赋能你也行

京东智联云开发者

MySQL 数据库

Go语言小规范

小高

阿里内部绝密《百亿级并发系统设计》实战教程,冒着被劝退的风险免费分享

Java架构之路

Java 阿里巴巴 程序员 面试 编程语言

MySQL-技术专题-MySQL MVCC实现机制

李浩宇/Alex

LeetCode题解:590. N叉树的后序遍历,栈,JavaScript,详细注释

Lee Chen

LeetCode 前端进阶训练营

十二、深入Python列表和元组

刘润森

Python

你掉进过“伪敏捷”的陷阱吗?

华为云开发者社区

项目管理 软件 敏捷

Presto在滴滴的探索与实践

滴滴技术

开源项目 滴滴技术 滴滴开源 presto

2020亚马逊全球Prime会员日为会员节省金额超过14亿美金

爱极客侠

拯救深度学习:标注数据不足下的深度学习方法

华为云开发者社区

学习 AI 训练

本周学习总结

饺子

塞上江南之旅

谋生亦谋爱

美食 旅行

【人人都懂密码学】一篇最易懂的Java密码学入门教程

华为云开发者社区

加密 密码

MySQL-技术专题-SQL优化系列

李浩宇/Alex

Vidyo整个产品架构是怎样的?

dwqcmo

音视频会议 集成架构 解决方案 智能硬件

大型互联网应用系统的技术方案和手段

饺子

六年Java老鸟,写给1-3年程序员的几点建议,满满干货指导

周老师

Java 编程 程序员 架构 面试

看看专科程序员与本科程序员之间,到底有什么区别?

Java架构师迁哥

LeetCode题解:589. N叉树的前序遍历,栈,JavaScript,详细注释

Lee Chen

LeetCode 前端进阶训练营

金秋十月游记

Xuhehui

美食 旅行

重磅推荐!阿里巴巴技术专家认证的Java系统性能圣经,太香了

996小迁

Java 架构 面试 Java系统性能

镜像即代码:使用 Packer 实现自动化构建镜像-InfoQ