制作 ArchLinux 系统阿里云ecs镜像模板

经过一番折腾,终于制作完成archlinux在阿里云上的镜像模版,可用于快速部署

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

按照一般步骤安装 Arch Linux,需要整个磁盘仅有一个分区。阿里不支持多分区的系统镜像

0.部分踩过的坑

A.阿里云仅仅支持单分区模式,不支持多分区
B.不支持EFI模式,硬盘需要采用MBR分区,虚拟硬盘一定要用驱动VirtIO BLOCK,不能用VirtIO SCSI
C./etc/fstab一定要使用uuid模式指定
D.不要试图开dhcpcd自动获取ip地址,必须要用脚本指定
E.磁盘大小不同的情况下,阿里云会使用growpart或xfsprogs进行扩容

1.分区

查看现有的磁盘和分区[事先创建一个5g的盘即可,待使用的时候进行扩容]

root@archiso ~ # cat /proc/partitions
major minor  #blocks  name
 11        0     677888 sr0
254        0    5242880 vda
  7        0     558296 loop0

将磁盘转换为MBR分区,并且创建一个分区设置为启动

root@archiso ~ # parted /dev/vda
 GNU Parted 3.3
 Using /dev/sda
 Welcome to GNU Parted! Type 'help' to view a list of commands.
 (parted) mklabel msdos                                                    
 (parted) print free                                                       
 Model: Virtio Block Device (virtblk)
 Disk /dev/vda: 5369MB
 Sector size (logical/physical): 512B/512B
 Partition Table: msdos
 Disk Flags: 
 Number  Start  End     Size    Type  File system  Flags
         1024B  5369MB  5369MB        Free Space
 (parted) mkpart primary 1 -1                                              
 (parted) set 1 boot on                                                    
 (parted) quit                                                             
 Information: You may need to update /etc/fstab.

查看磁盘分区

root@archiso ~ # fdisk -l
 Disk /dev/vda: 5 GiB, 5368709120 bytes, 10485760 sectors
 Units: sectors of 1 * 512 = 512 bytes
 Sector size (logical/physical): 512 bytes / 512 bytes
 I/O size (minimum/optimal): 512 bytes / 512 bytes
 Disklabel type: dos
 Disk identifier: 0x36a1ff8c
 Device     Boot Start      End  Sectors Size Id Type
 /dev/vda1  *     2048 10483711 10481664   5G 83 Linux
 Disk /dev/loop0: 545.22 MiB, 571695104 bytes, 1116592 sectors
 Units: sectors of 1 * 512 = 512 bytes
 Sector size (logical/physical): 512 bytes / 512 bytes
 I/O size (minimum/optimal): 512 bytes / 512 bytes                 

2.挂载必要的分区

root@archiso ~ # mkfs.ext4 /dev/vda1
 mke2fs 1.45.6 (20-Mar-2020)
 Discarding device blocks: done                            
 Creating filesystem with 1310208 4k blocks and 327680 inodes
 Filesystem UUID: fa386240-2d11-4478-aa5d-9936e4198727
 Superblock backups stored on blocks: 
         32768, 98304, 163840, 229376, 294912, 819200, 884736
 Allocating group tables: done                            
 Writing inode tables: done                            
 Creating journal (16384 blocks): done
 Writing superblocks and filesystem accounting information: done   

挂载分区

root@archiso ~ # resize2fs -s /dev/vda1
root@archiso ~ # mount /dev/vda1 /mnt
root@archiso ~ # cd /mnt
root@archiso /mnt # mkdir -p boot
root@archiso /mnt # cd /etc/pacman.d

3.修改镜像源到本地

root@archiso /etc/pacman.d # mv  mirrorlist{,.orig}
root@archiso /etc/pacman.d # nano -w mirrorlist
Server = https://mirrors.163.com/archlinux/$repo/os/$arch

4.进行安装

root@archiso /etc/pacman.d # pacstrap /mnt base base-devel linux linux-firmware mdadm dhcpcd nano openssh qemu-guest-agent 

