使用packer构建aws AMI 镜像
简介:
aws提供了各种各样的镜像供用户使用,但是大部分情况下,社区里提供的ami不能完全满足我们的需求,比如比较恶心的有些镜像的根分区只有 10g,所以一般我们都会使用社区的公有镜像来创建一个ec2,然后加工下(configure)她,然后再打成一个镜像,供项目使用,packer可 以让我们更加自动化的去生成AMI,我们可以将原始镜像跟所有配置的东西写成一个template文件,然后交给pakcer,packer便会通过 access key来连接到我们aws账户,完成上述人工建立镜像的步骤,生成一个新的AMI,这种方式可以使我们以代码的形式去管理自己的aws镜像,结合git等 版本控制系统,可以做到aws镜像的版本管理,为基础设施即代码这一目标打下坚实的基石。
也就是说packer以代码的形式为各种云平台提供创建镜像,包括aws,openstack,DigitalOcean,docker等,来自HashiCorp公司,vagrant工具同样出自该公司,这个公司开发了很多DevOps工具,并且遵从linux哲学,每一个工具都可以单独拿出来使用,并且用户也可以使用它们的服务创建一个工具流来使运维或者开发工作更简单。
下面就看简单看一下如何使用packer构建ec2镜像。
安装:
wget https://releases.hashicorp.com/packer/0.10.0/packer_0.10.0_linux_amd64.zip
解压出来就是一个packer的二进制文件,将其放到$PATH变量的目录中即可。
使用:
然后我们需要一个json的模版来描述如何构建一个ec2镜像,模版的一般形式如下,详细请查看官方文档:
{ "builders": [ ], #定义一个原始镜像 "descriptions": [ ], #描述信息 "min_packer_version": [ ], "post-processors": [ ], #定义预处理过程 "provisioners": [ ], #定义构建镜像的行为 "variables": [] #定义一些变量 }
如下例子是一个从一个原始的镜像开始,首先上传git key到root目录下,然后clone下来一个版本库,最终执行初始化脚本的packer模版,模版中可以指定aws access key,也可以不指定,不指定的话会去用户的~/.aws目录下找。
{ "builders": [ { "name": "first_build", "type": "amazon-ebs", "region": "us-east-1", "source_ami": "ami-ds1f15b6", "instance_type": "t2.micro", "ssh_username": "root", "ami_name": "MY_AMI_30G_CENTOS6_{{timestamp}}" } ], "provisioners": [ { "type": "file", "source": "git_id_rsa", "destination": "/root/.ssh/id_rsa" }, { "type": "shell", "inline": ["chmod 400 /root/.ssh/id_rsa", "chown root:root /root/.ssh/id_rsa", "cd /root/ && git clone git@git.awsgood.com:ops/ops_deploy.git --depth 1", "cd /root/ops_deploy/centos6 && sh init_full_aws_us.sh", "rm -rf /root/ops_deploy" ] } ] }
如上模版,使用了file根shell两个类型的provisioners,file可以上传文件到镜像,shell可以执行脚本,还支持通过ansible,chef,puppet等配置工具定义的动作来构建镜像,具体见provisioners文档。
最后说一下如何从一个根分区是10g的ami创建出一个根分区是30g的ami
◊ 基于这个10g的ami启动一个实例;
◊ 创建一个30g的ebs,attach到这个实例上;
◊ 使用dd命令将原始磁盘的数据克隆到新的磁盘上(这一步主要是要克隆MBR,否则磁盘无法启动linux);
◊ 然后给新的磁盘重新分区,分一个30g的分区,并设置上boot标志;
◊ 将新的分区挂载到一个临时目录,然后将老磁盘的整个根分区拷贝到新的分区中;
◊ 关闭实例,dettach两块磁盘,然后将新的磁盘以/dev/sda1的标签attach到实例上,如果能正常启动,则将该磁盘创建为ami。
上述步骤涉及到的命令有:
dd if=/dev/xvda of=/dev/xvdf bs=65536 #创建一个30g的ebs挂载上去,然后将原始盘的数据拷贝过去。 dd if=/dev/xvdf of=mbr.bin bs=512 count=1 #到处mbr,用于检查 hexdump -C mbr.bin #查看mbr信息,用于检查 fdisk /dev/xvdf #创建一个30G的主分区,并将其设置为启动分区,a指令可以设置启动分区 mkfs.ext4 /dev/xvdf1 mount /dev/xvdf1 /new rsync -auv / -exclude='/new/*' /new/ resize2fs /dev/xvdf1