惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

C
Check Point Blog
GbyAI
GbyAI
酷 壳 – CoolShell
酷 壳 – CoolShell
博客园 - 叶小钗
U
Unit 42
Engineering at Meta
Engineering at Meta
aimingoo的专栏
aimingoo的专栏
Y
Y Combinator Blog
Google DeepMind News
Google DeepMind News
Vercel News
Vercel News
美团技术团队
雷峰网
雷峰网
Recent Announcements
Recent Announcements
有赞技术团队
有赞技术团队
D
DataBreaches.Net
H
Hackread – Cybersecurity News, Data Breaches, AI and More
Apple Machine Learning Research
Apple Machine Learning Research
J
Java Code Geeks
罗磊的独立博客
MyScale Blog
MyScale Blog
博客园_首页
IT之家
IT之家
F
Fortinet All Blogs
博客园 - Franky

Phoenix's island

通过重写 EEPROM 永久修改 MAC 地址 · Phoenix's island AMI 主板 IPMI Bonding with ipmitool · Phoenix's island 远程转换 H330 为 HBA330 · Phoenix's island 修复 CentOS 'org.freedesktop.login1' timed out · Phoenix's island 配置 Fail2ban 保护 Proxmox VE · Phoenix's island 笔记:Arch Linux iPXE 基本启动脚本 · Phoenix's island 修复 LVM XFS 的 Input/output error · Phoenix's island FAT32 与 FAT32 的不同 · Phoenix's island 在 Linux 系统中升级超微 BIOS 固件 · Phoenix's island 软件工程实践上的一点思考 · Phoenix's island WireGuard 真香 · Phoenix's island 制作 Arch Linux 内存系统启动盘 · Phoenix's island 使用 fs.WriteStream 编写超简单的日志流 · Phoenix's island 重构 StickerSetBot · Phoenix's island Office Service Router 解决方案:Arch Linux in RAM · Phoenix's island 通过 SSH 修正安装有 GPU 的 HPE Proliant 服务器 · Phoenix's island 在线扩展 LVM root 分区 · Phoenix's island 在 Linux 服务器配置 LACP 与 VLAN · Phoenix's island 迁移 DokuWiki 到 BookStackApp · Phoenix's island
制作 Arch Linux 系统模板镜像 · Phoenix's island
2018-02-01 · via Phoenix's island

阿里云镜像制作踩坑记。

此文章主要记录按照阿里云 Customized Linux 制作 VPC 镜像的过程。一些部分也可用作制作其他平台镜像的参考。

当然记录的原因主要是 Arch 上的 cloud-init 打死无法在阿里云上修改 root 密码,就很气。

建立虚拟机

因为要制作 Customized Linux,所以第一步无法在阿里云平台上使用公共镜像制作。本机启动一个 Virtual Box,新建虚拟机,虚拟磁盘选择 RAW/IMG 格式即可。

按照一般步骤安装 Arch Linux,需要整个磁盘仅有一个分区。虽然很多平台支持多分区的镜像文件,但是莫名在这里踩了坑所以。

(另外吐槽:vps2arch 居然不帮我把 base-devel 装全了?!)

系统配置

安装一些必需的包。

1
# pacman -S qemu-guest-ga openssh

启用服务。

1
2
3
# systemctl enable qemu-ga
# systemctl enable sshd
# systemctl enable systemd-networkd

网络配置

哪个魂淡跟我讲 VPC 是 DHCP?装着 cloud-init 的 Arch 就可以自动设置内网 IP,这个没装的就 GG。

修改文件 /etc/systemd/network/default.network

1
2
3
4
5
[Match]
Name=en*

[Network]
DHCP=ipv4

总之先这样放着。

定制脚本

根据阿里云的文档,cloud init 不生效的时候需要用约定好的配置文件和脚本完成各种兼容动作。

新建目录 /aliyun_custom_image

新建文件 /usr/bin/aliyun-custom-os,写入内容

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
#!/bin/bash

os_conf_dir=/aliyun_custom_image
os_conf_file=${os_conf_dir}/os.conf

load_os_conf() {
if [[ -f $os_conf_file ]]; then
. $os_conf_file
echo $password
return 0
else
return 1
fi
}

cleanup() {

rm $os_conf_file >& /dev/null

mkdir -p $os_conf_dir
}

config_password() {
if [[ -n $password ]]; then
password=$(echo $password | base64 -d)
if [[ $? == 0 && -n $password ]]; then
echo "root:$password"
echo "root:$password" | chpasswd
fi
fi
}
config_hostname() {
if [[ -n $hostname ]]; then
echo "$hostname" > /etc/hostname
hostnamectl set-hostname $hostname
fi
}
config_network() {
if [[ -n $eth0_ip_addr ]]; then
config_interface
systemctl restart systemd-networkd
fi
}
config_interface() {
mask2cdr $eth0_netmask
cat << EOF > /etc/systemd/network/default.network



[Match]
Name=$(ip link | awk -F: '$0 !~ "lo|vir|wl|^[^0-9]"{print $2a;getline}' | sed -e 's/^[[:space:]]*//')

[Network]
Address=$eth0_ip_addr/$netmask
Gateway=$eth0_gateway

[Link]
MACAddress=$eth0_mac_address

[Address]
Address=$eth0_ip_addr/$netmask
EOF
echo "nameserver 1.1.1.1" > /etc/resolv.conf
for ns in $dns_nameserver
do
echo "nameserver $ns" >> /etc/resolv.conf
done
}

