diff --git a/cluster/check_storage.sh b/cluster/check_storage.sh index d6876e6..35e2327 100755 --- a/cluster/check_storage.sh +++ b/cluster/check_storage.sh @@ -1,14 +1,107 @@ #!/usr/bin/env bash -# 用途:檢查儲存狀態(PVC / Longhorn) +# 用途:檢查 K3s 儲存狀態 set -euo pipefail -echo "=== PVC ===" -kubectl get pvc +# 顏色定義 +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +NC='\033[0m' # No Color -if kubectl get ns longhorn-system >/dev/null 2>&1; then - echo - echo "=== Longhorn Volumes ===" - kubectl -n longhorn-system get volumes +echo "==========================================" +echo " K3s 儲存狀態檢查" +echo "==========================================" +echo "" + +# 1. PVC 狀態 +echo "📦 PVC (資料卷)" +echo "------------------------------------------" +kubectl get pvc -o custom-columns=NAME:.metadata.name,STATUS:.status.phase,SIZE:.spec.resources.requests.storage,AGE:.metadata.age + +# 統計 PVC +PVC_TOTAL=$(kubectl get pvc --no-headers 2>/dev/null | wc -l) +PVC_BOUND=$(kubectl get pvc --no-headers 2>/dev/null | grep -c "Bound" || true) +PVC_ISSUE=$((PVC_TOTAL - PVC_BOUND)) + +echo "" +if [ $PVC_ISSUE -eq 0 ]; then + echo -e "${GREEN}✓ 所有 PVC 正常 ($PVC_BOUND/$PVC_TOTAL)${NC}" +else + echo -e "${RED}✗ 有 $PVC_ISSUE 個 PVC 異常${NC}" fi +echo "" + +# 2. Longhorn Volume 狀態 +if kubectl get ns longhorn-system >/dev/null 2>&1; then + echo "💾 Longhorn 儲存" + echo "------------------------------------------" + + # 取得 volume 狀態 + kubectl -n longhorn-system get volumes -o custom-columns=NAME:.metadata.name,STATE:.status.state,健康:.status.robustness,NODE:.status.currentNodeID 2>/dev/null || { + kubectl -n longhorn-system get volumes + } + + echo "" + + # 統計健康狀態 + VOL_TOTAL=$(kubectl -n longhorn-system get volumes --no-headers 2>/dev/null | wc -l) + VOL_HEALTHY=$(kubectl -n longhorn-system get volumes --no-headers 2>/dev/null | grep -c "healthy" || true) + VOL_DEGRADED=$(kubectl -n longhorn-system get volumes --no-headers 2>/dev/null | grep -c "degraded" || true) + VOL_FAULT=$(kubectl -n longhorn-system get volumes --no-headers 2>/dev/null | grep -c "faulted" || true) + + if [ $VOL_DEGRADED -gt 0 ]; then + echo -e "${YELLOW}⚠ $VOL_DEGRADED 個 volume 處於 degraded 狀態${NC}" + fi + + if [ $VOL_FAULT -gt 0 ]; then + echo -e "${RED}✗ $VOL_FAULT 個 volume 處於 faulted 狀態${NC}" + fi + + if [ $VOL_HEALTHY -eq $VOL_TOTAL ]; then + echo -e "${GREEN}✓ 所有 volume 健康 ($VOL_HEALTHY/$VOL_TOTAL)${NC}" + else + echo -e "${GREEN}✓ 健康: $VOL_HEALTHY | ${YELLOW}警告: $VOL_DEGRADED | ${RED}故障: $VOL_FAULT${NC} (總計: $VOL_TOTAL)${NC}" + fi + + echo "" + + # 3. 節點儲存空間 + echo "🖥️ 節點儲存空間" + echo "------------------------------------------" + + for node in vm120 vm121 vm122; do + NODE_INFO=$(kubectl -n longhorn-system get nodes.longhorn.io "$node" -o jsonpath="{.status.diskStatus}" 2>/dev/null) + if [ -n "$NODE_INFO" ]; then + # 取得第一個 disk 的資訊 + DISK_NAME=$(echo "$NODE_INFO" | grep -oP '^\s+"\K[^"]+' | head -1) + if [ -n "$DISK_NAME" ]; then + STORAGE_AVAIL=$(echo "$NODE_INFO" | grep -A1 "$DISK_NAME" | grep storageAvailable | grep -oP '\d+' | head -1) + STORAGE_MAX=$(echo "$NODE_INFO" | grep -A1 "$DISK_NAME" | grep storageMaximum | grep -oP '\d+' | head -1) + + if [ -n "$STORAGE_AVAIL" ] && [ -n "$STORAGE_MAX" ]; then + # 轉換為 GB + AVAIL_GB=$((STORAGE_AVAIL / 1024 / 1024 / 1024)) + MAX_GB=$((STORAGE_MAX / 1024 / 1024 / 1024)) + USED_GB=$((MAX_GB - AVAIL_GB)) + PERCENT=$((USED_GB * 100 / MAX_GB)) + + # 顏色 + if [ $PERCENT -lt 70 ]; then + COLOR="$GREEN" + elif [ $PERCENT -lt 90 ]; then + COLOR="$YELLOW" + else + COLOR="$RED" + fi + + echo -e "$node: ${COLOR}${USED_GB}G / ${MAX_GB}G (${PERCENT}%)${NC}" + fi + fi + fi + done +fi + +echo "" +echo "=========================================="