系列专栏声明:比较流水,主要是写一些踩坑的点,和实践中与文档差距较大的地方的思考。这个专栏的典型特征可能是 次佳实践
,争取能在大量的最佳实践中生存。
HashiCorp Packer,通过调用云厂商的接口,把构建基础镜像的过程代码化,即 Infra as Code -> IaC
。个人之前的做法是用 Markdown 写安装的步骤,然后起一台新实例从上往下复制粘贴执行,然后对这个实例做镜像和备份。从 Markdown 到 Code 是一个 0 到 1 的质变。
Vultr 的代码如下,官方文档:
variable "vultr_api_key" {
type = string
default = "${env("VULTR_API_KEY")}"
sensitive = true
}
packer {
required_plugins {
vultr = {
version = ">=v2.3.2"
source = "github.com/vultr/vultr"
}
}
}
source "vultr" "debian11" {
api_key = "${var.vultr_api_key}"
os_id = "477"
plan_id = "vc2-1c-1gb"
region_id = "sgp"
snapshot_description = "Debian 11 Bullseye ${formatdate("YYYY-MM-DD hh:mm", timestamp())}"
ssh_key_ids = ["uuid-aaaa", "uuid-bbbb"]
ssh_username = "root"
state_timeout = "25m"
}
build {
sources = ["source.vultr.debian11"]
provisioner "shell" {
script = "packer.sh"
}
}
安装脚本的关键部分如下:
#!/bin/bash
sleep 5m
# apt-get update
apt-get install -y --no-install-recommends zsh
useradd core
mkdir -p /home/core/.ssh
touch /home/core/.zshrc
chown -R core:core /home/core
adduser core sudo
chsh -s /usr/bin/zsh core
su core -c 'sh -c "$(curl -fsSL https://raw.github.com/ohmyzsh/ohmyzsh/master/tools/install.sh)"'
su core -c 'git config --global core.editor "vim"'
踩坑如下:
- 一些值比如
os_id, plan_id, region_id
需要用 Open Api 去查,官方文档;上面用到的这些值都是公开报价,不涉及到帐号信息,所以可以直接调接口,不需要去实现Authorization: Bearer
Cloud-Init, User-Data, Start-Script
看上去是需要用Token
去查的,并且部分接口在/api/v1
还没有实现到/api/v2
,文档不太完善,由于暂时没有用到,等用到了再来补充- Vultr 允许指定多个
ssh pub key
到authorized_keys
。我们是用root
帐号初始化的,所以它们是被导入了/root/.ssh/authorized_keys
,上面我新建的那个core
帐号就没有;感觉需要某种初始化策略,通过云厂商提供的 RAM 机制,去 KMS 里面拉取,待研究 - 重点!!!似乎 Debian 系有某种机制,在第一次被拉起来的时候会去执行
apt-get update
,因此我们的脚本上手第一行也执行apt-get update
的话就会报错。官方的建议是先 always-sleep-on-packer-provisioning。
阿里云代码如下,官方文档:
variable "access_key" {
type = string
default = "${env("ALICLOUD_ACCESS_KEY")}"
sensitive = false
}
variable "secret_key" {
type = string
default = "${env("ALICLOUD_SECRET_KEY")}"
sensitive = true
}
packer {
required_plugins {
alicloud = {
version = ">= 0.0.1"
source = "github.com/hashicorp/alicloud"
}
}
}
source "alicloud-ecs" "debian10" {
access_key = "${var.access_key}"
secret_key = "${var.secret_key}"
region = "cn-hangzhou"
image_name = "Debian-10-Buster-${formatdate("YYYYMMDDhhmm", timestamp())}"
source_image = "debian_10_11_x64_20G_alibase_20211027.vhd"
system_disk_mapping {
disk_size = 20
}
ssh_username = "root"
instance_type = "ecs.t6-c1m2.large"
zone_id = "cn-hangzhou-i"
vpc_id = "vpc-aaaa"
vswitch_id = "vsw-bbbb"
security_group_id = "sg-cccc"
internet_charge_type = "PayByTraffic"
}
build {
sources = ["source.alicloud-ecs.debian10"]
provisioner "shell" {
script = "packer.sh"
}
}
踩坑点如下:
- 阿里云的所有 Open Api 都必须用 AK 访问,即使列举 Regions 也没有公开接口。但是如果使用子帐号的 AK 就会发现,
DescribeRegions
的权限是全局的,DescribeImages
的权限是要主动去向子帐号配置的,具体自己尝试和开工单吧。 Packer
支持在起实例的时候,不申请公网 EIP,而是通过 VPC IP 连接;但实际上在阿里云如果不开公网 EIP,实例也没办法去公网源更新和装软件。简单起见,我还是走 EIP 模式了。- 阿里云的 Debian 似乎不会执行
apt-get update
,很神奇,但是我还是决定sleep
了。 authorized_keys
只支持指定一个值,不支持数组,不知道图啥。- 重点!!!
security_group_id
也不支持数组,由于我把安全组分了几类,组合起来用的,所以没有一个恰好适合所有场景,尤其是安装的时候要允许一些公网连接的情况下,所以简单起见,专门为 packer 模式新建了一个安全组。 - 重点!!!有些软件是装不上的,你懂的,比如
ohmyzsh
,所以我在国内的coding.net
上 fork 了一份,类似场景类似处理;顺便提一句,阿里云有 docker 源,自己搜一下
$ curl -fsSL http://mirrors.aliyun.com/docker-ce/linux/debian/gpg | sudo apt-key add -
$ sudo add-apt-repository "deb [arch=amd64] http://mirrors.aliyun.com/docker-ce/linux/debian $(lsb_release -cs) stable"
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。