首页 理论教育 使用Packer创建Amazon机器镜像的实战方法

使用Packer创建Amazon机器镜像的实战方法

时间:2023-11-06 理论教育 版权反馈
【摘要】:它们位于terraform/aws目录:第一步是使用Packer创建Amazon Machine Image。它将基于Ubuntu并安装最新的Docker Engine。builder负责为不同的平台创建机器并生成它们的镜像。除了amazon-ebs,还可以为AMI选择使用amazon-instance和amazon-chroot builder。大多数情况下,应该使用amazon-ebs。请注意,当使用amazon-ebs类型时,我们必须提供AWS密钥。可以通过access_key和secret_key字段来指定。owners字段将结果限定为可信的AMI供应商。ssh_username指定了Packer在创建镜像时所使用的用户。

使用Packer创建Amazon机器镜像的实战方法

vfarcic/cloud-provisioning(https://github.com/vfarcic/cloud-provisioning)代码库已经有了我们将使用的Packer和Terraform的配置。它们位于terraform/aws目录:

第一步是使用Packer创建Amazon Machine Image(AMI)。为此,需要将AWS访问密钥设置为环境变量。它们与你在本章中已经创建的密钥相同。如果相同的终端会话仍然开着,则请跳过下面这组命令:

请用实际的值代替[…]。

现在使用相同的AMI来实例化所有的Swarm节点。它将基于Ubuntu并安装最新的Docker Engine。

我们要构建的镜像的JSON定义可以在terraform/aws/packerubuntu-docker.json中找到(https://github.com/vfarcic/cloud-provisioning/blob/master/terraform/ aws/packer-ubuntu-docker.json):

该配置包含两部分:builders和provisioners:

builders部分定义了Packer构建镜像所需的所有信息。provisioners部分描述了在builders部分所创建的机器上安装和配置软件的命令。唯一需要的部分是builders。

builder负责为不同的平台创建机器并生成它们的镜像。例如,EC2、VMware、VirtualBox等都有单独的builder。默认情况下,Packer附带了许多的builder,还可以扩展添加新的builder。

我们将使用的builders部分如下:

每种类型的builder都有特定的参数可供使用。我们指定其类型为amazon-ebs。除了amazon-ebs,还可以为AMI选择使用amazon-instance和amazon-chroot builder。大多数情况下,应该使用amazon-ebs。更多信息请访问Amazon AMI Builder页面(https://www.packer.io/docs/builders/amazon.html)。

请注意,当使用amazon-ebs类型时,我们必须提供AWS密钥。可以通过access_key和secret_key字段来指定。然而,还有另一种选择。如果这些字段未指定,Packer将尝试从环境变量AWS_ACCESS_KEY_ID和AWS_SECRET_ACCESS_KEY获得密钥。因为已经将它们导出,所以不必在Packer的配置中设置。此外,密钥应该是保密的。把它们放在配置中会有暴露的风险。

区域很关键,因为一个AMI只能在一个区域内创建。如果想在多个区域间共享同一台机器,那么每个区域都需要指定单独的builder。

可以将初始的AMI的ID指定为source_ami,作为新创建的机器的基础。但是,由于AMIs对于特定区域是唯一的,所以,如果我们决定改变区域,就会使其不可用。相反,我们采用了一种不同的方法,并指定了source_ami_filter,它将填充source_ami字段。它将过滤AMIs并找到带有hvm虚拟化类型以及Root Device Type是ebs的Ubuntu 16.04的镜像。owners字段将结果限定为可信的AMI供应商。如果返回多个AMI,过滤器就会失败,most_recent字段将会选择最新的镜像作为结果。

instance_type字段定义了使用哪种类型的EC2实例来构建AMI。请注意,这不会妨碍我们使用其他任何已支持的实例类型来实例化虚拟机,在本例中是Ubuntu。

与我们使用的其他字段不同,ssh_username并不专门用于amazon-ebsbuilder的。ssh_username指定了Packer在创建镜像时所使用的用户。就像实例类型一样,它不会妨碍我们在基于此镜像实例化虚拟机时指定任何其他用户。

ami_name字段是我们为这个AMI所起的名字。

如果已经创建了一个同名的AMI,那么force_deregister字段将在创建新AMI之前删除同名的AMI。

更多信息请参考AMI Builder(EBS Backed)页面(https://www.packer.io/ docs/builders/amazon-ebs.html)。

第二部分是provisioners。它包含一个含有所有provisioners的数组,在将它们转换成机器镜像之前,Packer应该使用provisioners在运行的机器中安装和配置软件。

可以使用相当多的provisioner类型。如果你读过《微服务运维实战(第一卷)》,你就会明白我提倡选择Ansible作为provisoner。在这里也应该使用它吗?大多数情况下,当构建的镜像要运行Docker容器时,我选择简单的shell。从Ansible改为shell的原因在于目标不同,在活动的服务器上运行时选择provisioners,而不是在构建镜像时。

与Shell不同,Ansible(和大多数其他provisioners)是幂等的(idempotent)。它们会验证实际状态并执行一个或另一个操作,这取决于期望的状态。这是一种很好的方法,因为我们可以运行Ansible任意次,结果总是相同的。例如,如果想要有JDK 8,那么Ansible会登录目标服务器,发现JDK不存在就安装。下次运行Ansible时,当发现JDK已经存在,就什么都不做。

这种方法允许我们随时运行Ansible playbook,JDK总是会被安装。如果试图通过Shell脚本做相同的事情,就需要编写冗长的if/else语句。如果JDK已经安装,就什么都不做;如果没有安装,就去安装;如果已经安装但是版本不对,就要升级等。

那为什么不将它与Packer一起使用呢?答案很简单。不需要幂等性,因为我们只在创建镜像时运行一次。我们不会在运行实例时使用它。你还记得“宠物与牛”的讨论吗?用来实例化虚拟机的镜像已经有了我们需要的所有东西。如果虚拟机的状态发生变化,我们就将终止它并创建一个新的。

如果需要升级或安装额外的软件,就不会在运行的实例中进行,而是创建一个新的镜像,终止正在运行的实例,并根据更新的镜像实例化新的实例。(www.xing528.com)

幂等性是我们使用Ansible的唯一原因吗?当然不是!当需要定义一个复杂的服务器配置时,它是一种非常方便的工具。但是,在我们的例子中,配置很简单。我们只需要Docker Engine。几乎所有东西都会在容器中运行。编写几个shell命令来安装Docker比定义Ansible playbook更容易,速度也更快。安装Ansible所需的命令数量可能与安装Docker的相同。

长话短说,现在将使用shell作为provisioner来构建AMIs。

将使用的provisioners部分如下:

shell类型之后有一连串的命令。这些命令与Install Docker on Ubuntu网页中的相同(https://docs.docker.com/engine/installation/linux/ubuntulinux/)。

现在已经大概了解了Packer配置是如何工作的,下面可以继续并构建一个镜像了:

我们运行了packer-ubuntu-docker.json所定义的packer build,并将机器可读的输出发送到packer-ubuntu-docker.log。机器可读的输出将允许我们轻松地解析它并检索刚才创建的AMI的ID。

输出的最后几行如下:

除了确认构建成功外,输出的相关部分是lineid、us-east-1:ami-02ebd915。它包含AMI ID,这是基于该镜像来实例化虚拟机所需要的。

如果需要从其他服务器得到ID,那么可能希望将packer-ubuntu-docker.log存储在代码库中。

图12-10描述了Packer执行过程的流程。

图12-10 Packer过程的流程

现在已经准备好根据我们构建的镜像创建一个Swarm集群。

免责声明:以上内容源自网络,版权归原作者所有,如有侵犯您的原创版权请告知,我们将尽快删除相关内容。

我要反馈