5.配置系统
生成fstab文件 (使用 -U or -L 来使用 UUID 或 labels):
# genfstab -U -p /mnt >> /mnt/etc/fstab

6.Change root到新的系统中:
# arch-chroot /mnt

7.设置主机名:
# echo archlinux > /etc/hostname

8. 修改时区与设置时间

[root@archiso etc]#  ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime 
[root@archiso etc]#  hwclock --systohc --utc  #设置硬件时钟为UTC:
9.设置字符集
取消 /etc/locale.gen 中的locale注释, 然后运行:
# locale-gen

10.设置时区
设置自己喜好的时区在 /etc/locale.conf 或者 $HOME/.config/locale.conf:
LANG=en_US.UTF-8
LANGUAGE=en_US.UTF-8
LC_ALL=C
LC_COLLATE=C
LC_MESSAGES=C
LC_TIME=zh_CN.UTF-8
SUPPORTED=zh_CN.UTF-8:zh_CN:zh:en_US.UTF-8:en_US:en
# echo LANG=your_locale > /etc/locale.conf
在 /etc/vconsole.conf增加键盘和字体设置.

11.配置网络.

12.配置一些依赖的驱动 /etc/mkinitcpio.conf. 
MODULES=(virtio virtio_blk virtio_pci virtio_net)

13.创建新的驱动内存盘:
# mkinitcpio -p linux

14.设置管理员密码:
# passwd

15.安装GRUB以及引导
[root@archiso etc]# pacman -S grub
[root@archiso etc]# grub-install --target=i386-pc --recheck --debug /dev/vda

16.生成引导配置文件并且重启

[root@archiso etc]#  grub-mkconfig -o /boot/grub/grub.cfg 

17.安装中文字体
[root@archiso etc]# pacman -S wqy-microhei wqy-microhei-lite wqy-bitmapfont wqy-zenhei ttf-arphic-ukai ttf-arphic-uming adobe-source-han-sans-cn-fonts adobe-source-han-serif-cn-fonts noto-fonts-cjk

18.设置虚拟机网络

有的需要指定静态IP地址

nano -w /etc/dhcpcd.conf
interface ens18
static ip_address=192.168.100.10/24
static routers=192.168.100.1
static domain_name_servers=8.8.8.8
[root@archiso /]# systemctl enable systemd-networkd
[root@archiso /]# systemctl enable systemd-resolved

19.配置初始化脚本

[root@archiso /]# mkdir /aliyun_custom_image && cd /aliyun_custom_image
[root@archiso /]# wget http://docs-aliyun.cn-hangzhou.oss.aliyun-inc.com/assets/attach/73848/cn_zh/1557459863884/image_check
[root@archiso /]# chmod 755 image_check
[root@archiso /]# nano -w /usr/bin/aliyun-custom-os
#!/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() {
    # ensure $os_conf_file is deleted, to avoid repeating config system
    rm $os_conf_file >& /dev/null
    # ensure $os_conf_dir is exitst
    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
# Generated by Aliyun Custom OS helper
# DO NOT EDIT THIS FILE! IT WILL BE OVERWRITTEN

[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 8.8.8.8" > /etc/resolv.conf
    for ns in $dns_nameserver
    do
        echo "nameserver $ns" >> /etc/resolv.conf
    done
}

