從快照還原虛擬機(執行個體)
本指南說明如何使用 snapshot-restore.sh 腳本,從已掛載的 OpenStack 磁碟的其中一個 Cinder 快照中還原該磁碟。
此腳本會提示您選擇專案、伺服器、已掛載的磁碟以及快照。 接著,它會關閉虛擬機,還原所選的 Ceph RBD 快照,然後重新啟動虛擬機。 如需完整的樣本還原工作流程,請參閱 完整還原作業的範例輸出。
從快照還原磁碟會覆寫所有的磁碟資料。 您將失去快照建立後所做的任何變更。
開始之前
請確認執行此腳本的主機具備所需的 OpenStack 和 Ceph 存取權限。
透過 SSH 以 root 身分連線至叢集
瞭解如何使用 SSH 連線至 CubeCOS 叢集的 root shell,以執行管理任務。
-
開啟您的終端機。
-
請使用以下指令透過 SSH(安全殼層協定)連線至您的 CubeCOS 叢集:
ssh root@<your-cluster-vip> -
出現提示時,請輸入您的 SSH 密碼。
從快照還原磁碟
-
將腳本儲存為
snapshot-restore.sh。 請從 完整還原腳本 取得該腳本。 -
將腳本設為可執行。
Make the restore script executablechmod +x snapshot-restore.sh -
執行該腳本。
Run snapshot-restore.sh./snapshot-restore.sh -
請輸入包含待還原虛擬機器的專案編號。
Project selectionSelect a project by number:1. admin2. _diagnostics3. bigstackEnter the number: 3 -
請輸入您要還原的虛擬機編號。 您可以透過虛擬機名稱或 UUID 來識別虛擬機。
Server selectionSelect a server by number:1. vm-snap-restore (52d7f3fa-4d6f-4868-b271-e018c78a061f)Enter the number: 1 -
請輸入要還原的磁碟編號。
存放作業系統的根硬碟通常是
/dev/sda,而其餘的資料硬碟則位於較低的索引位置。 要識別每個磁碟,請前往 運算 > 虛擬機,選取要還原的虛擬機,然後按一下 磁碟 索引標籤以檢視磁碟的相關資訊。Volume selectionSelect a volume by number:1. d11dfee8-3067-4031-8e4d-da3bc867c913 (Device: /dev/sda)2. 684483a5-4bd6-448f-810a-81517d82754f (Device: /dev/sdb)Enter the number: 1 -
請輸入要還原的快照編號。
Snapshot selectionSelect a snapshot by number:1. snapshot for add-data-v3 - Created: 2025-02-06 05:42:572. snapshot for add-data-v1 - Created: 2025-02-06 05:42:113. snapshot for snap-data - Created: 2025-02-06 02:01:19Enter the number: 1 -
確認還原。
此腳本會顯示已選取的磁碟和快照 ID,並提示使用者確認:
資料遺失從快照還原磁碟會覆寫所有的磁碟資料。 您將失去快照建立後所做的任何變更。
Restore confirmation promptWARNING: This operation will revert the volume(d11dfee8-3067-4031-8e4d-da3bc867c913) to the selected snapshot(50927e68-9330-46d6-bf8a-1dac0db8e652).The associated server will be SHUTDOWN, and all current disk data will be LOST.Type 'YES' to confirm:- 若要繼續,請輸入
YES。 - 若要取消,請輸入其他內容。
- 若要繼續,請輸入
在還原完成後,請確認伺服器和磁碟區是否運作正常
腳本執行完畢後,請確認伺服器與已還原的磁碟區是否運作正常。
- 請確認伺服器狀態為 運作中。
- 請確認預期的磁碟區是否仍已連接,且磁碟區狀態為 使用中。
- 請登入虛擬機,並檢查已還原的資料或檔案系統的狀態。
完整還原腳本
#!/bin/bash
source /etc/admin-openrc.sh
# Get the list of project names
projects=($(openstack project list -c Name -f value))
# Display the numbered list
echo "Select a project by number:"
for i in "${!projects[@]}"; do
echo "$((i+1)). ${projects[i]}"
done
# Read user input
read -p "Enter the number: " choice
# Validate input
if [[ $choice -ge 1 && $choice -le ${#projects[@]} ]]; then
project_name=(${projects[$((choice-1))]})
echo "You selected: ${projects[$((choice-1))]}"
else
echo "Invalid choice. Exiting."
exit 1
fi
## - End of Project -
# Get the list of servers (Name and ID)
mapfile -t servers < <(openstack server list --project="$project_name" --long -c Name -c ID -f value)
# Check if there are any servers
if [ ${#servers[@]} -eq 0 ]; then
echo "No servers found for project $project_name."
exit 1
fi
# Display the numbered list
echo "Select a server by number:"
for i in "${!servers[@]}"; do
selected_server_id=$(echo "${servers[i]}" | awk '{print $1}') # Extract server ID
server_name=$(echo "${servers[i]}" | awk '{$1=""; print $0}' | sed 's/^ *//') # Extract server name
echo "$((i+1)). $server_name ($selected_server_id)"
done
# Read user input
read -p "Enter the number: " choice
# Validate input
if [[ $choice -ge 1 && $choice -le ${#servers[@]} ]]; then
selected_server="${servers[$((choice-1))]}"
selected_server_id=$(echo "$selected_server" | awk '{print $1}') # Extract server ID
server_name=$(echo "$selected_server" | awk '{$1=""; print $0}' | sed 's/^ *//') # Extract server name
echo "You selected: $server_name ($selected_server_id)"
else
echo "Invalid choice. Exiting."
exit 1
fi
## - End of Server -
volumes_json=$(openstack server show "$selected_server_id" -c attached_volumes -f json)
# Extract volume IDs
mapfile -t volume_ids < <(echo "$volumes_json" | jq -r '.attached_volumes[].id')
# Check if there are any attached volumes
if [ ${#volume_ids[@]} -eq 0 ]; then
echo "No attached volumes found for server $selected_server_id."
exit 1
fi
# Get details of each attached volume
volume_info=()
for volume_id in "${volume_ids[@]}"; do
volume_json=$(openstack volume show "$volume_id" -c attachments -f json)
device=$(echo "$volume_json" | jq -r '.attachments[0].device')
# Store volume info (ID and device)
volume_info+=("$volume_id $device")
done
# Display numbered list
echo "Select a volume by number:"
for i in "${!volume_info[@]}"; do
volume_id=$(echo "${volume_info[i]}" | awk '{print $1}')
device=$(echo "${volume_info[i]}" | awk '{print $2}')
echo "$((i+1)). $volume_id (Device: $device)"
done
# Get user input
read -p "Enter the number: " choice
# Validate input
if [[ $choice -ge 1 && $choice -le ${#volume_info[@]} ]]; then
selected_volume_id=$(echo "${volume_info[$((choice-1))]}" | awk '{print $1}')
echo "You selected volume: $selected_volume_id"
else
echo "Invalid choice. Exiting."
exit 1
fi
## - End of Volume -
# Get all snapshots for the project "bigstack"
snapshots_json=$(openstack volume snapshot list --project="$project_name" --long -f json)
# Extract snapshots related to the selected volume
mapfile -t snapshot_info < <(echo "$snapshots_json" | jq -c --arg vol "$selected_volume_id" \
'.[] | select(.Volume == $vol) | {name: .Name, id: .ID, created_at: .["Created At"]}')
# Check if there are any snapshots
if [ ${#snapshot_info[@]} -eq 0 ]; then
echo "No snapshots found for volume: $selected_volume_id"
exit 1
fi
# Convert "Created At" to human-readable format and display options
echo "Select a snapshot by number:"
for i in "${!snapshot_info[@]}"; do
name=$(echo "${snapshot_info[i]}" | jq -r '.name') # Extract snapshot name
id=$(echo "${snapshot_info[i]}" | jq -r '.id') # Extract snapshot ID
created_at=$(echo "${snapshot_info[i]}" | jq -r '.created_at') # Extract Created At
# Convert to human-readable format
human_date=$(date -d "$created_at" '+%Y-%m-%d %H:%M:%S' 2>/dev/null)
# If date conversion fails, set a fallback
if [[ -z "$human_date" ]]; then
human_date="Invalid Date"
fi
echo "$((i+1)). $name - Created: $human_date"
done
# Get user selection
read -p "Enter the number: " choice
# Validate input
if [[ $choice -ge 1 && $choice -le ${#snapshot_info[@]} ]]; then
selected_snapshot_id=$(echo "${snapshot_info[$((choice-1))]}" | jq -r '.id') # Extract snapshot ID
echo "You selected snapshot: $selected_snapshot_id"
else
echo "Invalid choice. Exiting."
exit 1
fi
## - End of Snapshot -
# Ask for final confirmation
echo ""
echo "WARNING: This operation will revert the volume ($selected_volume_id) to the selected snapshot ($selected_snapshot_id)."
echo "The associated server will be SHUTDOWN, and all current disk data will be LOST."
echo ""
read -p "Type 'YES' to confirm: " confirmation
# Check if the user entered exactly "YES"
if [[ "$confirmation" != "YES" ]]; then
echo "Operation canceled. No changes were made."
exit 1
fi
# Proceed with the revert operation, ensure the server is SHUTOFF before proceeding
echo "Stopping the server ($selected_server_id)..."
openstack server stop "$selected_server_id"
# Wait until the server is fully stopped
echo "Waiting for server ($selected_server_id) to shut down..."
while true; do
vm_state=$(openstack server show "$selected_server_id" -c vm_state -f value)
if [[ "$vm_state" == "stopped" ]]; then
echo "✅ Server is now stopped."
break
fi
echo "⏳ Server is still stopping... checking again in 5 seconds."
sleep 5
done
echo "Reverting volume $selected_volume_id to snapshot $selected_snapshot_id..."
rbd snap rollback cinder-volumes/volume-"$selected_volume_id"@snapshot-"$selected_snapshot_id"
echo "Revert operation completed successfully."
echo "Starting the server ($selected_server_id)..."
openstack server start "$selected_server_id"
echo "Server started successfully."
完整還原作業的輸出範例
Select a project by number:
1. admin
2. _diagnostics
3. bigstack
Enter the number: 3
You selected: bigstack
Select a server by number:
1. vm-snap-restore (52d7f3fa-4d6f-4868-b271-e018c78a061f)
Enter the number: 1
You selected: vm-snap-restore (52d7f3fa-4d6f-4868-b271-e018c78a061f)
Select a volume by number:
1. d11dfee8-3067-4031-8e4d-da3bc867c913 (Device: /dev/sda)
2. 684483a5-4bd6-448f-810a-81517d82754f (Device: /dev/sdb)
Enter the number: 1
You selected volume: d11dfee8-3067-4031-8e4d-da3bc867c913
Select a snapshot by number:
1. snapshot for add-data-v3 - Created: 2025-02-06 05:42:57
2. snapshot for add-data-v1 - Created: 2025-02-06 05:42:11
3. snapshot for snap-data - Created: 2025-02-06 02:01:19
Enter the number: 1
You selected snapshot: 50927e68-9330-46d6-bf8a-1dac0db8e652
WARNING: This operation will revert the volume
(d11dfee8-3067-4031-8e4d-da3bc867c913) to the selected snapshot
(50927e68-9330-46d6-bf8a-1dac0db8e652).
The associated server will be SHUTDOWN, and all current disk data will be LOST.
Type 'YES' to confirm: YES
Stopping the server (52d7f3fa-4d6f-4868-b271-e018c78a061f)...
Waiting for server (52d7f3fa-4d6f-4868-b271-e018c78a061f) to shut down...
Server is still stopping. Checking again in 5 seconds.
Server is now stopped.
Reverting volume d11dfee8-3067-4031-8e4d-da3bc867c913 to snapshot 50927e68-9330-46d6-bf8a-1dac0db8e652...
Rolling back to snapshot: 100% complete...done.
Revert operation completed successfully.
Starting the server (52d7f3fa-4d6f-4868-b271-e018c78a061f)...
Server started successfully.
常見還原失敗的疑難排解
該腳本無法列出專案
請確認 /etc/admin-openrc.sh 檔案是否存在,且其中包含有效的 OpenStack 憑證。
要測試驗證功能:
openstack project list
未列出任何伺服器
請確認所選專案中包含伺服器,且您的憑證具備讀取這些伺服器的權限:
openstack server list --project PROJECT_NAME --long
未找到任何已掛載的磁碟區
請確認所選虛擬機已掛載磁碟:
openstack server show SERVER_ID -c attached_volumes
未找到任何快照
請確認所選的磁碟在所選的專案中是否存在快照:
openstack volume snapshot list --project PROJECT_NAME --long
伺服器不會停止
檢查伺服器狀態與虛擬化平台狀態:
openstack server show SERVER_ID -c status -c vm_state -c OS-EXT-SRV-ATTR:host
在伺服器停止運作之前,請勿執行 RBD 回滾。
還原失敗
請確認 Ceph 儲存池、磁碟標 ID 及快照 ID 是否正確:
rbd snap ls cinder-volumes/volume-VOLUME_ID
接著請確認回滾目標是否存在:
rbd info cinder-volumes/volume-VOLUME_ID@snapshot-SNAPSHOT_ID