玩转云镜像制作之packer篇

1.DevOps之基础设施即代码(Infrastracture as Code)

        什么是DevOps呢?按照*的定义,DevOps(Development和Operations的组合词)是一种重视“软件开发人员(Dev)”和“IT运维技术人员(Ops)”之间沟通合作的文化、运动或惯例。透过自动化“软件交付”和“架构变更”的流程,来使得构建、测试、发布软件能够更加地快捷、频繁和可靠。

        在缺乏DevOps能力的组织中,开发与运营之间存在着信息“鸿沟”──例如运营人员要求更好的可靠性和安全性,开发人员则希望基础设施响应更快,而业务用户的需求则是更快地将更多的特性发布给最终用户使用。这种信息鸿沟就是最常出问题的地方。而DevOps的引入能对产品交付、测试、功能开发和维护(包括──曾经罕见但如今已屡见不鲜的──“热补丁”)起到意义深远的影响。

        DevOps包含四个核心的部分,文化、自动化、度量和分享,而本文的重点是自动化。自动化的目标是就是将整个交付流程尽其所能的自动化,当然也包含基础设施管理的自动化,这也就意味着你的基础设施的管理不是通过手工的方式或者执行脚本来完成,而在传统的IT环境下,基础的硬件环境和软件环境的设置作为基础设施的关键部分是很难自动化的,但是随着云计算的兴起,通过可以机器处理的定义文件而不是物理硬件配置或使用交互式配置来管理和派生计算基础设施(进程,裸机服务器,虚拟服务器等)及其配置的过程变得越来越流行,也就是通过代码来管理基础设施,而这就是所谓的基础设施即代码(Infrastracture as Code)简写为IaC。

        IaC相比传统的方式,具有以下优点:

  • 自服务性-如果基础设施是通过代码定义的时候,那么整个流程都可以做到自动了,开发人员在需要的时候就就可以自己发布,而不必等待运维人员来发布。
  • 快捷而安全-由于整个部署过种都是自动化的,计算机执行的速度比人更快而且更完全。
  • 文档化-在传统的方式下,基础设施的状态只存在于单个系统管理人员头脑中,而IaC以任何人都可以阅读的源代码的方式来保存基础设施的状态,也就说是源代码具有了文档的功能。
  • 版本管理-你还可以将你的IaC代码使用版本控制工具管理起来,也就意味着你的基础设施变更历史是可以追踪的,这样当出现问题的时候,就可以通过查找历史来快速的定位和诊断问题。
  • 可检验-因为基础设施的状态是以代码的形式管理的,这样任何变更都可以通过代码审查或者提前运行测试来检验。
  • 可重用-你还可以将你的代码封装成模块,这样当有不同需求的时候,你就可以组装不同的模块来完成你的工作,而不是所有的情况都需要重头开始。

2.IaC的基石,镜像制作

随着越来越多的人认识到IaC的优势,各式各样的IaC工具被开发出来,它们分为以下四类:

  • Ad Hoc Script
  • 配置管理工具
  • 服务模板工具
  • 编排工具

        作为一种最直接的方式,人们使用通用语言编写各种Ad Hoc的脚本语言来完成基础设施的自动化工作,这种方式对于简单,一次性的工作很方便,但是对于复杂和长期的项目,你会发现维护这些脚本是一场恶梦。于是象Chef,Puppet和Ansible等配置管理工具出现,它们在通用语言的基础上定义相应的语法规则来安装和管理服务器上的软件,这些工具定义的代码和Ad Hoc脚本语言非常相似,但是它们强制要求代码具有结构化,一致性,可预测性,文档化和清晰的参数命名,而且它们能够远程管理大量的服务器。随着虚拟化和云计算的兴起,Packer,Docker等服务模板工具出现,模板工具的背后是镜像,相比于启动大量的服务器,然后在使用配置管理工具运行同样代码来重复安装软件和设置系统,镜像技术只需要捕获一个完整服务器包含操作系统,软件,文件和配置等经检验过的状态快照,然后通过Terraform等编排工具基于镜像来快速的创建服务器,数据库等等,这极大的提高了基础设施创建和管理的效率,因此镜像技术构成了主流云平台不可缺少的组成部分,而作为基础设施创建的第一步,镜像制作自然而然的构成了IaC的基石。

