通过Packer,您只需在JSON配置文件中指明构建镜像所需的基本信息、以及需要安装到镜像中的软件及配置,即可自动化构建ECS镜像。

前提条件

使用本教程进行操作前,请确保您已经注册了阿里云账号。如还未注册,请先完成账号注册

背景信息

Packer是HashiCorp推出的一款镜像工具,旨在通过简易的方式自动化构建镜像。由于构建镜像的过程以一份JSON配置文件为准,您无需担心多次构建的镜像不一致。Packer还能为测试和更新镜像带来使用便利,降低运维和管理镜像的时间成本。更多详情,请访问Packer官网

操作条件

本文通过比较“使用实例创建自定义镜像”和“使用Packer构建自定义镜像”的操作流程,突出Packer在DevOps场景中的优势。以下为本次操作的假设场景和一致性条件:

  • 目标地域:阿里云华北2(北京)地域,更多详情,请参见地域和可用区
  • 操作系统:CentOS 7.3 64位。本文两种方式均采用公共镜像centos_7_03_64_20G_alibase_20170818.vhd,您可以在ECS管理控制台或调用DescribeImages查询其他操作系统的镜像ID列表。
  • 自定义服务:redis。
  • 是否保留临时资源:否。
说明 本文操作会创建计费资源,请注意释放和清理。如实例、公网IP、快照等。

使用实例创建自定义镜像

本示例介绍如何通过ECS管理控制台创建一份自定义镜像。

  1. 登录ECS管理控制台
  2. 在左侧导航栏,单击实例与镜像 > 实例
  3. 在顶部状态栏左上角处,选择地域。
  4. 创建实例。具体操作请参见使用向导创建实例
    为较少费用消耗和简化操作流程,您可以选择以下配置:
    • 计费方式:按量付费。更多详情,请参见按量付费
    • 实例规格:ecs.t5-lc1m1.small。更多详情,请参见实例规格族
    • 公共镜像:CentOS 7.3 64位。
    • 专有网络:默认VPC。
    • 安全组:默认安全组。
    • 公网带宽:如果不需要公网访问,可以选择不开通公网带宽,并通过管理终端远程连接实例。更多详情,请参见使用管理终端连接Linux实例
  5. 远程连接ECS实例。连接方式请参见连接方式导航
  6. 运行yum install redis.x86_64 -y安装redis服务。
  7. 返回ECS控制台,选择华北2(北京)地域。
  8. 创建一份镜像。具体操作,请参见使用实例创建自定义镜像
  9. 在左侧导航栏,单击实例与镜像 > 镜像
  10. 镜像列表页面查看镜像完成状态。
  11. 可选: 镜像制作成功后,请释放临时资源,包括实例等。若您使用的是弹性公网IP,也可以选择释放。

使用Packer构建自定义镜像

