背景
在我们的生产环境开通的虚拟主机上尝试安装 kubelet 的时候,发现报了这么一个错误:
[ERROR CRI]: container runtime is not running: output: time="2024-01-09T10:28:09+08:00" level=fatal msg="validate service connection: CRI v1 runtime API is not implemented for endpoint "[unix:///var/run/containerd/containerd.sock]()": rpc error: code = Unimplemented desc = unknown service runtime.v1.RuntimeService"
现象就是 containerd 是好的,但是放到 crictl 去访问的时候就会报 CRI v1 runtime API is not implemented for endpoint
这个错误。
关于这个错误上网找的其他办法主要指向这个:serverfault.com/a/1126729/3...
简单来说就是 /etc/containerd/config.toml
这个文件里面需要关闭 disabled_plugins = ["cri"]
这个配置。但在我的场景下这个配置原本就没有。
然后一番排查,最后通过 systemctl status containerd -l
找到了问题的根源:
failed to create CRI service: failed to find snapshotter "overlayfs"
原本的系统盘 /
下面挂载的是 xfs,查了 xfs 对 overlayfs 的支持需要在格式化的时候指定 ftype=1,而这个没有,验证方法:
bash
xfs_info /
输出是这样的:
bash
meta-data=/dev/mapper/VG01-lv_root isize=256 agcount=4, agsize=2736896 blks
= sectsz=512 attr=2, projid32bit=1
= crc=0 finobt=0 spinodes=0
data = bsize=4096 blocks=10947584, imaxpct=25
= sunit=0 swidth=0 blks
naming =version 2 bsize=4096 ascii-ci=0 ftype=0
log =internal bsize=4096 blocks=5345, version=2
= sectsz=512 sunit=0 blks, lazy-count=1
realtime =none extsz=4096 blocks=0, rtextents=0
可以看到 ftype=0
,说明文件系统不支持。
为了解决这个问题,至少需要保证 /var/lib/containerd
这个目录下的文件系统支持 overlayfs,其实之前用 docker 的时候也遇到过同样的问题,对应的目录是 /var/lib/docker
。
我们可以创建一个新的数据盘,将其格式化为 ext4 或者 xfs(ftype=1) 的方式,然后单独挂载到 /var/lib/containerd
上面,这样可以解决问题。
但是这样操作我们需要浪费一块额外的数据盘而且多出来一些很冗余的配置,不是一个特别完美的解决方案。
解决方案
更好的方案显然是直接把系统盘的文件系统改掉,但是显然这需要格式化。
原始的系统磁盘布局是这样的:
bash
# lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
sda 8:0 0 50G 0 disk
├─sda1 8:1 0 200M 0 part /boot
└─sda2 8:2 0 49.8G 0 part
├─VG01-lv_root 253:0 0 41.8G 0 lvm /
└─VG01-lv_swap 253:1 0 8G 0 lvm [SWAP]
sdb 8:16 0 1G 0 disk
└─data01vg-appslv 253:2 0 896M 0 lvm /apps
sr0 11:0 1 1024M 0 rom
# df -h
文件系统 容量 已用 可用 已用% 挂载点
devtmpfs 1.9G 0 1.9G 0% /dev
tmpfs 1.9G 0 1.9G 0% /dev/shm
tmpfs 1.9G 36M 1.9G 2% /run
tmpfs 1.9G 0 1.9G 0% /sys/fs/cgroup
/dev/mapper/VG01-lv_root 42G 5.0G 37G 12% /
tmpfs 378M 0 378M 0% /run/user/0
/dev/sda1 197M 112M 86M 57% /boot
/dev/mapper/data01vg-appslv 866M 30M 776M 4% /apps
tmpfs 60M 0 60M 0% /var/log/rtlog
tmpfs 378M 0 378M 0% /run/user/1002
tmpfs 378M 0 378M 0% /run/user/1000
我们申请的资源就是这样,50GB 的系统盘分了两块,其中 VG01-lv_root 有 41.8G 的空间,另外还有 8G 的空间用作 swap 目录。但是实际根目录 / 下面只有 5G 的数据。
受这个帖子的启发,superuser.com/q/1321926/5...,我决定尝试在现有的环境下做一次给系统盘做一个换头手术,将系统盘的文件系统化格式化掉,但是保留原本的所有信息再重新拉起。
注意到,swap 分区其实是多余的,我们装 kubernetes 的时候本来就要关 swap,我们是不是能够用 swap 分区的 8G 空间用来腾挪,从而把根目录的挂载盘格掉呢?这就是我的乾坤大挪移方案:
- 关闭 swap,然后将 swap 格式化成 xfs(ftype=1),挂载到 /mnt 上;
- 将根目录 / (VG01-lv_root) 的数据通过 rsync 全部复制到 /mnt (VG01-lv_swap);
- 修改启动条件,将 / 和 /mnt 的挂载盘 (VG01-lv_root 和 VG01-lv_swap) 互换,重启;
- 将 /mnt 挂载了 VG-lv_root 格式化成 xfs(ftype=1);
- 将根目录 / (VG01-lv_swap) 的数据通过 rsync 全部复制到 /mnt (VG01-lv_root);
- 修改启动条件,换回最初的版本,重启,大功告成。
我居然把上面这个试通了,下面是实际操作细节:
1. 关闭 swap,格式化并挂载到 /mnt 上
临时关闭 swap (后面再改 /etc/fstab)
bash
swapoff -a
格式化成 xfs(ftype=1)
bash
mkfs.xfs -f -n ftype=1 /dev/mapper/VG01-lv_swap
输出:
ini
meta-data=/dev/mapper/VG01-lv_swap isize=512 agcount=4, agsize=524288 blks
= sectsz=512 attr=2, projid32bit=1
= crc=1 finobt=0, sparse=0
data = bsize=4096 blocks=2097152, 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
将 VG01-lv_swap 临时挂载到 /mnt:
bash
mount /dev/mapper/VG01-lv_swap /mnt
2. 将根目录的数据 rsync 到 /mnt 上
注意要加几个特殊的参数,同时忽略 /mnt 目录本身,/boot 目录,以及数据盘挂载的目录 /apps。
bash
rsync -avxHAX --delete --devices --specials --exclude /mnt --exclude /apps --exclude /boot / /mnt/
然后 ls -la /mnt
看一下数据是不是都过去了。
3. 修改启动条件
修改 /mnt/etc/fstab
(注意旧的位置 /etc/fstab 已经不 care 了),原版长这样:
bash
#
# /etc/fstab
# Created by anaconda on Wed Feb 15 08:41:10 2017
#
# Accessible filesystems, by reference, are maintained under '/dev/disk'
# See man pages fstab(5), findfs(8), mount(8) and/or blkid(8) for more info
#
/dev/mapper/VG01-lv_root / xfs defaults 0 0
UUID=faa7906a-6ff7-4d7b-bf5e-5ecc4ac54fb3 /boot xfs defaults 0 0
/dev/mapper/VG01-lv_swap swap swap defaults 0 0
/dev/mapper/data01vg-appslv /apps ext4 defaults 0 0
将 VG01-lv_root 改成 VG01-lv_swap,同时注释掉 swap 那行,改完之后变成这样:
bash
#
# /etc/fstab
# Created by anaconda on Wed Feb 15 08:41:10 2017
#
# Accessible filesystems, by reference, are maintained under '/dev/disk'
# See man pages fstab(5), findfs(8), mount(8) and/or blkid(8) for more info
#
/dev/mapper/VG01-lv_swap / xfs defaults 0 0
UUID=faa7906a-6ff7-4d7b-bf5e-5ecc4ac54fb3 /boot xfs defaults 0 0
#/dev/mapper/VG01-lv_swap swap swap defaults 0 0
/dev/mapper/data01vg-appslv /apps ext4 defaults 0 0
然后,启动点的配置也要修改,修改 /boot/grub2/grub.cfg
(记得先备份原版),找到下面这个位置,将所有 VG01-lv_root 和 VG01-lv_swap 对调:
涉及的原版片段是这样的,共需修改六处:
scss
### BEGIN /etc/grub.d/10_linux ###
menuentry 'CentOS Linux (3.10.0-1160.92.1.el7.x86_64) 7 (Core)' --class centos --class gnu-linux --class gnu --class os --unrestricted $menuentry_id_option 'gnulinux-3.10.0-327.el7.x86_64-advanced-6e2cc491-a603-4ec9-9677-65d425c720e2' {
load_video
set gfxpayload=keep
insmod gzio
insmod part_msdos
insmod xfs
set root='hd0,msdos1'
if [ x$feature_platform_search_hint = xy ]; then
search --no-floppy --fs-uuid --set=root --hint-bios=hd0,msdos1 --hint-efi=hd0,msdos1 --hint-baremetal=ahci0,msdos1 --hint='hd0,msdos1' faa7906a-6ff7-4d7b-bf5e-5ecc4ac54fb3
else
search --no-floppy --fs-uuid --set=root faa7906a-6ff7-4d7b-bf5e-5ecc4ac54fb3
fi
linux16 /vmlinuz-3.10.0-1160.92.1.el7.x86_64 root=/dev/mapper/VG01-lv_root ro crashkernel=auto rd.lvm.lv=VG01/lv_root rd.lvm.lv=VG01/lv_swap rhgb biosdevname=0 net.ifnames=0 quiet LANG=en_US.UTF-8
initrd16 /initramfs-3.10.0-1160.92.1.el7.x86_64.img
}
menuentry 'CentOS Linux (0-rescue-5f1865c966684867b0a1a7aec6828fb7) 7 (Core)' --class centos --class gnu-linux --class gnu --class os --unrestricted $menuentry_id_option 'gnulinux-0-rescue-5f1865c966684867b0a1a7aec6828fb7-advanced-6e2cc491-a60
3-4ec9-9677-65d425c720e2' {
load_video
insmod gzio
insmod part_msdos
insmod xfs
set root='hd0,msdos1'
if [ x$feature_platform_search_hint = xy ]; then
search --no-floppy --fs-uuid --set=root --hint-bios=hd0,msdos1 --hint-efi=hd0,msdos1 --hint-baremetal=ahci0,msdos1 --hint='hd0,msdos1' faa7906a-6ff7-4d7b-bf5e-5ecc4ac54fb3
else
search --no-floppy --fs-uuid --set=root faa7906a-6ff7-4d7b-bf5e-5ecc4ac54fb3
fi
linux16 /vmlinuz-0-rescue-5f1865c966684867b0a1a7aec6828fb7 root=/dev/mapper/VG01-lv_root ro crashkernel=auto rd.lvm.lv=VG01/lv_root rd.lvm.lv=VG01/lv_swap rhgb biosdevname=0 net.ifnames=0 quiet
initrd16 /initramfs-0-rescue-5f1865c966684867b0a1a7aec6828fb7.img
}
搞定之后,reboot
重启(注意这个地方千万别搞错,否则启动不了就直接原地暴毙了)。
4. 重启后格式化 VG01-lv_root
如果能够正常重启,最难的这一关就已经渡过,先 lsblk
确认下挂载情况:
bash
# lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
sda 8:0 0 50G 0 disk
├─sda1 8:1 0 200M 0 part
└─sda2 8:2 0 49.8G 0 part
├─VG01-lv_swap 253:0 0 8G 0 lvm /
└─VG01-lv_root 253:1 0 41.8G 0 lvm
sdb 8:16 0 1G 0 disk
└─data01vg-appslv 253:2 0 896M 0 lvm /apps
sr0 11:0 1 1024M 0 rom
可以看到根目录已经挂载到只有 8G 的 VG01-lv_swap 上了,现在 VG01-lv_root 已经腾挪出来了。
然后格式化:
bash
mkfs.xfs -f -n ftype=1 /dev/mapper/VG01-lv_root
临时挂载到 /mnt:
bash
mkdir -p /mnt # 如果原来没有这个目录就创建一下
mount /dev/mapper/VG01-lv_root /mnt
5. 再挪一次系统盘数据
bash
rsync -avxHAX --delete --devices --specials --exclude /mnt --exclude /apps --exclude /boot / /mnt/
挪完看一下是不是数据都在了,进入下一步。
6. 把启动条件改回去
修改 /mnt/etc/fstab,把根目录的挂载设备从 lv_swap 改回 lv_root
bash
#
# /etc/fstab
# Created by anaconda on Wed Feb 15 08:41:10 2017
#
# Accessible filesystems, by reference, are maintained under '/dev/disk'
# See man pages fstab(5), findfs(8), mount(8) and/or blkid(8) for more info
#
/dev/mapper/VG01-lv_root / xfs defaults 0 0
UUID=faa7906a-6ff7-4d7b-bf5e-5ecc4ac54fb3 /boot xfs defaults 0 0
#/dev/mapper/VG01-lv_swap swap swap defaults 0 0
/dev/mapper/data01vg-appslv /apps ext4 defaults 0 0
修改启动配置,修改 /boot/grub2/grub.cfg
,直接把原来备份那个挪回去就好。
中间出了点小插曲,发现 /boot 里面东西不见了,对照一下其他没改过的主机,是挂在在 /dev/sda1 上面的,因此临时挂载一下就 OK (mount /dev/sda1 /boot),不影响。
重启,大功告成。
结果验证
搞完之后,看一下挂载情况:
bash
# lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
sda 8:0 0 50G 0 disk
├─sda1 8:1 0 200M 0 part /boot
└─sda2 8:2 0 49.8G 0 part
├─VG01-lv_root 253:0 0 41.8G 0 lvm /
└─VG01-lv_swap 253:1 0 8G 0 lvm
sdb 8:16 0 1G 0 disk
└─data01vg-appslv 253:2 0 896M 0 lvm /apps
sr0 11:0 1 1024M 0 rom
众神归位,好,再看一下磁盘格式:
ini
# xfs_info /
meta-data=/dev/mapper/VG01-lv_root isize=512 agcount=4, agsize=2736896 blks
= sectsz=512 attr=2, projid32bit=1
= crc=1 finobt=0 spinodes=0
data = bsize=4096 blocks=10947584, imaxpct=25
= sunit=0 swidth=0 blks
naming =version 2 bsize=4096 ascii-ci=0 ftype=1
log =internal bsize=4096 blocks=5345, version=2
= sectsz=512 sunit=0 blks, lazy-count=1
realtime =none extsz=4096 blocks=0, rtextents=0
看到 ftype=1 了,说明系统盘格式已经转换成功。
再看看 CRI 接口的支持(如果还是不支持 overlay 的话就会报开始那个错误):
arduino
# crictl images
IMAGE TAG IMAGE ID SIZE
没有报错就是已经好了。
不确定通过 rsync 同步数据的方式是否会造成某些问题,但是目前来看一切正常,如果大家参考这个实践的话可能实际的硬盘挂载情况会有很大的不同,这里主要参考思路,切勿照搬,操作风险也比较大,请谨慎操作。