Add comprehensive Proxmox host analysis before optimization

New features:
- analyze_proxmox_status() function shows detailed system state
  - RAM usage and allocation
  - VM/Container count and status
  - Total VM memory allocation and overcommit ratio
  - Storage status (pvesm)
  - Current kernel parameters vs recommended
  - CPU governor status
  - ZFS ARC size (if applicable)
  - Existing optimizations detection

- Added optimize_cpu_governor() function
  - Sets CPU to 'performance' mode for VMs
  - Makes persistent via cpufrequtils

- Added optimize_zfs_arc() function
  - Limits ZFS ARC to 25% of RAM
  - Frees more RAM for VMs
  - Updates initramfs for persistence

Analysis now runs automatically when Proxmox is detected,
showing comprehensive system status before mode selection.
This commit is contained in:
mindesbunister
2025-10-06 11:11:30 +02:00
parent e419e29acd
commit ac74501319

View File

@@ -42,6 +42,154 @@ check_root() {
fi
}
analyze_proxmox_status() {
echo -e "${CYAN}🔍 Proxmox Host Analysis${NC}"
echo "========================"
echo ""
# System info
local ram_gb=$(free -g | awk '/^Mem:|^Speicher:/{print $2}')
local ram_used=$(free -g | awk '/^Mem:|^Speicher:/{print $3}')
local ram_available=$(free -g | awk '/^Mem:|^Speicher:/{print $7}')
local cpu_cores=$(nproc)
local pve_version=$(pveversion | head -1 || echo "Unknown")
echo "📊 System Information:"
echo " 💾 RAM: ${ram_gb}GB (Used: ${ram_used}GB, Available: ${ram_available}GB)"
echo " 🖥️ CPU: ${cpu_cores} cores"
echo " 📦 Proxmox: $pve_version"
echo ""
# VM/Container workload
local vm_count=$(qm list 2>/dev/null | tail -n +2 | wc -l || echo "0")
local ct_count=$(pct list 2>/dev/null | tail -n +2 | wc -l || echo "0")
local vm_running=$(qm list 2>/dev/null | grep -c "running" || echo "0")
local ct_running=$(pct list 2>/dev/null | grep -c "running" || echo "0")
echo "🖥️ Workload:"
echo " 🖼️ VMs: $vm_count total ($vm_running running)"
echo " 📦 Containers: $ct_count total ($ct_running running)"
echo ""
# Check VM memory allocation
local total_vm_mem=0
if command -v qm &>/dev/null; then
while read -r vmid; do
local mem=$(qm config "$vmid" 2>/dev/null | grep "^memory:" | awk '{print $2}' || echo "0")
total_vm_mem=$((total_vm_mem + mem))
done < <(qm list 2>/dev/null | tail -n +2 | awk '{print $1}')
local total_vm_mem_gb=$((total_vm_mem / 1024))
echo " 📊 Total VM memory allocated: ${total_vm_mem_gb}GB"
local overcommit_ratio=$(echo "scale=1; $total_vm_mem_gb * 100 / $ram_gb" | bc 2>/dev/null || echo "N/A")
echo " 📈 Memory overcommit: ${overcommit_ratio}%"
echo ""
fi
# Storage
echo "💾 Storage:"
if command -v pvesm &>/dev/null; then
pvesm status 2>/dev/null | tail -n +2 | while read -r name type status total used avail percent; do
echo "$name ($type): ${used}/${total} used"
done
fi
echo ""
# Check current kernel parameters
echo "⚙️ Current Kernel Parameters:"
local swappiness=$(sysctl -n vm.swappiness 2>/dev/null || echo "60")
local dirty_ratio=$(sysctl -n vm.dirty_ratio 2>/dev/null || echo "20")
local dirty_bg=$(sysctl -n vm.dirty_background_ratio 2>/dev/null || echo "10")
local cache_pressure=$(sysctl -n vm.vfs_cache_pressure 2>/dev/null || echo "100")
local qdisc=$(sysctl -n net.core.default_qdisc 2>/dev/null || echo "pfifo_fast")
local tcp_congestion=$(sysctl -n net.ipv4.tcp_congestion_control 2>/dev/null || echo "cubic")
echo " 📊 Memory:"
echo " vm.swappiness: $swappiness (Proxmox recommended: 10)"
echo " vm.dirty_ratio: $dirty_ratio (Proxmox recommended: 10)"
echo " vm.dirty_background_ratio: $dirty_bg (Proxmox recommended: 5)"
echo " vm.vfs_cache_pressure: $cache_pressure (Proxmox recommended: 50)"
echo ""
echo " 📡 Network:"
echo " net.core.default_qdisc: $qdisc (Proxmox recommended: fq)"
echo " net.ipv4.tcp_congestion_control: $tcp_congestion (Proxmox recommended: bbr)"
echo ""
# Check CPU governor
local governor=$(cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor 2>/dev/null || echo "unknown")
echo "🖥️ CPU Governor: $governor (Recommended: performance)"
echo ""
# Check ZFS if present
if command -v zpool &>/dev/null && zpool list &>/dev/null 2>&1; then
echo "🗄️ ZFS Configuration:"
local arc_max=$(cat /sys/module/zfs/parameters/zfs_arc_max 2>/dev/null || echo "0")
local arc_max_gb=$((arc_max / 1024 / 1024 / 1024))
local recommended_arc=$((ram_gb / 4))
echo " <20> Current ARC max: ${arc_max_gb}GB"
echo " 💡 Recommended: ${recommended_arc}GB (25% of RAM, leaves more for VMs)"
echo ""
fi
# Check for existing optimizations
echo "🔍 Existing Optimizations:"
local has_optimizations=false
if [[ -f /etc/sysctl.d/99-system-optimization.conf ]] || [[ -f /etc/sysctl.d/99-proxmox-tuning.conf ]]; then
echo " ✅ Custom sysctl configuration found"
has_optimizations=true
else
echo " ❌ No custom sysctl configuration"
fi
if mount | grep -q "tmpfs.*tmpfs-cache"; then
local tmpfs_count=$(mount | grep -c "tmpfs.*tmpfs-cache")
echo " ⚠️ tmpfs mounts found: $tmpfs_count (may use RAM needed by VMs)"
has_optimizations=true
else
echo " ✅ No tmpfs cache mounts (good for Proxmox)"
fi
if [[ -e /dev/zram0 ]] && swapon --show | grep -q zram0; then
local zram_size=$(swapon --show | grep zram0 | awk '{print $3}')
echo " ⚠️ zram active: $zram_size (reduces RAM for VMs)"
has_optimizations=true
else
echo " ✅ No zram (good for Proxmox)"
fi
echo ""
# Assessment
echo "📋 Assessment:"
local needs_optimization=false
if [[ "$swappiness" != "10" ]] || [[ "$dirty_ratio" != "10" ]] || [[ "$qdisc" != "fq" ]] || [[ "$tcp_congestion" != "bbr" ]]; then
echo " ⚠️ Kernel parameters not optimized for hypervisor workload"
needs_optimization=true
else
echo " ✅ Kernel parameters look good"
fi
if [[ "$governor" != "performance" ]] && [[ "$governor" != "unknown" ]]; then
echo " ⚠️ CPU governor not set to 'performance'"
needs_optimization=true
fi
if command -v zpool &>/dev/null && zpool list &>/dev/null 2>&1; then
if [[ $arc_max_gb -gt $recommended_arc ]]; then
echo " ⚠️ ZFS ARC could be limited to give VMs more RAM"
needs_optimization=true
fi
fi
if [[ "$needs_optimization" == "false" ]]; then
echo " ✅ System is already well-optimized for Proxmox!"
fi
echo ""
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo ""
}
check_proxmox() {
# Detect if running on Proxmox host
if [[ -f /etc/pve/.version ]] || [[ -d /etc/pve ]] || pveversion &>/dev/null; then
@@ -49,17 +197,14 @@ check_proxmox() {
warn "⚠️ Proxmox VE host detected!"
echo ""
# Get VM/CT count
local vm_count=$(qm list 2>/dev/null | tail -n +2 | wc -l || echo "0")
local ct_count=$(pct list 2>/dev/null | tail -n +2 | wc -l || echo "0")
# Show detailed analysis
analyze_proxmox_status
echo "🖥️ System: Proxmox VE (${vm_count} VMs, ${ct_count} containers)"
echo ""
echo "This tool has TWO modes:"
echo ""
echo " 1⃣ Proxmox Host Mode (Hypervisor Optimization)"
echo " • Optimized kernel params for VM workloads"
echo " • Minimal RAM allocation (5-10% max)"
echo " • Minimal RAM allocation (2GB APT cache only)"
echo " • CPU performance governor"
echo " • ZFS ARC limiting (if applicable)"
echo " • No desktop app configuration"
@@ -1320,6 +1465,90 @@ EOF
success "Kernel parameters optimized ($profile profile)"
}
optimize_cpu_governor() {
if [[ "${PROXMOX_MODE:-false}" != "true" ]]; then
return 0
fi
log "Optimizing CPU governor for Proxmox..."
# Check current governor
local current_governor=$(cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor 2>/dev/null || echo "unknown")
if [[ "$current_governor" == "performance" ]]; then
success "CPU governor already set to 'performance'"
return 0
fi
if [[ "$current_governor" == "unknown" ]]; then
warn "CPU frequency scaling not available on this system"
return 0
fi
# Install cpufrequtils if needed
if ! command -v cpufreq-set &>/dev/null; then
log "Installing cpufrequtils..."
apt-get update -qq
apt-get install -y cpufrequtils >/dev/null 2>&1
fi
# Set governor to performance
for cpu in /sys/devices/system/cpu/cpu[0-9]*; do
if [[ -f "$cpu/cpufreq/scaling_governor" ]]; then
echo "performance" > "$cpu/cpufreq/scaling_governor" 2>/dev/null || true
fi
done
# Make persistent
cat > /etc/default/cpufrequtils << 'EOF'
# CPU governor for Proxmox host
GOVERNOR="performance"
EOF
success "CPU governor set to 'performance' (full speed for VMs)"
}
optimize_zfs_arc() {
if [[ "${PROXMOX_MODE:-false}" != "true" ]]; then
return 0
fi
# Check if ZFS is present
if ! command -v zpool &>/dev/null || ! zpool list &>/dev/null 2>&1; then
return 0
fi
log "Optimizing ZFS ARC limit..."
local ram_gb=$(free -g | awk '/^Mem:|^Speicher:/{print $2}')
local current_arc=$(cat /sys/module/zfs/parameters/zfs_arc_max 2>/dev/null || echo "0")
local current_arc_gb=$((current_arc / 1024 / 1024 / 1024))
local recommended_arc=$((ram_gb / 4)) # 25% of RAM
if [[ $current_arc_gb -le $recommended_arc ]] && [[ $current_arc_gb -gt 0 ]]; then
success "ZFS ARC already limited to ${current_arc_gb}GB (good for VMs)"
return 0
fi
local arc_bytes=$((recommended_arc * 1024 * 1024 * 1024))
# Set immediately
echo "$arc_bytes" > /sys/module/zfs/parameters/zfs_arc_max 2>/dev/null || true
# Make persistent
mkdir -p /etc/modprobe.d
if ! grep -q "zfs_arc_max" /etc/modprobe.d/zfs.conf 2>/dev/null; then
echo "options zfs zfs_arc_max=$arc_bytes" >> /etc/modprobe.d/zfs.conf
else
sed -i "s/zfs_arc_max=[0-9]*/zfs_arc_max=$arc_bytes/" /etc/modprobe.d/zfs.conf
fi
# Update initramfs
update-initramfs -u -k all >/dev/null 2>&1 || true
success "ZFS ARC limited to ${recommended_arc}GB (frees RAM for VMs)"
}
create_service() {
if [[ $SETUP_SERVICE != true ]]; then
return 0
@@ -1494,6 +1723,11 @@ main() {
setup_zram
setup_tmpfs
tune_kernel
# Proxmox-specific optimizations
optimize_cpu_governor
optimize_zfs_arc
create_service
# Show results