28 - 自动化部署与镜像管理(debootstrap / cloud-init / Packer)
前提条件
- 已完成 Ansible 基础配置(控制节点与被管节点连通)
- 以 root 身份登录,或 ops 用户执行
sudo -i切换至 root 环境 - 系统运行在 Debian 12 Bookworm
- KVM/QEMU 已安装(Packer QEMU 构建需要,参见第 25 章)
- 建议准备一台干净虚拟机或云实例用于测试 cloud-init
全局参数
主机名 linuxdc,IP 192.168.1.100/24,SSH 端口 2222,运维用户 ops
三种工具定位
| 工具 | 用途 | 输出产物 | 典型场景 |
|---|---|---|---|
debootstrap |
构建最小 Debian 根文件系统 | 目录 / tarball | chroot、LXC 模板、离线环境 |
cloud-init |
云实例首次启动个性化初始化 | 运行时配置 | AWS / Azure / GCP / Proxmox 实例 |
Packer |
自动化构建标准化机器镜像 | qcow2 / AMI / VMDK 等 | 批量部署、不可变基础设施 |
详细步骤
1. debootstrap — 构建最小根文件系统
apt install -y debootstrap
创建最小 Debian 12 根文件系统(使用国内镜像加速):
mkdir -p /opt/chroot-bookworm
debootstrap --arch=amd64 bookworm /opt/chroot-bookworm \
https://mirrors.tuna.tsinghua.edu.cn/debian/
进入 chroot 环境进一步定制:
# 挂载必要的虚拟文件系统
mount -t proc proc /opt/chroot-bookworm/proc
mount --rbind /sys /opt/chroot-bookworm/sys
mount --rbind /dev /opt/chroot-bookworm/dev
chroot /opt/chroot-bookworm /bin/bash
在 chroot 内执行(此时已是新系统环境):
apt update
apt install -y vim locales systemd-sysv openssh-server
# 配置 locale
dpkg-reconfigure locales # 选择 en_US.UTF-8 或 zh_CN.UTF-8
# 设置 root 密码
passwd root
exit # 退出 chroot
清理并卸载:
umount -R /opt/chroot-bookworm/proc
umount -R /opt/chroot-bookworm/sys
umount -R /opt/chroot-bookworm/dev
打包为 tarball(可导入 LXC 或作为容器基础镜像):
tar -czf /opt/debian-bookworm-minimal.tar.gz \
-C /opt/chroot-bookworm .
ls -lh /opt/debian-bookworm-minimal.tar.gz
检查点
tarball 文件存在,大小通常在 100–300 MB 之间。解压后 chroot 进入,cat /etc/debian_version 显示 12.x。
2. cloud-init — 云实例初始化
安装(在作为云模板的机器上):
apt install -y cloud-init
cloud-init user-data 配置示例:
创建测试配置文件:
vim /tmp/test-cloud-config.yaml
#cloud-config
# 设置主机名
hostname: linuxdc-node
fqdn: linuxdc-node.local
# 创建运维用户
users:
- name: ops
groups: sudo
shell: /bin/bash
sudo: "ALL=(ALL) NOPASSWD:ALL"
ssh_authorized_keys:
- "ssh-ed25519 AAAAC3... ops@linuxdc" # 替换为实际公钥
# 安装基础软件包
packages:
- vim
- htop
- git
- curl
# 首次启动执行命令
runcmd:
- [ systemctl, enable, --now, ssh ]
- apt update && apt full-upgrade -y
- echo "cloud-init completed at $(date)" >> /var/log/cloud-init-custom.log
# 时区
timezone: Asia/Shanghai
本地模拟测试:
# 清除上次运行记录
cloud-init clean --logs
# 以指定配置文件运行 init 阶段
cloud-init init --local
# 查看执行日志
cat /var/log/cloud-init.log | tail -30
cloud-init status
生产使用方式
云平台(AWS / GCP / Azure / Proxmox)在创建实例时,将 user-data 内容粘贴到对应的配置字段。实例首次启动时 cloud-init 自动读取并执行,此后标记为已完成,不再重复执行(除非执行 cloud-init clean)。
cloud-init 数据源类型:
| 数据源 | 平台 |
|---|---|
DataSourceEC2 |
AWS EC2 |
DataSourceAzure |
Microsoft Azure |
DataSourceGCE |
Google Cloud |
DataSourceOpenStack |
OpenStack / Proxmox |
DataSourceNoCloud |
本地测试(从文件或 ISO 读取) |
3. Packer — 自动化镜像构建
安装(HashiCorp 官方 apt 源):
apt install -y wget gnupg
wget -O- https://apt.releases.hashicorp.com/gpg \
| gpg --dearmor -o /usr/share/keyrings/hashicorp-archive-keyring.gpg
echo "deb [signed-by=/usr/share/keyrings/hashicorp-archive-keyring.gpg] \
https://apt.releases.hashicorp.com $(lsb_release -cs) main" \
| tee /etc/apt/sources.list.d/hashicorp.list
apt update
apt install -y packer
packer version
创建项目目录:
mkdir -p ~/packer-debian/http
cd ~/packer-debian
Packer HCL 配置文件(debian12.pkr.hcl):
vim debian12.pkr.hcl
packer {
required_plugins {
qemu = {
version = ">= 1.0.0"
source = "github.com/hashicorp/qemu"
}
}
}
variable "ssh_password" {
default = "packer-build-temp"
sensitive = true
}
source "qemu" "debian12" {
# ISO 需提前下载到本地,从官网获取 checksum
iso_url = "file:///opt/iso/debian-12-amd64-netinst.iso"
iso_checksum = "sha256:见官方校验页面"
ssh_username = "ops"
ssh_password = var.ssh_password
ssh_timeout = "30m"
shutdown_command = "echo '${var.ssh_password}' | sudo -S shutdown -P now"
disk_size = "20000"
format = "qcow2"
accelerator = "kvm"
headless = true
vm_name = "debian12-template"
memory = 2048
cpus = 2
boot_wait = "5s"
boot_command = [
"<esc><wait>",
"install auto=true priority=critical preseed/url=http://{{ .HTTPIP }}:{{ .HTTPPort }}/preseed.cfg<enter><wait>"
]
http_directory = "http"
output_directory = "output-debian12"
}
build {
sources = ["source.qemu.debian12"]
# 基础系统更新
provisioner "shell" {
inline = [
"apt-get update",
"apt-get full-upgrade -y",
"apt-get install -y qemu-guest-agent cloud-init openssh-server",
"systemctl enable qemu-guest-agent cloud-init",
"apt-get clean"
]
execute_command = "echo '${var.ssh_password}' | sudo -S bash -c '{{ .Path }}'"
}
# 安全加固(使用已有 Ansible playbook)
provisioner "ansible" {
playbook_file = "../ansible/playbooks/template-hardening.yml"
user = "ops"
extra_arguments = [
"--extra-vars", "ansible_become_pass=${var.ssh_password}"
]
}
}
ISO checksum 必须校验
iso_checksum 字段必须填写从 Debian 官方网站(https://www.debian.org/CD/verify)获取的真实 SHA256 值,不可省略或填写占位符。Packer 会在构建开始前验证 ISO 完整性,校验失败则终止构建。
执行构建:
# 初始化插件
packer init .
# 语法检查
packer validate .
# 构建(--on-error=ask 出错时暂停便于调试)
packer build --on-error=ask .
构建完成后产物:output-debian12/debian12-template.qcow2,可直接导入 KVM / Proxmox / OpenStack。
实践任务
- 用
debootstrap创建最小 Debian 12 chroot 环境,进入后安装openssh-server,打包为 tarball - 在一台虚拟机上安装
cloud-init,编写包含用户创建和软件包安装的 user-data,执行cloud-init clean && cloud-init init --local模拟运行 - 安装 Packer,创建项目目录,编写基于本地 ISO 的 QEMU 构建模板,执行
packer validate .验证语法 - (可选)完整执行
packer build,将 Ansible hardening playbook 集成为 provisioner,输出 qcow2 镜像
自测问题
1. debootstrap 和 Packer 在构建系统镜像时的主要区别是什么?
debootstrap 是 Debian 专用的底层工具,直接从 APT 源提取软件包构建最小根文件系统(目录形式),适合 chroot、LXC、离线环境,输出为目录或 tarball,不含引导程序。Packer 是平台无关的镜像自动化构建工具,驱动虚拟化引擎(QEMU / VMware / AWS 等)运行完整的 OS 安装流程,然后通过 provisioner 执行配置,输出为可直接启动的磁盘镜像(qcow2 / AMI / VMDK),适合生产机器模板。两者可以组合:用 debootstrap 生成基础 rootfs,再由 Packer 打包成完整磁盘镜像。
2. cloud-init 的 user-data 和 meta-data 分别用于什么?
user-data 是用户提供的个性化配置内容(#cloud-config 格式的 YAML 或 shell 脚本),用于定义主机名、用户、SSH 密钥、软件包、运行命令等实例初始化逻辑,由用户在创建实例时写入。meta-data 是云平台提供的实例元信息(实例 ID、IP 地址、区域、标签等),由云平台自动注入,cloud-init 读取后用于配置主机网络、生成唯一主机名等。两者通过不同的数据源渠道提供(HTTP 元数据服务 / ISO / 文件),用户通常只需编写 user-data。
3. Packer 的 provisioner 有哪些常见类型?ansible provisioner 的优势是什么?
| Provisioner | 说明 |
|---|---|
shell |
在构建实例内执行 shell 脚本或内联命令 |
file |
上传文件到构建实例 |
ansible |
调用 Ansible playbook 对构建实例执行配置 |
ansible-local |
在构建实例内部运行 Ansible(需预装) |
chef-solo / puppet |
调用 Chef / Puppet 配置管理 |
ansible provisioner 的优势:复用已有的 playbook 和 roles(无需重写为 shell 脚本);任务幂等,构建失败可安全重试;配置即代码,变更有版本记录;同一 playbook 既可用于 Packer 构建时配置,也可用于运行时的配置漂移修复,保持一致性。
4. 生产环境中为什么推荐将 Packer 构建的镜像作为所有新实例的起点?
标准化镜像确保所有新实例从相同的已知良好状态启动:安全加固(内核参数、SSH 配置、防火墙规则)已内置,不依赖实例启动后的手动配置;软件包版本固定,避免"同批次不同机器安装了不同版本"的漂移问题;启动速度更快(无需在线安装大量软件包);镜像经过测试和扫描(Trivy、Lynis),安全基线有保障。这是"不可变基础设施"理念的核心实践:实例不应被就地修改,配置变更通过构建新镜像并替换实例来实现。
总结
debootstrap 适合轻量本地根文件系统构建,cloud-init 实现云实例的无人值守个性化初始化,Packer 将整个镜像构建流程代码化。三者配合 Ansible,构成"基础设施即代码"流水线的核心组件:标准化镜像 → 自动化部署 → 配置管理,实现从代码提交到生产实例的全链路自动化。