3.镜像制作的利器Packer

        所谓的镜像,就是一个包含预先配置好操作系统和预装软件的静态单元,通过它可以快速的创建新的虚拟机运行实例,不同的平台支持不同的镜像格式,例如AWS的EC2支持AMIs,VMware支持VMDK/VMX,Alicloud的ECS支持RAW和VHD格式等等。各云平台都提供了大量的基础镜像供用户使用,但是随着云平台用户成熟度的增加,用户对镜像个性化的需要越来越强烈,同时出于商业的考虑,用户也希望自己的系统具有在不同云平台之间迁移的能力,当然也包含个性化的镜像迁移的能力。尽管各大云平台都提供了WEB界面工具使得用户可以手工创建自定义镜像,也开放了相应的API使得通过自动化的脚本来创建个性化的自定义镜像成为可能。但是都存在一定的局限性而难以满足用户的最终需求,Packer就在这种背景下诞生了。

3.1 Packer是什么

Packer是一个从单一的模板文件来创建多平台一致性镜像的轻量级开源工具,它能够运行在常用的主流操作系统如Windows、Linux和Mac os上,能够高效的并行创建多平台例如AWS、Azure和Alicloud的镜像,它的目的并不是取代Puppet/Chef等配置管理工具,实际上,当制作镜像的时候,Packer可以使用Chef或者Puppet等工具来安装镜像所需要的软件。通过Packer自动化的创建各种平台的镜像是非常容易的。

使用Packer来创建镜像有如下优点:

  • 基础设施部署讯捷:Packer镜像允许您在几秒钟内启动完成配置和已配置的机器,而不是几分钟或几小时。 这不仅有利于生产,也有利于开发,因为开发虚拟机也可以在几秒钟内启动,而无需等待通常更长的配置时间。
  • 可移植性:因为Packer为多个平台创建相同的映像,您可以在Alicloud中运行生产,在像OpenStack的私有云中分阶段测试,以及在桌面虚拟化解决方案(如VMware或VirtualBox)中开发。 每个环境运行相同的机器映像,提供最终的可移植性。
  • 稳定性的改进:Packer在构建映像时安装和配置机器的所有软件。 如果这些脚本中有错误,它们将被早期捕获,而不是在启动机器后几分钟。
  • 更好的可测试性: 在构建机器映像之后,可以快速启动该机器映像,并且通过冒烟测试以验证镜像是可以正常工作的。
  • 良好的可扩展性: Packer使用插件机制,可以很方便的根据需要来扩展功能,并与许多流行的技术和工具集成。
  • 是HashiCorp公司生态系统的一部分

3.2 Packer的组成及及原理

Packer包含构建器(Builder),(派生器)Provisioner,(后处理器)Post-Processor三个组件,通过JSON格式的模板文件,可以灵活的组合这三种组件并行的、自动化的创建多平台一致的镜像文件。为单个平台生成镜像的单个任务称为构建,而单个构建的结果也称为工件(Artifact),多个构建可以并行运行。

  • Builder又称构建器,能够为单个平台创建镜像。构建器读取一些配置并使用它来运行和生成镜像。作为构建的一部分调用构建器以创建实际生成的镜像。常见的构建器包括VirtualBox,Alicloud ECS和Amazon EC2。构建器可以以插件的形式创建并添加到Packer中。
  • Provisioner(派生器),这一组件在Buider创建的运行的机器中安装和配置软件。他们执行使镜像包含有用软件的主要工作。常见的派生器包括shell脚本,Chef,Puppet等。
  • Post-Processors(后处理器),它使用构建器或另一个后处理器的结果来创建新工件的过程。例如压缩后处理器压缩工件,上传后处理器上传工件等。