您已经安装了Packer。关于如何安装Packer,请参见Packer官方文档或者阿里云文档使用Packer构建自定义镜像。完成以下操作,使用Packer构建自定义镜像:

  1. 本地新建一份alicloud.json文件,文件内容如下:
    {
      "variables": {
        "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":"cn-beijing",
        "image_name":"packer_basic",
        "source_image":"centos_7_03_64_20G_alibase_20170818.vhd",
        "ssh_username":"root",
        "instance_type":"ecs.t5-lc1m1.small",
        "internet_charge_type":"PayByTraffic",
        "io_optimized":"true"
      }],
      "provisioners": [{
        "type": "shell",
        "inline": [
          "sleep 30",
          "yum install redis.x86_64 -y"
        ]
      }]
    }
    表 1. Packer参数解释
    参数 示例值 参数解释
    variables{"varible1":"value"} variables{"access_key":"{{env `ALICLOUD_ACCESS_KEY`}}"} 定义了builders中会用到的变量(variables)。将AccessKey(access_key和secret_key)信息写入配置文件有信息泄露的风险,设置成变量后可防止意外,变量的值取自运行时的输入值。
    builders{"type":"value"} builders{"type":"alicloud-ecs"} Packer定义的镜像生成器(builders)。阿里云支持alicloud-ecs,又称Alicloud Image Builder,用于在阿里云ECS创建自定义镜像。
    provisioners{"type":"value"} provisioners{"type":"shell"} Packer定义的镜像配置器(provisioners),用以定义需要在临时实例内执行的操作。本文使用的是Shell Provisioner,表示在连接Linux实例后自动执行一段shell命令(如yum install redis.x86_64 -y)安装redis服务。
    表 2. 阿里云参数解释
    参数 数据类型 示例值 参数解释 重要度
    access_key String LTAInPyXXXXQXXXX 您的AccessKeyID。更多详情,请参见创建AccessKey
    说明 由于AccessKey权限过大,为防止错误操作,建议您创建RAM用户,并使用RAM子账号创建AccessKey。更多详情,请参见创建RAM用户
    secret_key String CM1ycKrrCekQ0dhXXXXXXXXXl7yavUT 您的AccessKeySecret。
    region String cn-beijing 目标自定义镜像的所属地域。更多详情,请参见地域和可用区
    image_name String packer_basic 目标自定义镜像的名称。不允许与已有镜像重名。
    source_image String centos_7_03_64_20G_alibase_20170818.vhd 具有相同操作系统的阿里云公共镜像ID。
    instance_type String ecs.t5-lc1m1.small 创建自定义镜像时使用的临时实例的实例规格。更多详情,请参见实例规格族
    internet_charge_type String PaybyTraffic 临时实例的公网带宽付费类型。建议设置为按流量付费(PaybyTraffic)。
    io_optimized Boolean true 临时实例的I/O优化属性。建议设置为I/O优化(true)。
  2. 执行以下命令构建一份镜像:
    packer build alicloud.json
    说明 构建镜像是相对耗时的任务,请您耐心等待。镜像构建成功后,会出现在相应阿里云地域中,您可以通过ECS控制台或DescribeImages查看。

    构建镜像时会产生的操作日志。日志给出了构建过程中执行的每一个步骤,包括校验参数、创建临时资源、预安装软件、创建目标资源和释放临时资源等。

    alicloud-ecs output will be in this color.
    
    ==> alicloud-ecs: Prevalidating image name...
        alicloud-ecs: Found image ID: centos_7_03_64_20G_alibase_20170818.vhd
    ==> alicloud-ecs: Creating temporary keypair: packer_xxx
    ==> alicloud-ecs: Creating vpc
    ==> alicloud-ecs: Creating vswitch...
    ==> alicloud-ecs: Creating security groups...
    ==> alicloud-ecs: Creating instance.
    ==> alicloud-ecs: Allocating eip
    ==> alicloud-ecs: Allocated eip xxx
        alicloud-ecs: Attach keypair packer_xxx to instance: i-xxx
    ==> alicloud-ecs: Starting instance: i-xxx
    ==> alicloud-ecs: Using ssh communicator to connect: ***
    ==> alicloud-ecs: Waiting for SSH to become available...
    ==> alicloud-ecs: Connected to SSH!
    ==> alicloud-ecs: Provisioning with shell script: /var/folders/k_/nv2r4drx3xxxxxxxxxxxndb40000gn/T/packer-shell260049331
        alicloud-ecs: Loaded plugins: fastestmirror
        alicloud-ecs: Determining fastest mirrors
        alicloud-ecs: Resolving Dependencies
        alicloud-ecs: --> Running transaction check
        alicloud-ecs: ---> Package redis.x86_64 0:3.2.12-2.el7 will be installed
        alicloud-ecs: --> Processing Dependency: libjemalloc.so.1()(64bit) for package: redis-3.2.12-2.el7.x86_64
        alicloud-ecs: --> Running transaction check
        alicloud-ecs: ---> Package jemalloc.x86_64 0:3.6.0-1.el7 will be installed
        alicloud-ecs: --> Finished Dependency Resolution
        alicloud-ecs:
        alicloud-ecs: Dependencies Resolved
        alicloud-ecs:
        alicloud-ecs: ================================================================================
        alicloud-ecs:  Package           Arch            Version                  Repository     Size
        alicloud-ecs: ================================================================================
        alicloud-ecs: Installing:
        alicloud-ecs:  redis             x86_64          3.2.12-2.el7             epel          544 k
        alicloud-ecs: Installing for dependencies:
        alicloud-ecs:  jemalloc          x86_64          3.6.0-1.el7              epel          105 k
        alicloud-ecs:
        alicloud-ecs: Transaction Summary
        alicloud-ecs: ================================================================================
        alicloud-ecs: Install  1 Package (+1 Dependent package)
        alicloud-ecs:
        alicloud-ecs: Total download size: 648 k
        alicloud-ecs: Installed size: 1.7 M
        alicloud-ecs: Downloading packages:
        alicloud-ecs: --------------------------------------------------------------------------------
        alicloud-ecs: Total                                              2.2 MB/s | 648 kB  00:00
        alicloud-ecs: Running transaction check
        alicloud-ecs: Running transaction test
        alicloud-ecs: Transaction test succeeded
        alicloud-ecs: Running transaction
        alicloud-ecs:   Installing : jemalloc-3.6.0-1.el7.x86_64                                  1/2
        alicloud-ecs:   Installing : redis-3.2.12-2.el7.x86_64                                    2/2
        alicloud-ecs:   Verifying  : redis-3.2.12-2.el7.x86_64                                    1/2
        alicloud-ecs:   Verifying  : jemalloc-3.6.0-1.el7.x86_64                                  2/2
        alicloud-ecs:
        alicloud-ecs: Installed:
        alicloud-ecs:   redis.x86_64 0:3.2.12-2.el7
        alicloud-ecs:
        alicloud-ecs: Dependency Installed:
        alicloud-ecs:   jemalloc.x86_64 0:3.6.0-1.el7
        alicloud-ecs:
        alicloud-ecs: Complete!
    ==> alicloud-ecs: Stopping instance: i-xxx
    ==> alicloud-ecs: Waiting instance stopped: i-xxx
    ==> alicloud-ecs: Creating image: packer_basic
        alicloud-ecs: Detach keypair packer_xxx from instance: i-xxx
    ==> alicloud-ecs: Cleaning up 'EIP'
    ==> alicloud-ecs: Cleaning up 'instance'
    ==> alicloud-ecs: Cleaning up 'security group'
    ==> alicloud-ecs: Cleaning up 'vSwitch'
    ==> alicloud-ecs: Cleaning up 'VPC'
    ==> alicloud-ecs: Deleting temporary keypair...
    Build 'alicloud-ecs' finished.
    
    ==> Builds finished. The artifacts of successful builds are:
    --> alicloud-ecs: Alicloud images were created:
    
    cn-beijing: m-xxx