Files
linux-scripts/install-cadvisor.sh
T
chiefgeek a1a17e81a1 Sync all scripts from website downloads — 352 scripts total
Includes updated JS challenge scripts with Claude-User whitelist,
same-site referer bypass, Blackbox-Exporter allowed bot, and all
new exporters, cheat sheets, and automation scripts.
2026-05-25 03:31:08 +02:00

483 lines
14 KiB
Bash

#!/bin/bash
#############################################################
#### cAdvisor Installer ####
#### Download, install, and configure Google cAdvisor ####
#### for Docker container metrics with Prometheus ####
#### ####
#### Supports: Docker (container) or binary (systemd) ####
#### ####
#### Author: Phil Connor ####
#### Contact: contact@mylinux.work ####
#### Version: 1.0.0.20260308 ####
#############################################################
set -euo pipefail
SCRIPT_NAME=$(basename "$0")
readonly SCRIPT_NAME
# Defaults
readonly DEFAULT_CADVISOR_VERSION="0.49.1"
readonly DEFAULT_LISTEN_PORT="8080"
readonly DEFAULT_PROMETHEUS_CONFIG="/etc/prometheus/prometheus.yml"
readonly DEFAULT_BIND_ADDRESS="0.0.0.0"
# Configuration (overridable by environment or flags)
CADVISOR_VERSION="${CADVISOR_VERSION:-$DEFAULT_CADVISOR_VERSION}"
LISTEN_PORT="${LISTEN_PORT:-$DEFAULT_LISTEN_PORT}"
BIND_ADDRESS="${BIND_ADDRESS:-$DEFAULT_BIND_ADDRESS}"
PROMETHEUS_CONFIG="${PROMETHEUS_CONFIG:-$DEFAULT_PROMETHEUS_CONFIG}"
INSTALL_MODE="docker"
RESTART_POLICY="unless-stopped"
CONTAINER_NAME="cadvisor"
ADD_TO_PROMETHEUS=false
DRY_RUN=false
UNINSTALL=false
# Logging
log_info() {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] INFO: $1"
}
log_error() {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] ERROR: $1" >&2
}
log_warn() {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] WARN: $1"
}
show_help() {
cat << EOF
Usage: $SCRIPT_NAME [OPTIONS]
Download, install, and configure Google cAdvisor for Docker container monitoring.
INSTALL MODES:
--docker Run cAdvisor as a Docker container (default)
--binary Download and install as a systemd service
OPTIONS:
--version <ver> cAdvisor version to install (default: $DEFAULT_CADVISOR_VERSION)
--port <port> Metrics listen port (default: $DEFAULT_LISTEN_PORT)
--bind <address> Bind address (default: $DEFAULT_BIND_ADDRESS)
--name <name> Docker container name (default: cadvisor)
--restart <policy> Docker restart policy (default: unless-stopped)
--add-to-prometheus Add scrape target to Prometheus config
--prometheus-config Path to prometheus.yml (default: $DEFAULT_PROMETHEUS_CONFIG)
--uninstall Remove cAdvisor installation
--dry-run Show what would be done without executing
--help, -h Show this help message
ENVIRONMENT VARIABLES:
CADVISOR_VERSION cAdvisor version (default: $DEFAULT_CADVISOR_VERSION)
LISTEN_PORT Metrics listen port (default: $DEFAULT_LISTEN_PORT)
BIND_ADDRESS Bind address (default: $DEFAULT_BIND_ADDRESS)
PROMETHEUS_CONFIG Path to prometheus.yml (default: $DEFAULT_PROMETHEUS_CONFIG)
EXAMPLES:
$SCRIPT_NAME --docker
$SCRIPT_NAME --docker --port 9080 --add-to-prometheus
$SCRIPT_NAME --binary --version 0.49.1 --add-to-prometheus
$SCRIPT_NAME --uninstall
EOF
exit 0
}
#########################
### Parse Arguments ###
#########################
parse_arguments() {
while [[ $# -gt 0 ]]; do
case $1 in
--docker) INSTALL_MODE="docker"; shift ;;
--binary) INSTALL_MODE="binary"; shift ;;
--version) CADVISOR_VERSION="$2"; shift 2 ;;
--port) LISTEN_PORT="$2"; shift 2 ;;
--bind) BIND_ADDRESS="$2"; shift 2 ;;
--name) CONTAINER_NAME="$2"; shift 2 ;;
--restart) RESTART_POLICY="$2"; shift 2 ;;
--add-to-prometheus) ADD_TO_PROMETHEUS=true; shift ;;
--prometheus-config) PROMETHEUS_CONFIG="$2"; shift 2 ;;
--uninstall) UNINSTALL=true; shift ;;
--dry-run) DRY_RUN=true; shift ;;
--help|-h) show_help ;;
*) log_error "Unknown option: $1"; show_help ;;
esac
done
}
#########################
### Permission Check ###
#########################
check_permissions() {
if [[ $EUID -ne 0 ]]; then
log_error "This script must be run as root"
exit 1
fi
}
#########################
### Pre-flight Checks ###
#########################
check_docker() {
if ! command -v docker &>/dev/null; then
log_error "Docker is not installed. Install Docker first or use --binary mode."
exit 1
fi
if ! docker info &>/dev/null; then
log_error "Docker daemon is not running"
exit 1
fi
}
check_port_available() {
if ss -tlnp 2>/dev/null | grep -q ":${LISTEN_PORT} " || \
netstat -tlnp 2>/dev/null | grep -q ":${LISTEN_PORT} "; then
log_warn "Port $LISTEN_PORT is already in use"
# Check if it's cAdvisor already running
if docker ps --format '{{.Names}}' 2>/dev/null | grep -q "^${CONTAINER_NAME}$"; then
log_warn "cAdvisor container '$CONTAINER_NAME' is already running"
return 1
fi
if systemctl is-active --quiet cadvisor 2>/dev/null; then
log_warn "cAdvisor systemd service is already running"
return 1
fi
log_error "Port $LISTEN_PORT is in use by another process"
exit 1
fi
return 0
}
detect_arch() {
local arch
arch=$(uname -m)
case "$arch" in
x86_64) echo "amd64" ;;
aarch64) echo "arm64" ;;
armv7l) echo "armv7" ;;
*) log_error "Unsupported architecture: $arch"; exit 1 ;;
esac
}
#########################
### Docker Install ###
#########################
install_docker_mode() {
check_docker
if ! check_port_available; then
log_info "cAdvisor is already running — nothing to do"
return
fi
log_info "Installing cAdvisor v${CADVISOR_VERSION} as Docker container"
local image="gcr.io/cadvisor/cadvisor:v${CADVISOR_VERSION}"
local docker_cmd=(
docker run -d
--name "$CONTAINER_NAME"
--restart "$RESTART_POLICY"
-p "${BIND_ADDRESS}:${LISTEN_PORT}:8080"
-v /:/rootfs:ro
-v /var/run:/var/run:ro
-v /sys:/sys:ro
-v /var/lib/docker/:/var/lib/docker:ro
-v /dev/disk/:/dev/disk:ro
--privileged
--device /dev/kmsg
"$image"
)
if [[ "$DRY_RUN" == "true" ]]; then
log_info "[DRY RUN] Would execute:"
echo " ${docker_cmd[*]}"
return
fi
# Pull image first
log_info "Pulling image: $image"
docker pull "$image"
# Remove existing stopped container if present
if docker ps -a --format '{{.Names}}' | grep -q "^${CONTAINER_NAME}$"; then
log_info "Removing existing stopped container: $CONTAINER_NAME"
docker rm -f "$CONTAINER_NAME" 2>/dev/null || true
fi
# Run container
"${docker_cmd[@]}"
log_info "Container '$CONTAINER_NAME' started"
# Wait for metrics endpoint
wait_for_metrics
}
#########################
### Binary Install ###
#########################
install_binary_mode() {
local arch
arch=$(detect_arch)
local download_url="https://github.com/google/cadvisor/releases/download/v${CADVISOR_VERSION}/cadvisor-v${CADVISOR_VERSION}-linux-${arch}"
local binary_path="/usr/local/bin/cadvisor"
log_info "Installing cAdvisor v${CADVISOR_VERSION} as systemd service (${arch})"
if [[ "$DRY_RUN" == "true" ]]; then
log_info "[DRY RUN] Would download: $download_url"
log_info "[DRY RUN] Would install to: $binary_path"
log_info "[DRY RUN] Would create systemd unit: /etc/systemd/system/cadvisor.service"
return
fi
# Download binary
log_info "Downloading cAdvisor binary..."
local temp_file
temp_file=$(mktemp)
if ! curl -fsSL -o "$temp_file" "$download_url"; then
rm -f "$temp_file"
log_error "Failed to download cAdvisor from $download_url"
exit 1
fi
# Install binary
chmod +x "$temp_file"
mv "$temp_file" "$binary_path"
log_info "Installed binary to $binary_path"
# Create systemd unit
create_systemd_unit
# Enable and start
systemctl daemon-reload
systemctl enable cadvisor
systemctl start cadvisor
log_info "cAdvisor systemd service started"
# Wait for metrics endpoint
wait_for_metrics
}
create_systemd_unit() {
cat > /etc/systemd/system/cadvisor.service << EOF
[Unit]
Description=cAdvisor - Container Advisor
Documentation=https://github.com/google/cadvisor
After=network.target docker.service
Wants=docker.service
[Service]
Type=simple
ExecStart=/usr/local/bin/cadvisor \\
--port=${LISTEN_PORT} \\
--listen_ip=${BIND_ADDRESS} \\
--docker_only=true \\
--housekeeping_interval=30s \\
--storage_duration=2m0s
Restart=on-failure
RestartSec=5
LimitNOFILE=65536
[Install]
WantedBy=multi-user.target
EOF
log_info "Created systemd unit: /etc/systemd/system/cadvisor.service"
}
#########################
### Post-install ###
#########################
wait_for_metrics() {
log_info "Waiting for metrics endpoint..."
local attempts=0
local max_attempts=15
while [[ $attempts -lt $max_attempts ]]; do
if curl -sf "http://localhost:${LISTEN_PORT}/metrics" >/dev/null 2>&1; then
log_info "cAdvisor is responding on port $LISTEN_PORT"
return 0
fi
attempts=$((attempts + 1))
sleep 2
done
log_warn "cAdvisor did not respond within ${max_attempts} attempts — check logs"
return 1
}
add_prometheus_scrape_config() {
if [[ "$ADD_TO_PROMETHEUS" != "true" ]]; then
return
fi
if [[ ! -f "$PROMETHEUS_CONFIG" ]]; then
log_warn "Prometheus config not found at $PROMETHEUS_CONFIG — skipping"
return
fi
# Check if cadvisor job already exists
if grep -q "job_name.*cadvisor" "$PROMETHEUS_CONFIG" 2>/dev/null; then
log_info "cAdvisor scrape target already exists in $PROMETHEUS_CONFIG"
return
fi
if [[ "$DRY_RUN" == "true" ]]; then
log_info "[DRY RUN] Would add cAdvisor scrape config to $PROMETHEUS_CONFIG"
return
fi
# Backup config
cp "$PROMETHEUS_CONFIG" "${PROMETHEUS_CONFIG}.bak.$(date +%s)"
# Determine the target address
local target_host
if [[ "$INSTALL_MODE" == "docker" ]]; then
target_host="${CONTAINER_NAME}:8080"
else
target_host="localhost:${LISTEN_PORT}"
fi
cat >> "$PROMETHEUS_CONFIG" << EOF
- job_name: 'cadvisor'
scrape_interval: 15s
static_configs:
- targets: ['${target_host}']
EOF
log_info "Added cAdvisor scrape target to $PROMETHEUS_CONFIG"
# Reload Prometheus if running
if systemctl is-active --quiet prometheus 2>/dev/null; then
if systemctl reload prometheus 2>/dev/null; then
log_info "Prometheus configuration reloaded"
else
systemctl restart prometheus 2>/dev/null || true
log_info "Prometheus restarted"
fi
fi
}
#########################
### Uninstall ###
#########################
uninstall_cadvisor() {
log_info "Uninstalling cAdvisor..."
if [[ "$DRY_RUN" == "true" ]]; then
log_info "[DRY RUN] Would stop and remove Docker container '$CONTAINER_NAME'"
log_info "[DRY RUN] Would stop and remove systemd service 'cadvisor'"
log_info "[DRY RUN] Would remove /usr/local/bin/cadvisor"
return
fi
# Remove Docker container
if docker ps -a --format '{{.Names}}' 2>/dev/null | grep -q "^${CONTAINER_NAME}$"; then
docker stop "$CONTAINER_NAME" 2>/dev/null || true
docker rm "$CONTAINER_NAME" 2>/dev/null || true
log_info "Removed Docker container: $CONTAINER_NAME"
fi
# Remove systemd service
if [[ -f /etc/systemd/system/cadvisor.service ]]; then
systemctl stop cadvisor 2>/dev/null || true
systemctl disable cadvisor 2>/dev/null || true
rm -f /etc/systemd/system/cadvisor.service
systemctl daemon-reload
log_info "Removed systemd service"
fi
# Remove binary
if [[ -f /usr/local/bin/cadvisor ]]; then
rm -f /usr/local/bin/cadvisor
log_info "Removed /usr/local/bin/cadvisor"
fi
log_info "cAdvisor uninstalled"
}
#########################
### Verify ###
#########################
verify_installation() {
if [[ "$DRY_RUN" == "true" ]]; then
return
fi
echo
echo "=== cAdvisor Installation Summary ==="
echo " Mode: $INSTALL_MODE"
echo " Version: $CADVISOR_VERSION"
echo " Metrics URL: http://localhost:${LISTEN_PORT}/metrics"
echo " Web UI: http://localhost:${LISTEN_PORT}/"
echo
if [[ "$INSTALL_MODE" == "docker" ]]; then
echo " Container: $CONTAINER_NAME"
echo " Status: $(docker inspect -f '{{.State.Status}}' "$CONTAINER_NAME" 2>/dev/null || echo 'unknown')"
else
echo " Service: cadvisor.service"
echo " Status: $(systemctl is-active cadvisor 2>/dev/null || echo 'unknown')"
fi
echo
echo "Verify with:"
echo " curl -s http://localhost:${LISTEN_PORT}/metrics | head -20"
echo
if [[ "$ADD_TO_PROMETHEUS" == "true" ]]; then
echo "Prometheus scrape target configured in: $PROMETHEUS_CONFIG"
echo
else
echo "To add to Prometheus, add this to your scrape_configs:"
echo
echo " - job_name: 'cadvisor'"
echo " scrape_interval: 15s"
echo " static_configs:"
if [[ "$INSTALL_MODE" == "docker" ]]; then
echo " - targets: ['${CONTAINER_NAME}:8080']"
else
echo " - targets: ['localhost:${LISTEN_PORT}']"
fi
echo
fi
}
#########################
### Main ###
#########################
main() {
parse_arguments "$@"
if [[ "$UNINSTALL" == "true" ]]; then
check_permissions
uninstall_cadvisor
exit 0
fi
check_permissions
log_info "Installing cAdvisor v${CADVISOR_VERSION} (mode: ${INSTALL_MODE})"
case "$INSTALL_MODE" in
docker) install_docker_mode ;;
binary) install_binary_mode ;;
*) log_error "Unknown install mode: $INSTALL_MODE"; exit 1 ;;
esac
add_prometheus_scrape_config
verify_installation
}
main "$@"