Packer创建镜像的原理其实并不复杂,以阿里云的镜像创建过程为例:
玩转云镜像制作之packer篇

  • 1.阿里云构建器读取配置文件,根据配置文件定义,通过阿里云提供的API提交创建相应的ECS实例,配置网络和安全规则的请求。
  • 2.阿里云控制系统根据API请求创建ECS实例,配置好网络和安全规则等等。
  • 3.派生器读取配置文件,通过SSH或者WINRM等远程协议连接上ECS实例,按照模板文件的要求安装和配置软件。
  • 4.当ECS实例安装和配置好所需要的软件之后,构建器发出捕获实例状态创建镜像的请求。
  • 5.阿里云控制系统根据请求创建镜像,创建过程完成后或者创建的过程中有任何错误发生,构建器会根据配置模板的要求来保留或者清除相应的临时资源。
  • 6.如果配置有后处理器,可以对前面步骤产生的镜像作进一步的处理,例如通过packer-post-processor-alicloud-import后处理器,可以将本地的镜像导入到ECS镜像系统中

在了解了Packer的原理和优势之后,我们就可以通过实践来学习如何使用它来创建自己的镜像。

3.3 Packer的安装

首先从Packer官网(https://www.packer.io/downloads.html)下载对应操作系统的安装包,本文以Mac OS X x64为例,点击如下图的官网链接(https://releases.hashicorp.com/packer/0.12.3/packe_0.12.3_darwin_amd64.zip )下载packer安装包玩转云镜像制作之packer篇

然后打开终端,导航到下载目录下,执行如下命令,如果得到如下图的输出,packer就安装好了:

#unzip packer_0.12.3_darwin_amd64.zip
#sudo mv packer /usr/local/bin/
#packer
usage: packer [--version] [--help] <command> [<args>]

Available commands are:
    build       build image(s) from template
    fix         fixes templates from old versions of packer
    inspect     see components of a template
    push        push a template and supporting files to a Packer build service
    validate    check that a template is valid
    version     Prints the Packer version

由于阿里云的packer插件提交还在流程中,所以还需要从阿里云的开源工具站点(https://github.com/alibaba/opstools)下载阿里云的packer插件(https://github.com/alibaba/packer-provider/releases/download/V1.1/packer-builder-alicloud-ecs_darwin-amd64.tgz),然后执行如下命令,如果输出如下,插件就安装好了:

#tar -xvf  packer-builder-alicloud-ecs_darwin-amd64.tgz
#sudo mv bin/packer-builder-alicloud-ecs /usr/local/bin/
# ls /usr/local/bin | grep packer

packer   packer-builder-alicloud-ecs   packer-post-processor-alicloud-import

3.4 Packer实例

下面通过创建一个包含Redis数据库的镜像的简单实例来学习如何使用Packer。

    1. 首先打开常用的文件编辑器,输入如下内容,将其中<<...>>部分替换成你自己的实际值,并且存储为alicloud.json模板文件:
{
  "builders": [{
    "type":"alicloud-ecs",
    "access_key":"<<Your Access Key>>",
    "secret_key":"<<Your Secret Key>>",
    "region":"cn-beijing",
    "image_name":"packer_basic",
    "source_image":"centos_7_2_64_40G_base_20170222.vhd",
    "ssh_username":"root",
    "instance_type":"ecs.n1.tiny",
    "io_optimized":"true"
  }],
  "provisioners": [{
    "type": "shell",
    "inline": [
      "sleep 30",
      "yum install redis.x86_64 -y"
    ]
  }]
}
    1. 打开命令行终端,输入如下命令:
# packer build aliclouod.json
alicloud-ecs output will be in this color.

==> alicloud-ecs: Prevalidating alicloud image name...
    alicloud-ecs: Found image ID: centos_7_2_64_40G_base_20170222.vhd
==> alicloud-ecs: Start create alicloud vpc
==> alicloud-ecs: Start creating vswitch...
==> alicloud-ecs: Allocated alicloud eip 47.93.55.94
==> alicloud-ecs: Connected to SSH!
==> alicloud-ecs: Provisioning with shell script: /var/folders/
3q/w38xx_js6cl6k5mwkrqsnw7w0000gn/T/packer-shell077409543
    alicloud-ecs: Loaded plugins: fastestmirror
    alicloud-ecs: Determining fastest mirrors
    .......................
    alicloud-ecs: Installed:
    alicloud-ecs: redis.x86_64 0:3.2.3-1.el7
    ......................
    alicloud-ecs: Complete!
==> alicloud-ecs: Start delete alicloud image snapshots
==> alicloud-ecs: Clean the created VPC
Build 'alicloud-ecs' finished.

==> Builds finished. The artifacts of successful builds are:
--> alicloud-ecs: Alicloud images were created:

cn-beijing: m-2zehwk9as9ed3yna7pq0
    1. 十几分钟后,你就可以在自定义镜像列表里看到刚刚创建好的镜像packer_basic

玩转云镜像制作之packer篇

4.阿里云的Packer插件开发

阿里云的插件开发起步较晚,虽然已经向官方提交了PR,但是还没有合并的主流中去,所以目前只能以外挂的插件方式运行,当前已经支持从基础镜像创建新的自定义镜像和上传本地基于KVM创建的镜像到ECS镜像列表,现在国内对于Packer插件的文档也比较少,如果读者需要更详细的实战资料,可以参考如下两篇博客,也欢迎读者能够在阿里云Packer官方插件资源库提出需求或者贡献力量。

5. Packer应用场景分析

应用场景1:

官方提供的基础镜像只能提供有限的操作系统版本组合,而有些专有云用户需要特定版本的操作系统镜像,通过工单的形式周期过长,用户难以接受,而由用户自己制作基础镜像的不但技术要求高,从本地上传到镜像列表的操作也很复杂,用户很难制作出能够正常运行的基础镜像,而使用packer,其post-processor能够自动的将本地镜像上传到镜像列表中,通过提供一些基础模板,用户只需要修改模板文件的源ISO,就可以创建出指定版本的基础镜像,极大的降低了镜像制作的门槛。

应用场景2:

在镜像市场中有许多第三方镜像,ISV制作镜像中包含的内容是什么,对阿里云及用户都是不透明的,我们无法清晰的看到镜像中是否有隐患或不安全的内容,为了确保安全,只能进行大量的安全扫描,一方面,使得ISV发布镜像的周期较长,另一方面,通过扫描二进制文件,很难完全避免安全风险。而通过packer模板文件制作的镜像,我们可以清晰的看到脚本中执行的命令,相比二进制文件,安全扫描也容易得多,而且也方便ISV做镜像的版本管理,以及多平台的镜像制作,提高镜像制作的效率,不需要ISV一遍一遍的手工制作。

应用场景3:

在弹性伸缩(ESS)中,镜像的生成是否方便高效起着重要的作用,当检测到工作负载达到阀值的时候,需要使用镜像来生成新的实例,当弹性伸缩的应用数量达到一定规模的时候,通过手工来创建镜像是难以接受的。特别是当需要升级应用时,如果使用传统的方式,直接在运行时实例上在线升级应用,一方面,在线升级的速度较慢,而且会影响在线用户的检验,另一方面,当出现错误的时候,回滚也比较困难,很容易形成较长时间的当机,而采用Packer,结合Jenkins和Terraform等工具,能够将应用的从代码到镜像升级,产生更新后实例的过程完全自动化。当Jenkins检测到有代码提交时,可以触发Packer根据模板使用更新后代码创建新的镜像,然后Jenkins触发Terraform来创建新ECS实例,将新实例加入伸缩组,并将旧实例移出伸缩组,这样就完成了应用的更新,当检测到新代码出现问题的时候,又可以将旧实例重新加入伸缩组而移除新实例来完成回滚。

6.展望

诚然,引入新的机制,会引入相应的学习曲线,对于packer来说,编写可用的镜像模板文件不是一件简单的事情,但是随着开源的盛行,很多常用的的模板都能够从github上找到,例如如下资源库(https://github.com/chef/bento)中就包含大量的模板,当然,由于阿里云的packer插件支持才刚刚起步,所以也欢迎大家以阿里云官方packer插件资源库(https://github.com/alibaba/packer-provider)来贡献一份力量。

参考文献

DevOps https://zh.wikipedia.org/wiki/DevOps

OReilly Terraform Up & Running

https://www.packer.io/docs/

上一篇:在SQL Server2005中进行错误捕捉


下一篇:J2SE5.0中最有趣的新特性:注释(annotation)