C15-OpenStack 儲存服務 1:Cinder 區塊儲存與後端整合
0. 環境與準備
0.1 本課環境
| 主機 | 角色 | 管理網 IP |
|---|---|---|
| jmp001 | 學員操作機(OpenStack CLI),接在外部網段 192.168.100.0/24 | 10.127.0.3 |
| ctl001 / ctl002 / ctl003 | 控制節點:cinder_api、cinder_scheduler | 10.127.0.4 / .14 / .15 |
| scp001 | 儲存節點:cinder_volume(LVM driver,後端名稱 lvm-1)、tgtd(iSCSI target) | 10.127.0.7 |
| scp002 | 運算節點:nova_compute、nova_libvirt、iscsid。你的 VM 放在這台 | 10.127.0.18 |
- 認證檔:jmp001 的
/home/ubuntu/creds/stuNN-openrc.sh(NN 為學員編號 01–20) - 你建立的資源一律以
c15-stuNN-開頭 - 需要看節點時,在 jmp001 用
ssh <節點 IP> "sudo …"送過去,和 C13 一樣
講師已建立全班共用的環境,請不要修改或刪除:
| 資源 | 名稱 | 說明 |
|---|---|---|
| Network / Router / SG | c15-net(192.168.15.0/24)、c15-router、c15-sg | 讓你的 VM 能綁 Floating IP,從 jmp001 SSH 進去。SG 放行 ICMP 與 TCP 22 |
| QoS Spec | c15-gold-qos | consumer front-end:total_iops_sec=500、total_bytes_sec=20971520(20 MiB/s) |
| Volume Type | c15-gold | volume_backend_name=lvm-1,並關聯 c15-gold-qos |
| Volume Type | c15-nowhere | volume_backend_name=no-such-backend:故意指向不存在的後端 |
本課 volume 在 scp001 上建立,VM 在 scp002 上跑,兩台之間用 iSCSI 連線。這正是 p.6、p.8 說的「LVM 例外」:target 在 cinder-volume 所在的主機上。
⚠️ 規則
- 你使用的是和講師相同的管理員權限,只操作名稱有你編號的資源
- 本環境沒有部署 cinder-backup。不要執行
volume backup create:它會留下一筆error紀錄,而且因為沒有 backup 服務,這筆紀錄無法用 API 刪除(D5 會說明)- 預期輸出是示意,UUID、IP、時間會與你看到的不同
0.2 準備,並先把 VM 建起來
0.2 和 0.3 作用的位置:
VM 開機需要一點時間,所以先送出建立指令,再往下看其他東西。
# [jmp001]
export NN=01 # ← 換成你的學員編號(01–20)
source ~/venv/bin/activate
source ~/creds/stu${NN}-openrc.sh
echo "c15-stu${NN}"
openstack server create c15-stu${NN}-vm --image cirros --flavor m1.tiny \
--network c15-net --security-group c15-sg \
--availability-zone nova:scp002-6164930-iaas -c id -c status預期輸出:
c15-stu01
+--------+--------------------------------------+
| Field | Value |
+--------+--------------------------------------+
| id | 6c544407-de12-4533-8c24-7a3ff8b3caf4 |
| status | BUILD |
+--------+--------------------------------------+- 若印出
c15-stu(沒有編號),代表NN沒設好,先修正再往下做 - 這台 VM 是 Boot from Local:開機碟 vda 放在 scp002 本機。本課要掛上去的 volume 是第二顆碟 vdb(p.2)
--availability-zone nova:<host>指定主機,讓全班的 VM 都在 scp002,資料路徑才會跨主機(scp002 → scp001)- 換終端機或重新 SSH 後,
export NN、兩個source,以及後面各節設定的變數都要重新執行
0.3 Cinder 的服務與後端(p.6、9、18)
# [jmp001]
openstack volume service list
openstack volume backend pool list --long -f yaml預期輸出:
+------------------+---------------------------+------+---------+-------+----------------------------+
| Binary | Host | Zone | Status | State | Updated At |
+------------------+---------------------------+------+---------+-------+----------------------------+
| cinder-scheduler | ctl002-6161063-iaas | nova | enabled | up | 2026-11-07T19:54:58.000000 |
| cinder-scheduler | ctl001-6161060-iaas | nova | enabled | up | 2026-11-07T19:54:58.000000 |
| cinder-scheduler | ctl003-6161069-iaas | nova | enabled | up | 2026-11-07T19:54:53.000000 |
| cinder-volume | scp001-6161072-iaas@lvm-1 | nova | enabled | up | 2026-11-07T19:54:59.000000 |
+------------------+---------------------------+------+---------+-------+----------------------------+
- Capabilities:
QoS_support: false
allocated_capacity_gb: 0
backend_state: up
cacheable: true
driver_version: 3.0.0
filter_function: null
free_capacity_gb: 475.0
goodness_function: null
location_info: LVMVolumeDriver:scp001-6161072-iaas:cinder-volumes:thin:0
max_over_subscription_ratio: '20.0'
multiattach: true
pool_name: lvm-1
provisioned_capacity_gb: 0.0
reserved_percentage: 0
storage_protocol: iSCSI
thick_provisioning_support: false
thin_provisioning_support: true
timestamp: '2026-11-07T19:54:09.468097'
total_capacity_gb: 475.0
total_volumes: 1
vendor_name: Open Source
volume_backend_name: lvm-1
Name: scp001-6161072-iaas@lvm-1#lvm-1- service list:
cinder-scheduler在三台控制節點上各跑一個cinder-volume只有一個,Host 欄位是主機@後端- 沒有
cinder-backup:本環境沒有部署它(p.6 的四個服務只有三個)
- pool list:
- pool 名稱是
host@backend#pool,之後每個 volume 都會記錄在這三段裡(p.7、9) storage_protocol: iSCSI:Compute 節點要用 iSCSI 連到這個後端(p.8)thin_provisioning_support: true和max_over_subscription_ratio: '20.0':可以超額配置到實際容量的 20 倍,所以要同時看provisioned_capacity_gb與實際使用量(p.18)QoS_support: false:這個後端不能做 back-end QoS,限速只能交給 Nova 的 front-end(A1 會看到)multiattach: true:這個後端支援多重掛載,但 Volume Type 還要設multiattach='<is> True'才會用到(p.4)
- pool 名稱是
Part A:用 Volume Type 申請 Volume(p.4、7、19)
下圖標出這一節每一步作用在哪個元件上(淡色的是這一節不會碰到的):
A1. 講師準備的兩個 Type
# [jmp001]
openstack volume type list --long
openstack volume qos list預期輸出:
+--------------------------------------+-------------+-----------+-------------------------------+---------------------------------------+
| ID | Name | Is Public | Description | Properties |
+--------------------------------------+-------------+-----------+-------------------------------+---------------------------------------+
| 95a89e5c-c712-4266-828f-2d4a14b6046d | c15-nowhere | True | C15: 指向不存在的後端 | volume_backend_name='no-such-backend' |
| 6f460bd9-a9c6-4708-bfa8-eda995cb4beb | c15-gold | True | C15: LVM 後端 + front-end QoS | volume_backend_name='lvm-1' |
| cf1a0609-3669-4736-8640-e15bd45e7867 | __DEFAULT__ | True | Default Volume Type | |
+--------------------------------------+-------------+-----------+-------------------------------+---------------------------------------+
+--------------------------------------+--------------+-----------+--------------+--------------------------------------------------+
| ID | Name | Consumer | Associations | Properties |
+--------------------------------------+--------------+-----------+--------------+--------------------------------------------------+
| 617f03c2-bc47-44f6-8779-3eaa4c1862f4 | c15-gold-qos | front-end | c15-gold | total_bytes_sec='20971520', total_iops_sec='500' |
+--------------------------------------+--------------+-----------+--------------+--------------------------------------------------+- 使用者只選 Type 的名稱。真正決定後端的是 Properties(extra specs)裡的
volume_backend_name(p.4) c15-gold-qos的 Consumer 是front-end:限速由 Nova(libvirt)在 VM 那一端執行,不是由儲存後端執行。C5 會在 VM 的設定裡看到它__DEFAULT__是default_volume_type,建立時不指定--type就用它
A2. 建立 Volume,看它落在哪裡
# [jmp001]
openstack volume create c15-stu${NN}-vol --type c15-gold --size 1 -c id -c status
sleep 3
openstack volume show c15-stu${NN}-vol -c status -c type -c size -c os-vol-host-attr:host
export VOL=$(openstack volume show c15-stu${NN}-vol -f value -c id); echo $VOL預期輸出:
+--------+--------------------------------------+
| Field | Value |
+--------+--------------------------------------+
| id | 02229066-fa48-4f05-97f3-556246776fd9 |
| status | creating |
+--------+--------------------------------------+
+-----------------------+---------------------------------+
| Field | Value |
+-----------------------+---------------------------------+
| os-vol-host-attr:host | scp001-6161072-iaas@lvm-1#lvm-1 |
| size | 1 |
| status | available |
| type | c15-gold |
+-----------------------+---------------------------------+
02229066-fa48-4f05-97f3-556246776fd9create一回應就是creating:cinder-api 只建立資料庫紀錄,然後交給 scheduler(p.7 步驟 1)- 幾秒後變成
available,os-vol-host-attr:host填上scp001-6161072-iaas@lvm-1#lvm-1:- scheduler 依 Type 選了後端(步驟 2)
- scp001 的 cinder-volume 呼叫 LVM driver 建好實體(步驟 3–5)
- 試跑時從送出到
available不到 5 秒
A3. 找不到後端的 Volume
# [jmp001]
openstack volume create c15-stu${NN}-bad --type c15-nowhere --size 1 -c status
sleep 5
openstack volume show c15-stu${NN}-bad -c status -c os-vol-host-attr:host
export BAD=$(openstack volume show c15-stu${NN}-bad -f value -c id)
openstack --os-volume-api-version 3.3 volume message list -f value -c "Resource UUID" -c "User Message" | grep $BAD預期輸出:
+--------+----------+
| Field | Value |
+--------+----------+
| status | creating |
+--------+----------+
+-----------------------+-------+
| Field | Value |
+-----------------------+-------+
| os-vol-host-attr:host | None |
| status | error |
+-----------------------+-------+
494e6297-3ab4-4bcb-8d47-b031566aa7b1 schedule allocate volume:Could not find any available weighted backend.- API 照樣接受請求(
creating),失敗發生在 scheduler:沒有任何後端回報volume_backend_name=no-such-backend,CapabilitiesFilter 把唯一的後端篩掉,於是進入error(p.7「沒有任何後端通過 filter 時,Volume 進入 error」) host是None:它從來沒有被分配到任何 cinder-volume,所以後端上什麼都沒有volume message list是給使用者看的錯誤訊息,不必翻日誌就能看出原因(p.17、19)。它需要 API microversion 3.3 以上,所以要加--os-volume-api-version 3.3- 全班的訊息都在同一個清單裡,所以用
grep $BAD只看你自己的
Part B:後端上的實體(p.8、9)
下圖標出這一節每一步作用在哪個元件上(淡色的是這一節不會碰到的):
# [jmp001]
ssh 10.127.0.7 "sudo lvs -o lv_name,lv_attr,lv_size,origin,data_percent cinder-volumes" | grep -E "LV|pool|$VOL"
ssh 10.127.0.7 "sudo docker exec tgtd tgtadm --lld iscsi --mode target --op show" | grep -c $VOL預期輸出:
LV Attr LSize Origin Data%
cinder-volumes-pool twi-aotz-- 475.00g 0.00
volume-02229066-fa48-4f05-97f3-556246776fd9 Vwi-a-tz-- 1.00g 0.00
0- 你的 volume 在 scp001 上就是 VG
cinder-volumes裡的 LVvolume-<VOL>,名稱直接用 volume ID - Attr 第一個字
V是 thin volume,它從 thin poolcinder-volumes-pool(Attr 開頭t)取空間。Data% 是 0.00:宣告 1 GB,實際上還沒用到任何空間(thin provisioning,p.18) - tgtd 裡沒有這個 volume 的 target(
grep -c是 0):LVM driver 要等到有人 attach 才會匯出
Part C:Attach 與資料路徑(p.11、12、15、4)
下圖標出這一節每一步作用在哪個元件上(淡色的是這一節不會碰到的):
C1. 綁 Floating IP,再 attach
# [jmp001]
openstack server show c15-stu${NN}-vm -c status -c OS-EXT-SRV-ATTR:host
export FIP=$(openstack floating ip create public1 --description c15-stu${NN}-fip -f value -c floating_ip_address)
openstack server add floating ip c15-stu${NN}-vm $FIP; echo $FIP
openstack server add volume c15-stu${NN}-vm c15-stu${NN}-vol
for i in 1 2 3 4 5 6; do echo "$(date +%T) $(openstack volume show $VOL -f value -c status)"; sleep 2; done預期輸出:
+----------------------+---------------------+
| Field | Value |
+----------------------+---------------------+
| OS-EXT-SRV-ATTR:host | scp002-6164930-iaas |
| status | ACTIVE |
+----------------------+---------------------+
192.168.100.100
+-----------------------+--------------------------------------+
| Field | Value |
+-----------------------+--------------------------------------+
| ID | 02229066-fa48-4f05-97f3-556246776fd9 |
| Server ID | 6c544407-de12-4533-8c24-7a3ff8b3caf4 |
| Volume ID | 02229066-fa48-4f05-97f3-556246776fd9 |
| Device | /dev/vdb |
| Tag | None |
| Delete On Termination | False |
+-----------------------+--------------------------------------+
03:57:07 reserved
03:57:10 attaching
03:57:14 in-use
03:57:16 in-use
03:57:18 in-use
03:57:20 in-use- VM 還不是
ACTIVE就等一下再 attach - 狀態依序是 p.11 的流程:
reserved:步驟 1 attachment-create,先保留這個 volumeattaching:步驟 2–5,nova-compute 收集 connector、取得 connection_info、登入 target、掛進 VMin-use:步驟 6 attachment-complete
- 試跑時從送出 attach 到
in-use約 12 秒 - 你看到的第一個狀態可能已經是
attaching或in-use,這也正常 Device /dev/vdb只是 Nova 的提示,Guest 裡不一定叫這個名字(p.15)
C2. Attachment 與 connection_info
# [jmp001]
openstack --os-volume-api-version 3.27 volume attachment list --volume-id $VOL
export ATT=$(openstack --os-volume-api-version 3.27 volume attachment list --volume-id $VOL -f value -c ID)
openstack --os-volume-api-version 3.27 volume attachment show $ATT -f yaml | grep -vE "auth_(username|password)"預期輸出:
+--------------------------------------+--------------------------------------+--------------------------------------+----------+
| ID | Volume ID | Server ID | Status |
+--------------------------------------+--------------------------------------+--------------------------------------+----------+
| befa172a-7500-47b0-85d7-938e3b8921d8 | 02229066-fa48-4f05-97f3-556246776fd9 | 6c544407-de12-4533-8c24-7a3ff8b3caf4 | attached |
+--------------------------------------+--------------------------------------+--------------------------------------+----------+
ID: befa172a-7500-47b0-85d7-938e3b8921d8
Volume ID: 02229066-fa48-4f05-97f3-556246776fd9
Instance ID: 6c544407-de12-4533-8c24-7a3ff8b3caf4
Status: attached
Attach Mode: rw
Attached At: '2026-11-07T19:57:07.000000'
Detached At: ''
Properties:
access_mode: rw
attachment_id: befa172a-7500-47b0-85d7-938e3b8921d8
auth_method: CHAP
cacheable: false
driver_volume_type: iscsi
encrypted: false
enforce_multipath: true
qos_specs:
total_bytes_sec: '20971520'
total_iops_sec: '500'
target_discovered: false
target_iqn: iqn.2010-10.org.openstack:volume-02229066-fa48-4f05-97f3-556246776fd9
target_lun: 1
target_portal: 10.127.0.7:3260
volume_id: 02229066-fa48-4f05-97f3-556246776fd9- Attachment 是 Cinder 裡「這個 volume 連到哪個消費者」的紀錄(p.3、11)
attachment指令需要 microversion 3.27- 全班的 attachment 都在同一個清單裡,所以用
--volume-id篩選
Properties就是 driver 產生的 connection_info(p.15),nova-compute 靠它連到後端:driver_volume_type: iscsi:用 iSCSI 協定target_portal: 10.127.0.7:3260:target 在 scp001,也就是 cinder-volume 那台主機target_iqn:target 名稱,結尾就是 volume IDauth_method: CHAP:登入要帳號密碼,每個 volume 一組qos_specs:front-end QoS 也跟著 connection_info 交給 Nova
- ⚠️ 指令用
grep -v拿掉了auth_username/auth_password兩行,那是這個 volume 的 iSCSI CHAP 帳密。不要把完整輸出貼到任何地方
C3. scp001:tgtd 匯出了 target
只印出你自己的 target,CHAP 帳號以「略」取代:
# [jmp001]
ssh 10.127.0.7 "sudo docker exec tgtd tgtadm --lld iscsi --mode target --op show" \
| awk -v v="$VOL" '/^Target/{p=index($0,v)>0} /Account information/{if(p)print " Account information: (CHAP 帳號,略)"; s=1; next} /ACL information/{s=0} p&&!s' \
| grep -vE "SCSI|Removable|Prevent|Readonly|SWP|Online|flags|Thin"預期輸出:
Target 1: iqn.2010-10.org.openstack:volume-02229066-fa48-4f05-97f3-556246776fd9
System information:
Driver: iscsi
State: ready
I_T nexus information:
I_T nexus: 29
Initiator: iqn.2016-04.com.open-iscsi:a94163e4c3ce alias: scp002-6164930-iaas
Connection: 0
IP Address: 10.127.0.18
LUN information:
LUN: 0
Type: controller
Size: 0 MB, Block size: 1
Backing store type: null
Backing store path: None
LUN: 1
Type: disk
Size: 1074 MB, Block size: 512
Backing store type: rdwr
Backing store path: /dev/cinder-volumes/volume-02229066-fa48-4f05-97f3-556246776fd9
Account information: (CHAP 帳號,略)
ACL information:
ALL- B 節還沒有的 target,attach 後出現了,這是 p.11 步驟 4「Driver 建立匯出」的結果
I_T nexus:已經有 initiator 連進來,來源是 scp002(10.127.0.18)LUN 1的Backing store path就是 B 節看到的 LV:tgtd 把 LV 直接當成磁碟匯出ACL information: ALL:tgtd 不以 IP 限制,存取控制靠的是 CHAP 帳密
C4. scp002:iSCSI session 與主機上的裝置
# [jmp001]
ssh 10.127.0.18 "sudo docker exec iscsid iscsiadm -m session" | grep $VOL
ssh 10.127.0.18 "ls -l /dev/disk/by-path/" | grep $VOL預期輸出:
tcp: [23] 10.127.0.7:3260,1 iqn.2010-10.org.openstack:volume-02229066-fa48-4f05-97f3-556246776fd9 (non-flash)
lrwxrwxrwx 1 root root 9 Nov 8 03:57 ip-10.127.0.7:3260-iscsi-iqn.2010-10.org.openstack:volume-02229066-fa48-4f05-97f3-556246776fd9-lun-1 -> ../../sda- scp002 的
iscsid容器已經登入 scp001 的 target(p.15:「os-brick 以 iscsiadm 登入 target」) - 主機上出現一顆 SCSI 磁碟(例子是
sda)。全班 20 人的 volume 都會掛在 scp002,所以字母不一定是sda,以 by-path 名稱裡的 volume ID 為準 - 這條連線是 scp002 → scp001 直接連,不經過控制節點,也不經過 cinder-volume 程式,這就是 p.12 的「資料路徑」
C5. scp002:libvirt 把它交給 VM
# [jmp001]
export INST=$(openstack server show c15-stu${NN}-vm -f value -c OS-EXT-SRV-ATTR:instance_name); echo $INST
ssh 10.127.0.18 "sudo docker exec nova_libvirt virsh domblklist $INST"
ssh 10.127.0.18 "sudo docker exec nova_libvirt virsh dumpxml $INST" | grep -B3 -A8 "<target dev='vdb'"預期輸出:
instance-00000099
Target Source
-----------------------------------------------------------------------------
vda /var/lib/nova/instances/6c544407-de12-4533-8c24-7a3ff8b3caf4/disk
vdb /dev/sda
<driver name='qemu' type='raw' cache='none' io='native'/>
<source dev='/dev/sda' index='3'/>
<backingStore/>
<target dev='vdb' bus='virtio'/>
<iotune>
<total_bytes_sec>20971520</total_bytes_sec>
<total_iops_sec>500</total_iops_sec>
</iotune>
<serial>02229066-fa48-4f05-97f3-556246776fd9</serial>
<alias name='ua-02229066-fa48-4f05-97f3-556246776fd9'/>vda是 scp002 本機的檔案(Boot from Local);vdb的來源是 C4 那顆 iSCSI 磁碟。QEMU 只是把主機上的區塊裝置交給 VM<iotune>:A1 的 front-end QoS 實際生效的地方。限速由 QEMU 執行,後端完全不知道(p.4 講者備註)<serial>是 volume ID,C6 會在 Guest 裡看到它
C6. 進 VM 看,並寫入一筆資料
# [jmp001]
echo $VOL | cut -c1-20
ssh cirros@$FIP第一次連線會問 Are you sure you want to continue connecting (yes/no/[fingerprint])?,輸入 yes。密碼是 cirros 映像的預設密碼 gocubsgo。進入後執行(把 01 換成你的編號):
# [c15-stuNN-vm]
lsblk
cat /sys/block/vdb/serial; echo
ls /dev/disk/by-id/
echo c15-stu01-hello | sudo dd of=/dev/vdb bs=512 count=1 conv=sync,fsync
sudo dd if=/dev/vdb bs=32 count=1 2>/dev/null; echo
exit預期輸出([jmp001] 那行在前,之後是 VM 裡的輸出):
02229066-fa48-4f05-9
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINTS
vda 252:0 0 1G 0 disk
|-vda1 252:1 0 1015M 0 part /
`-vda15 252:15 0 8M 0 part
vdb 252:16 0 1G 0 disk
02229066-fa48-4f05-9
ls: /dev/disk/by-id/: No such file or directory
0+1 records in
1+0 records out
c15-stu01-hello- Guest 看到的只是一顆 1 GB 的 virtio 磁碟
vdb,不知道後面是 iSCSI,也不知道是 LVM(p.15「Guest 看到的都是磁碟」) /sys/block/vdb/serial是 volume ID 的前 20 碼(virtio 的 serial 長度上限),和[jmp001]印出的一致。有多顆 volume 時,以這個對應,不要相信/dev/vdX的字母- p.15 和 p.13 講者備註說的
/dev/disk/by-id/,在一般 Linux(有 udev)會出現virtio-02229066-fa48-4f05-9這樣的名稱 - cirros 沒有 udev,所以沒有這個目錄,改看
/sys的 serial
- p.15 和 p.13 講者備註說的
dd … conv=fsync把字串直接寫進磁碟第一個 sector,並要求 Guest 確實寫出去。這樣 D 節的 snapshot 才會包含它(p.17「Guest 內先執行 sync」)
Part D:Snapshot 與狀態機(p.16、17)
下圖標出這一節每一步作用在哪個元件上(淡色的是這一節不會碰到的):
D1. 對 in-use 的 volume 做 snapshot
# [jmp001]
openstack volume snapshot create c15-stu${NN}-snap --volume c15-stu${NN}-vol
openstack volume snapshot create c15-stu${NN}-snap --volume c15-stu${NN}-vol --force -c id -c status
sleep 3
export SNAP=$(openstack volume snapshot show c15-stu${NN}-snap -f value -c id)
openstack volume snapshot show c15-stu${NN}-snap -c status
ssh 10.127.0.7 "sudo lvs -o lv_name,lv_attr,lv_size,origin,data_percent cinder-volumes" | grep -E "LV|$VOL|$SNAP"預期輸出:
Invalid volume: Volume 02229066-fa48-4f05-97f3-556246776fd9 status must be available, but current status is: in-use. (HTTP 400) (Request-ID: req-8d45fda3-8955-4cb1-9b6c-d1bd90f58ef7)
+--------+--------------------------------------+
| Field | Value |
+--------+--------------------------------------+
| id | af2cad90-fd20-4c18-b23d-b3699372c500 |
| status | creating |
+--------+--------------------------------------+
+--------+-----------+
| Field | Value |
+--------+-----------+
| status | available |
+--------+-----------+
LV Attr LSize Origin Data%
_snapshot-af2cad90-fd20-4c18-b23d-b3699372c500 Vwi---tz-k 1.00g volume-02229066-fa48-4f05-97f3-556246776fd9
volume-02229066-fa48-4f05-97f3-556246776fd9 Vwi-aotz-- 1.00g 0.02- 第一次被拒絕(HTTP 400):volume 正在
in-use,Cinder 不知道 Guest 有沒有寫到一半。加--force表示「我已經自己處理好一致性」(p.17:in-use 要加--force;Snapshot 成功不代表應用程式一致) - 試跑時 snapshot 1–3 秒就
available:LVM thin 的 snapshot 是 copy-on-write,不複製資料(p.17「建立速度:快」) - 在 scp001 上,snapshot 是另一個 thin LV
_snapshot-<SNAP>:Origin指向你的 volume- Attr 最後的
k(activation skip)表示平常不啟用 - 它和 volume 在同一個 thin pool:這個後端壞掉,兩者一起不見(p.17「無法防範後端故障」)
D2. 從 snapshot 建立新 volume
# [jmp001]
openstack volume create c15-stu${NN}-clone --snapshot c15-stu${NN}-snap -c status
sleep 6
openstack volume show c15-stu${NN}-clone -c status -c type -c snapshot_id -c os-vol-host-attr:host
export CLONE=$(openstack volume show c15-stu${NN}-clone -f value -c id)
ssh 10.127.0.7 "sudo lvs -o lv_name,lv_attr,lv_size,origin,data_percent cinder-volumes" | grep -E "LV|$VOL|$SNAP|$CLONE"
ssh 10.127.0.7 "sudo dd if=/dev/cinder-volumes/volume-$CLONE bs=32 count=1 2>/dev/null"; echo預期輸出:
+--------+----------+
| Field | Value |
+--------+----------+
| status | creating |
+--------+----------+
+-----------------------+--------------------------------------+
| Field | Value |
+-----------------------+--------------------------------------+
| os-vol-host-attr:host | scp001-6161072-iaas@lvm-1#lvm-1 |
| snapshot_id | af2cad90-fd20-4c18-b23d-b3699372c500 |
| status | available |
| type | c15-gold |
+-----------------------+--------------------------------------+
LV Attr LSize Origin Data%
_snapshot-af2cad90-fd20-4c18-b23d-b3699372c500 Vwi-a-tz-k 1.00g volume-02229066-fa48-4f05-97f3-556246776fd9 0.02
volume-02229066-fa48-4f05-97f3-556246776fd9 Vwi-aotz-- 1.00g 0.02
volume-94ef8ed3-2c5e-4589-bf1c-743e39771089 Vwi-a-tz-- 1.00g _snapshot-af2cad90-fd20-4c18-b23d-b3699372c500 0.02
c15-stu01-hello- 新 volume 沿用原 volume 的 Type(
c15-gold),也一定在同一個後端:snapshot 只存在於這個後端 - 新 LV 的
Origin是 snapshot,同樣是 thin,只要幾秒(試跑約 6 秒) - 直接在後端讀新 LV 的第一個 sector,看到 C6 在 VM 裡寫入的字串:snapshot 確實保留了寫入當下的內容。這次讀取完全不經過 OpenStack
D3. 狀態機擋下的操作
# [jmp001]
openstack volume delete c15-stu${NN}-vol
openstack volume list --long -c Name -c Status -c Type -c "Attached to" | grep -E "Name|c15-stu${NN}-"預期輸出:
Failed to delete volume with name or ID 'c15-stu01-vol': Invalid volume: Volume status must be available or error or error_restoring or error_extending or error_managing and must not be migrating, attached, belong to a group, have snapshots, awaiting a transfer, or be disassociated from snapshots after volume transfer. (HTTP 400) (Request-ID: req-2bfd2f95-4440-4a61-97d4-47982a0200ae)
1 of 1 volumes failed to delete.
| Name | Status | Type | Attached to |
| c15-stu01-clone | available | c15-gold | |
| c15-stu01-bad | error | c15-nowhere | |
| c15-stu01-vol | in-use | c15-gold | Attached to c15-stu01-vm on /dev/vdb |- 錯誤訊息列出了刪除的條件:狀態必須是
available或error系列,而且不能 attached、不能有 snapshot。你的 volume 兩項都不符合 - 對照 p.16:
in-use是穩定狀態,「避免刪除或未確認的破壞性操作」。error的c15-stuNN-bad則可以直接刪(F 節)
D4. 先刪 snapshot 會怎樣?
p.17 的建議順序是「先刪由 snapshot 建立的 volume,再刪 snapshot」,因為部分後端的 clone 依賴 snapshot。在這個 LVM thin 後端上試試看:
# [jmp001]
openstack volume snapshot delete c15-stu${NN}-snap
sleep 4
openstack volume snapshot list | grep -c c15-stu${NN}-snap
ssh 10.127.0.7 "sudo lvs -o lv_name,lv_attr,lv_size,origin,data_percent cinder-volumes" | grep -E "LV|$VOL|$SNAP|$CLONE"預期輸出:
0
LV Attr LSize Origin Data%
volume-02229066-fa48-4f05-97f3-556246776fd9 Vwi-aotz-- 1.00g 0.02
volume-94ef8ed3-2c5e-4589-bf1c-743e39771089 Vwi-a-tz-- 1.00g 0.02- 在 LVM thin 上,snapshot 可以先刪:clone 的
Origin變成空的,資料仍在。thin LV 共用 pool 的資料區塊,沒有誰依賴誰 - 換成 Ceph RBD,clone 是指向 snapshot 的 copy-on-write 子映像,就可能因為相依而刪不掉或要先 flatten。所以 p.17 的順序是「跨後端都安全」的做法,不代表每個後端都強制
D5. Snapshot ≠ Backup(只看,不要做)
# [jmp001]
openstack volume service list -c Binary -c Host -c State預期輸出:
+------------------+---------------------------+-------+
| Binary | Host | State |
+------------------+---------------------------+-------+
| cinder-scheduler | ctl002-6161063-iaas | up |
| cinder-scheduler | ctl001-6161060-iaas | up |
| cinder-scheduler | ctl003-6161069-iaas | up |
| cinder-volume | scp001-6161072-iaas@lvm-1 | up |
+------------------+---------------------------+-------+- 清單裡沒有
cinder-backup,所以這朵雲做不了 Backup(p.17:Backup 寫入獨立的 Backup Repository,才能防範後端故障) - 講師試跑時執行過
volume backup create:- API 照樣接受,但 backup 立刻變成
error volume message list顯示Backup failed to schedule. Service not found for creating backup.- 要刪掉這筆紀錄,
volume backup delete會回 404Service cinder-backup could not be found:刪除也要交給 backup 服務,所以留下一筆刪不掉的紀錄
- API 照樣接受,但 backup 立刻變成
- 這也是 p.18 說的「不可只改資料庫」的反面:要清掉它,正確做法是先把服務部署回來,而不是直接改 DB
Part E:Detach 與擴充(p.11、16)
下圖標出這一節每一步作用在哪個元件上(淡色的是這一節不會碰到的):
E1. Detach:連線依序拆掉
# [jmp001]
openstack server remove volume c15-stu${NN}-vm c15-stu${NN}-vol
for i in 1 2 3; do echo "$(date +%T) $(openstack volume show $VOL -f value -c status)"; sleep 2; done
openstack --os-volume-api-version 3.27 volume attachment list --volume-id $VOL
ssh 10.127.0.7 "sudo docker exec tgtd tgtadm --lld iscsi --mode target --op show" | grep -c $VOL
ssh 10.127.0.18 "sudo docker exec iscsid iscsiadm -m session" | grep -c $VOL預期輸出:
04:00:39 detaching
04:00:42 available
04:00:44 available
0
iscsiadm: No active sessions.
0- detach 是 attach 的反向:nova-compute 先把磁碟從 VM 拔掉、登出 iSCSI,再請 Cinder 刪除 attachment 與 target(p.11 講者備註)
- 試跑約 6 秒回到
available。之後 attachment 清單是空的(只印一行空白),scp001 的 target 和 scp002 的 session 都消失(兩個grep -c都是 0) iscsiadm: No active sessions.是 scp002 上已經沒有任何 iSCSI session 時印出的訊息。全班同時做時,別人的 session 可能還在,就不會出現這行,以grep -c的 0 為準- volume 本身和裡面的資料都還在,可以再掛到別台 VM(p.2「detach 後可掛到其他 VM」)
E2. 擴充,以及不能縮小
# [jmp001]
openstack volume set --size 2 c15-stu${NN}-vol
sleep 3
openstack volume show c15-stu${NN}-vol -c size -c status
ssh 10.127.0.7 "sudo lvs -o lv_name,lv_size cinder-volumes" | grep $VOL
openstack volume set --size 1 c15-stu${NN}-vol預期輸出:
+--------+-----------+
| Field | Value |
+--------+-----------+
| size | 2 |
| status | available |
+--------+-----------+
volume-02229066-fa48-4f05-97f3-556246776fd9 2.00g
Failed to set volume size: New size must be greater than 2 GB
One or more of the set operations failed- 擴充期間短暫進入
extending(p.16 的過渡狀態),試跑時 3 秒內完成,LV 變成 2 GB - 縮小會被拒絕:Cinder 不知道 Guest 的檔案系統用到哪裡,縮小可能截斷資料
Part F:清除
下圖標出這一節每一步作用在哪個元件上(淡色的是這一節不會碰到的):
# [jmp001]
openstack volume delete c15-stu${NN}-clone c15-stu${NN}-vol c15-stu${NN}-bad
openstack floating ip delete $(openstack floating ip list --long -f value -c ID -c Description | awk -v d=c15-stu${NN}-fip '$2==d{print $1}')
openstack server delete --wait c15-stu${NN}-vm
sleep 3
openstack volume list --name c15-stu${NN} -f value -c Name
openstack volume snapshot list -f value -c Name | grep c15-stu${NN}
openstack server list --name c15-stu${NN} -f value -c Name
ssh 10.127.0.7 "sudo lvs cinder-volumes" | grep -cE "$VOL|$CLONE"預期輸出:(前三個查詢沒有輸出)
0- 依 p.17 的順序:
- 由 snapshot 建立的 clone
- snapshot(D4 已經刪了)
- 原 volume
- 原 volume 在 E1 已經 detach,
error的 bad volume 可以直接刪 - 最後一行檢查 scp001 上不再有你的 LV
- 如果某個 volume 刪不掉,先看它的狀態,不要用
volume set --state硬改(p.18),請找講師
小結
| 試跑量測(單人) | 時間 |
|---|---|
volume create → available | < 5 秒 |
c15-nowhere → error | < 5 秒 |
attach:送出 → in-use | 約 12 秒(reserved → attaching → in-use) |
snapshot(--force)→ available | 1–3 秒 |
| 由 snapshot 建立 volume | 約 6 秒 |
detach → available | 約 6 秒 |
| extend 1 → 2 GB | < 3 秒 |
| 你看到的 | 在哪裡 | 對應簡報 |
|---|---|---|
host@backend#pool | volume show 的 os-vol-host-attr:host | p.7、9 |
| scheduler 找不到後端 | volume message list | p.7、19 |
| volume 的實體 | scp001 的 LV volume-<ID>(thin) | p.8、9 |
| connection_info | volume attachment show 的 Properties | p.11、15 |
| iSCSI target / session | scp001 tgtd、scp002 iscsid | p.12、15 |
| front-end QoS | VM XML 的 <iotune> | p.4 |
| Guest 裡對應 volume | /sys/block/vdX/serial(或 /dev/disk/by-id/) | p.15 |
| snapshot 在同一個後端 | 同一個 thin pool 的 _snapshot-<ID> | p.17 |