移动云计算Libvirt集成Ceph iSCSI
由于 Arch Linux ARM的软件仓库对 libvirt-storage-ceph
缺失,所以我在部署 移动云计算Libvirt集成Ceph RBD 遇到较大困难暂时放弃。我调整方案,改为采用 Ceph iSCSI 为 KVM 虚拟化服务器集群提供分布式存储。
Ceph iSCSI 可以解决客户端(libvirt)无法原生支持Ceph的缺憾,通过输出 Ceph RADOS 块设备(RBD)镜像作为SCSI磁盘来提供了一个高可用(Highly Available, HA) iSCSI target:

通过Ceph iSCSI网关将RBD镜像映射为iSCSI target
准备工作
为减少iSCSI initiator超时的可能性,调整OSD监控检测的心跳间隔,即修订
/etc/ceph/ceph.conf
配置:
[osd]
osd heartbeat grace = 20
osd heartbeat interval = 5
从一个Ceph Monitor (ceph-mon)节点更新运行状态:
ceph tell osd.* config set osd_heartbeat_grace 20
ceph tell osd.* config set osd_heartbeat_interval 5
在每个OSD节点 上更新运行状态:
# 在第一个节点上针对 osd.0 更新osd服务的心跳服务状态,其他节点依次类推
ceph daemon osd.0 config set osd_heartbeat_grace 20
ceph daemon osd.0 config set osd_heartbeat_interval 5
部署 Ceph iSCSI
Ceph iSCSI 部署比预想要复杂,虽然客户端可以采用标准的iSCSI initator访问,但是服务端iSCSI和客户端initator需要配置完成以下步骤:
libvirt支持iSCSI方式
libvirt有两种方式使用iSCSI:
iSCSI pool: 使用iSCSI target来存储卷,所有卷需要在iSCSI服务器上预先分配
iSCSI direct pool: 是iSCSI pool的变体,不使用iscsiadm,而是使用
libscsi
,需要提供 host , target IQN 和 initiator IQN
libvirt配置iSCSI存储池(iSCSI pool)
target path
决定了libvirt如何输出(expose)存储池的的河北路径: /dev/sda
/dev/sdb
等路径不是好多选择,因为这些路径在启动时不稳定,或者在集群中的机器上不稳定(名称由内核按照先到先得的原则分配)。强烈建议使用 /dev/disk/by-path
,除非你知道自己在做什么(显然大多数情况你不知道^_^)。这种 /dev/disk/by-path
的路径名可以获得稳定的命名方案。
host name
是iSCSI服务器的FQDN
Source Path
是创建iSCSI target时候获得的IQN,我的案例是 iqn.2022-12.io.cloud-atlas.iscsi-gw:iscsi-igw
( 见 Ceph iSCSI initator客户端 扫描 配置Ceph iSCSI网关 输出的iSCSI Node )
创建一个
ceph_iscsi_libvirt.xml
配置:
<pool type='iscsi'>
<name>images_iscsi</name>
<source>
<host name='a-b-data-2.dev.cloud-atlas.io'/>
<device path='iqn.2022-12.io.cloud-atlas.iscsi-gw:iscsi-igw'/>
<auth type='chap' username='libvirtd'>
<secret usage='libvirtiscsi'/>
</auth>
</source>
<target>
<path>/dev/disk/by-path</path>
</target>
</pool>
使用
virsh
定义iSCSI存储池:
sudo virsh pool-define ceph_iscsi_libvirt.xml
提示信息:
Pool images_iscsi defined from ceph_iscsi_libvirt.xml
检查存储池
images_iscsi
尚未激活:
sudo virsh pool-list --all
显示输出:
Name State Autostart
--------------------------------------
...
images_iscsi inactive no
参考 Secret XML format: Usage type "iscsi" 在
ceph_iscsi_libvirt.xml
中定义了<secret usage='libvirtiscsi'/>
这个secret,现在就需要创建这个secret,然后再给这个secret插入密码值(你可以认为这是一个分离的密码本):
<secret ephemeral='no' private='yes'>
<description>Passphrase for the ceph iSCSI</description>
<usage type='iscsi'>
<target>libvirtiscsi</target>
</usage>
</secret>
执行以下命令创建secret:
sudo virsh secret-define ceph_iscsi_libvirt_secret.xml
此时会提示这个secret对应的UUID,例如:
ca36b1f9-6299-4b69-a3c9-c44e1349c66d
然后向secret插入密码值:
virsh secret-set-value --interactive ca36b1f9-6299-4b69-a3c9-c44e1349c66d
在交互模式下输入密钥,则提示secret的值设置成功:
Enter new value for secret:
Secret value set
终于,我们现在完成了认证密钥设置,可以启动存储池了
激活存储池
images_iscsi
并设置为自动启动:
sudo virsh pool-start images_iscsi
这里可能会提示错误:
error: Failed to start pool images_iscsi
error: internal error: Child process (/usr/bin/iscsiadm --mode node --portal a-b-data-2.dev.cloud-atlas.io:3260,1 --targetname iqn.2022-12.io.cloud-atlas.iscsi-gw:iscsi-igw --login) unexpected exit status 15: iscsiadm: Could not login to [iface: default, target: iqn.2022-12.io.cloud-atlas.iscsi-gw:iscsi-igw, portal: a-b-data-2.dev.cloud-atlas.io,3260].
iscsiadm: initiator reported error (15 - session exists)
iscsiadm: Could not log into all portals
原因是之前的会话没有退出,需要先退出。
但是我发现奇怪,我执行了:
sudo iscsiadm -m node -T iqn.2022-12.io.cloud-atlas.iscsi-gw:iscsi-igw -u
并且重复执行上述logout命令,已经明确看到:
iscsiadm: No matching sessions found
说明没有当前会话
但是再次启动 images_iscsi
存储池还是同样报错,而再次执行 iscsiadm
logout,发现确实又出现了会话。这说明执行启动存储确实发起了iscsi登陆会话。
我考虑之前实践 Ceph iSCSI initator客户端 配置了initator,所以执行 从系统删除iSCSI会话 然后再重复上述启动libvirt iSCSI pool操作,就可以看到成功启动:
sudo virsh pool-start images_iscsi
输出显示:
Pool images_iscsi started
设置 iSCSI pool 自动启动
virsh pool-autostart images_iscsi
提示信息:
Pool images_iscsi marked as autostarted
查询LUN信息
在完成 libvirt 访问iSCSI target的存储池配置之后,就可以查询存储池中的LUN来获得那些而可用的虚拟磁盘。注意 libvirt iSCSI pool
不支持直接操作远程iSCSI target服务器上的磁盘创建(重大安全隐患),所以必须在 配置Ceph iSCSI网关 为libvirt客户端创建好磁盘并attach。
显然,这个 libvirt iSCSI pool
的功能比较简陋,远比不上 Libvirt集成Ceph RBD 方便灵活。如果作为云计算,需要有辅助工具平台来串联整个流程
查询远程iSCSI target提供的LUN磁盘:
virsh vol-list images_iscsi
可以看到 配置Ceph iSCSI网关 配置的5块磁盘:
Name Path
---------------------------------------------------------------------------------------------------------------------------------
unit:0:0:0 /dev/disk/by-path/ip-a-b-data-2.dev.cloud-atlas.io:3260-iscsi-iqn.2022-12.io.cloud-atlas.iscsi-gw:iscsi-igw-lun-0
unit:0:0:1 /dev/disk/by-path/ip-a-b-data-2.dev.cloud-atlas.io:3260-iscsi-iqn.2022-12.io.cloud-atlas.iscsi-gw:iscsi-igw-lun-1
unit:0:0:2 /dev/disk/by-path/ip-a-b-data-2.dev.cloud-atlas.io:3260-iscsi-iqn.2022-12.io.cloud-atlas.iscsi-gw:iscsi-igw-lun-2
unit:0:0:3 /dev/disk/by-path/ip-a-b-data-2.dev.cloud-atlas.io:3260-iscsi-iqn.2022-12.io.cloud-atlas.iscsi-gw:iscsi-igw-lun-3
unit:0:0:4 /dev/disk/by-path/ip-a-b-data-2.dev.cloud-atlas.io:3260-iscsi-iqn.2022-12.io.cloud-atlas.iscsi-gw:iscsi-igw-lun-4
上述远程iSCSI target LUNs已经被映射到本地作为本地块设备,可以通过
virsh vol-info
命令检查,例如检查第一块磁盘:
# virsh vol-info可以检查LUN信息,将iSCSI target LUN作为本地磁盘
virsh vol-info /dev/disk/by-path/ip-a-b-data-2.dev.cloud-atlas.io:3260-iscsi-iqn.2022-12.io.cloud-atlas.iscsi-gw:iscsi-igw-lun-0
输出信息可以看到这个磁盘就如 配置Ceph iSCSI网关 所配置的服务器端RBD设备情况:
Name: unit:0:0:0
Type: block
Capacity: 10.00 GiB
Allocation: 10.00 GiB
通过
virsh vol-dumpxml
命令可以获得LUN信息:
virsh vol-dumpxml /dev/disk/by-path/ip-a-b-data-2.dev.cloud-atlas.io:3260-iscsi-iqn.2022-12.io.cloud-atlas.iscsi-gw:iscsi-igw-lun-0
输出信息如下:
<volume type='block'>
<name>unit:0:0:0</name>
<key>360014057d19ff6d9865427e94cba1e76</key>
<capacity unit='bytes'>10737418240</capacity>
<allocation unit='bytes'>10737418240</allocation>
<physical unit='bytes'>10737418240</physical>
<target>
<path>/dev/disk/by-path/ip-a-b-data-2.dev.cloud-atlas.io:3260-iscsi-iqn.2022-12.io.cloud-atlas.iscsi-gw:iscsi-igw-lun-0</path>
<permissions>
<mode>0660</mode>
<owner>0</owner>
<group>995</group>
</permissions>
<timestamps>
<atime>1671959189.366283420</atime>
<mtime>1671959189.366283420</mtime>
<ctime>1671959189.366283420</ctime>
<btime>0</btime>
</timestamps>
</target>
</volume>
使用iSCSI LUN磁盘创建虚拟机
既然iSCSI target KUN磁盘已经就绪,由于我的整个环境是在 ARM硬件环境KVM虚拟化 ( Apple ARM架构芯片M1 Pro Macbook Pro上 ),所以构建虚拟机方法也采用 arch linux ARM KVM虚拟化 方式相同(虚拟机OS选择 Fedora ):
host="a-k8s-m-1"
virt-install \
--network bridge:virbr0 \
--name ${host} \
--ram=3072 \
--vcpus=2 \
--arch aarch64 \
--boot uefi \
--disk path=/dev/disk/by-path/ip-a-b-data-2.dev.cloud-atlas.io:3260-iscsi-iqn.2022-12.io.cloud-atlas.iscsi-gw:iscsi-igw-lun-0,format=raw,bus=virtio,cache=writeback,io=threads \
--cdrom=/var/lib/libvirt/images/Fedora-Server-dvd-aarch64-37-1.7.iso
详细安装步骤同 arch linux ARM KVM虚拟化 中 Fedora 37 Server安装
重复上述步骤,完成5个虚拟机的部署,完成后虚拟机列表:
# virsh list
Id Name State
----------------------------
1 a-b-data-2 running
2 a-b-data-1 running
3 a-b-data-3 running
5 a-k8s-m-1 running
8 a-k8s-m-3 running
11 a-k8s-m-2 running
12 a-k8s-n-2 running
13 a-k8s-n-1 running
以下段落仅记录参考,暂未实践
libvirt配置iSCSI直接存储池(iSCSI direct pool)
警告
iSCSI direct pool
我没有实践(暂时没有时间精力)
libvirt通过 libiscsi
来构建iSCSI direct pool 访问iSCSI target,配置需要:
host
target IQN
initator IQN
iSCSI direct pool的支持是libvirt v4.7.0开始支持的( iSCSI pool 则是早期 v0.4.1 开始支持 )
创建一个
ceph_direct_iscsi_libvirt.xml
配置:
<pool type="iscsi-direct">
<name>images_iscsi_direct</name>
<source>
<host name="a-b-data-2.dev.cloud-atlas.io"/>
<device path="iqn.2022-12.io.cloud-atlas.iscsi-gw:iscsi-igw"/>
<auth type='chap' username='libvirtd'>
<secret usage='mypassword12'/>
</auth>
<initiator>
<iqn name="iqn.1989-06.io.cloud-atlas:libvirt-client"/>
</initiator>
</source>
</pool>
multipath
警告
multipath
我没有实践(暂时没有时间精力)
备注
openstack/cinder-specs/specs/kilo/iscsi-multipath-enhancment.rst 介绍了 nova-compute 支持iSCSI卷数据路径的multipath。但我还没有找到 libvirt 采用 multipath 的参考资料,后续再实践
从 libvirt storage: Multipath pool 来看,仅提供一个本地挂载的Multipath pool,主要实现应该是依赖主机底层的multipath来实现的。