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.sixther.me: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.ext3 /dev/xvdf1
mount /dev/xvdf1 /new
rsync -auv / -exclude='/new/*' /new/
resize2fs /dev/xvdf1