mask2cdr() {
    # Assumes there's no "255." after a non-255 byte in the mask
    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
[root@archiso /]# chmod +x /usr/bin/aliyun-custom-os
[root@archiso /]# nano -w /usr/lib/systemd/system/aliyun-custom-os.service
[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
[root@archiso /]# systemctl enable aliyun-custom-os

20.增加扩容功能的支持

[root@archiso /]# pacman -Ss xfsprogs
[root@archiso /]# pacman -U growpart-0.31-1-any.pkg.tar.xz

root@archiso /etc/pacman.d # # exit
root@archiso /etc/pacman.d # umount /mnt
root@archiso /etc/pacman.d # reboot

镜像检查方式
https://help.aliyun.com/document_detail/73848.html?spm=a2c4g.11186623.4.5.6e9648a2VUStjY
镜像压缩方法
qemu-img convert -c -O qcow2 vm500G.qcow2 new.img.qcow2
镜像扩容方法
qemu-img resize vmSrv.img +10G

磁盘的扩展

运行fdisk -l命令查看现有云盘大小
以下示例返回云盘(/dev/vda)容量是100GiB

[root@ecshost ~]# fdisk -l
Disk /dev/vda: 107.4 GB, 107374182400 bytes, 209715200 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk label type: dos
Disk identifier: 0x000bad2b

   Device Boot      Start         End      Blocks   Id  System
/dev/vda1   *        2048    83886046    41941999+  83  Linux

运行df -Th命令查看云盘分区大小和文件系统类型。 以下示例返回分区(/dev/vda1)容量是40GiB,文件系统类型为ext4

[root@ecshost ~]# df -Th
Filesystem     Type      Size  Used Avail Use% Mounted on
devtmpfs       devtmpfs  869M     0  869M   0% /dev
tmpfs          tmpfs     879M     0  879M   0% /dev/shm
tmpfs          tmpfs     879M  460K  878M   1% /run
tmpfs          tmpfs     879M     0  879M   0% /sys/fs/cgroup
/dev/vda1      ext4       40G  1.8G   36G   5% /
tmpfs          tmpfs     176M     0  176M   0% /run/user/0

运行growpart <DeviceName> <PartionNumber>命令扩容分区。 示例命令表示扩容系统盘的第一个分区(/dev/vda1)

[root@ecshost ~]# LANG=en_US.UTF-8
[root@ecshost ~]# growpart /dev/vda 1
CHANGED: partition=1 start=2048 old: size=83883999 end=83886047 new: size=209713119 end=209715167

扩展文件系统。 根据文件系统类型选择以下扩展方式

1.ext*文件系统(例如ext3和ext4):运行resize2fs <PartitionName>命令。
示例命令表示为扩容系统盘的/dev/vda1分区的文件系统。

[root@ecshost ~]# resize2fs /dev/vda1
resize2fs 1.42.9 (28-Dec-2013)
Filesystem at /dev/vda1 is mounted on /; on-line resizing required
old_desc_blocks = 3, new_desc_blocks = 7
The filesystem on /dev/vda1 is now 26214139 blocks long.

2.xfs文件系统:运行xfs_growfs <mountpoint>命令。
示例命令表示为扩容系统盘的/dev/vda1分区的文件系统。其中根目录(/)为/dev/vda1的挂载点

[root@ecshost ~]# xfs_growfs /
meta-data=/dev/vda1              isize=512    agcount=13, agsize=1310656 blks
         =                       sectsz=512   attr=2, projid32bit=1
         =                       crc=1        finobt=1, sparse=1, rmapbt=0
         =                       reflink=1
data     =                       bsize=4096   blocks=15728379, imaxpct=25
         =                       sunit=0      swidth=0 blks
naming   =version 2              bsize=4096   ascii-ci=0, ftype=1
log      =internal log           bsize=4096   blocks=2560, version=2
         =                       sectsz=512   sunit=0 blks, lazy-count=1
realtime =none                   extsz=4096   blocks=0, rtextents=0
data blocks changed from 15728379 to 20971259

运行df -h命令查看云盘分区大小。
返回分区(/dev/vda1)容量是100GiB,表示已经成功扩容

[root@ecshost ~]# df -h
Filesystem      Size  Used Avail Use% Mounted on
devtmpfs        869M     0  869M   0% /dev
tmpfs           879M     0  879M   0% /dev/shm
tmpfs           879M  492K  878M   1% /run
tmpfs           879M     0  879M   0% /sys/fs/cgroup
/dev/vda1        99G  1.8G   93G   2% /
tmpfs           176M     0  176M   0% /run/user/0

关于Zeno Chen

本人涉及的领域较多,杂而不精 程序设计语言: Perl, Java, PHP, Python; 数据库系统: MySQL,Oracle; 偶尔做做电路板的开发,主攻STM32单片机
此条目发表在Linux分类目录。将固定链接加入收藏夹。