mask2cdr() {

local x=${1##*255.}
set -- 0^^^128^192^224^240^248^252^254^ $(( (${#1} - ${#x})*2 )) ${x%%.*}
x=${1%%$3*}
netmask=$(( $2 + (${#x}/4) ))
}

if load_os_conf ; then
config_password
config_hostname
config_network
cleanup
else
echo "not load $os_conf_file"
fi

赋予执行权限

1
# chmod +x /usr/bin/aliyun-custom-os

新建 systemd unit 文件 /usr/lib/systemd/system/aliyun-custom-os.service 写入内容

1
2
3
4
5
6
7
8
9
10
11
12
[Unit]
Description=Aliyun Custom OS Helper Script

[Service]
Type=oneshot
ExecStart=/usr/bin/aliyun-custom-os
TimeoutSec=30
StandardInput=tty
RemainAfterExit=yes

[Install]
WantedBy=multi-user.target

然后启用这个服务

1
systemctl enable aliyun-custom-os

挂载镜像

正常 shutdown 虚拟机,然后拿到镜像文件的路径。例如 ~/vm/archlinux.img

接下来需要将此镜像挂载到宿主机系统中修改、清理文件。首先确定镜像文件中的分区位置:

1
2
$ file ~/vm/archlinux.img
archlinux.img: x86 boot sector; partition 1: ID=0x83, active, starthead 32, startsector 2048, 41938944 sectors, code offset 0x63

得知 startsector2048

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
$ fdisk -l ~/vm/archlinux.img
You must set cylinders.
You can do this from the extra functions menu.

Disk archlinux.img: 0 MB, 0 bytes
255 heads, 63 sectors/track, 0 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x91d8e293

Device Boot Start End Blocks Id System
archlinux.img1 * 1 2611 20969472 83 Linux
Partition 1 has different physical/logical endings:
phys=(1023, 254, 63) logical=(2610, 180, 2)

得知 sectorsize512

使用 mount 命令带 offset 参数挂载镜像中的分区:

1
2
$ sudo mkdir -p /mnt/img
$ sudo mount -t ext4 -o loop,offset=$((2048*512)) /path/to/archlinux.img /mnt/img/

就可以 cd /mnt/img 看到镜像里的 rootfs 啦。

清理/检查文件

要删除的:

1
2
3
4
5
# rm /root/.bash_history 
# rm /etc/ssh/ssh_host_*
# rm -r /var/log/*
# rm -r /var/cache/*
# rm /etc/resolv.conf.bak

要检查的:

/etc/hosts - 我不知道为什么,第一次的时候把这个文件留空了(:з」∠)

/etc/resolv.conf - 鉴于总是有人喜欢手动修改这个文件,所以直接把它写成静态文件好了。内容例如

1
2
nameserver 8.8.8.8
nameserver 8.8.4.4

/etc/ssh/sshd_config 中是否允许 root 密码登陆。

准备镜像

退出 /mnt/img 目录,然后卸载镜像

1
# umount /mnt/img

(可选)使用 qemu-img 转换镜像格式到 VHD,减少镜像文件大小。特别是对国内的小水管上传(心疼

1
$ qemu-img convert -f raw -O vpc archlinux.img archlinux.vhd

上传镜像

在相同的 region 创建一个 OSS bucket,然后创建一个 RAM 子用户赋予 OSS 写权限并创建 Access Key,使用 OSSBrowser 上传准备好的 VHD 文件。

上传完毕后,在 ECS 标签下的镜像标签即可导入镜像。如果是第一次操作,需要给 ECS 授权访问 OSS。在导入的页面提示中提供了授权的链接。镜像内容配置如下:

  • OSS Object 地址:镜像文件在 OSS 中的 URL
  • Image 名称:archlinux-2018.1-x86_64 … 等符合要求即可
  • 操作系统:Linux
  • 系统盘大小:40GB
  • 系统架构:x86_64
  • 系统平台:Customized Linux
  • 镜像格式:VHD(如果是 img 就选 RAW)
  • 镜像描述:随便写啦。

确定后应该就会开始制作镜像了。

测试

因为没有做经典实例的兼容,这个镜像只能用于 VPC 的实例。总体而言,cloud-init 本来兼容的 Arch 却无法更改 root 密码(其他的倒是没问题),所以才选择了用一个 dirty 的方案来实现。

不知道应该说阿里云的工程师对自定义镜像的考虑周到还是对不同发行版的考虑欠妥…?

最后庆幸倒腾来去上传了好多遍 20G 的文件,日本运营商家宽带宽对等真的是帮了大忙,不然一个镜像制作不知道要到什么时候 > > (斜眼看国内三大运营商

参考: