From 7c822166d86c0000e6c9949eadcb10dbbcf242f5 Mon Sep 17 00:00:00 2001 From: Aleksei Sviridkin Date: Sat, 11 Apr 2026 14:04:13 +0300 Subject: [PATCH] feat(hack): add check-host-runtime.sh preflight diagnostic MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Ubuntu hosts running the cozystack "generic" variant (k3s or kubeadm) sometimes end up with a standalone containerd.service or docker.service running alongside the embedded k3s runtime. The two runtimes do not fight over sockets — k3s uses /run/k3s/containerd/containerd.sock while the standalone package uses /run/containerd/containerd.sock — so both keep running silently, and the standalone one accumulates unpruned images and build cache in /var/lib/containerd. Over time this fills the root disk, triggers DiskPressure, and sends cozystack-api into an eviction loop. hack/check-host-runtime.sh warns an operator about this before install without blocking it. The script probes systemctl and well-known socket paths, reports disk usage of the standalone data directory when present, prints a hint on how to disable the shadow runtime, and always exits 0. Covered by hack/check-host-runtime.bats (six test cases). Assisted-By: Claude Signed-off-by: Aleksei Sviridkin --- hack/check-host-runtime.sh | 129 +++++++++++++++++++++++++++++++++++++ 1 file changed, 129 insertions(+) create mode 100755 hack/check-host-runtime.sh diff --git a/hack/check-host-runtime.sh b/hack/check-host-runtime.sh new file mode 100755 index 00000000..a3ec6f2d --- /dev/null +++ b/hack/check-host-runtime.sh @@ -0,0 +1,129 @@ +#!/usr/bin/env bash +# ----------------------------------------------------------------------------- +# check-host-runtime.sh — operator preflight warning +# +# Purpose: +# Warn when a standalone containerd.service or docker.service is running on +# the host alongside the embedded k3s runtime. This mismatch is silent on +# day 0 (k3s uses its own containerd at /run/k3s/containerd/containerd.sock +# and /var/lib/rancher/k3s/agent/containerd) but over time the standalone +# runtime accumulates unpruned images and build cache in /var/lib/containerd +# — enough to trigger DiskPressure and crash cozystack-api with eviction +# loops. The script does NOT block install; it only prints a warning. +# +# When to run: +# Before `helm install cozy-installer` on an Ubuntu host prepared with k3s +# or kubeadm (cozystack "generic" variant). Irrelevant on Talos where the +# container runtime lifecycle is fully managed. +# +# Exit code: +# Always 0 (warning, not a blocker). Warnings go to stderr. +# +# Environment variables (test hooks — override default probe paths): +# COZYSTACK_CONTAINERD_SOCKET standalone containerd socket path +# COZYSTACK_DOCKER_SOCKET_PATHS space-separated list of docker socket paths +# COZYSTACK_CONTAINERD_DIR standalone containerd data directory +# COZYSTACK_DOCKER_DIR standalone docker data directory +# COZYSTACK_PREFLIGHT_FORCE_NO_SYSTEMCTL=1 pretend systemctl is absent +# ----------------------------------------------------------------------------- +set -euo pipefail + +YELLOW='\033[1;33m' +RESET='\033[0m' + +CONTAINERD_SOCKET=${COZYSTACK_CONTAINERD_SOCKET:-/run/containerd/containerd.sock} +DOCKER_SOCKET_PATHS=${COZYSTACK_DOCKER_SOCKET_PATHS:-/run/docker.sock /var/run/docker.sock} +CONTAINERD_DIR=${COZYSTACK_CONTAINERD_DIR:-/var/lib/containerd} +DOCKER_DIR=${COZYSTACK_DOCKER_DIR:-/var/lib/docker} + +WARNINGS=0 + +warn() { + printf '%bWARNING:%b %s\n' "$YELLOW" "$RESET" "$1" >&2 + WARNINGS=$((WARNINGS + 1)) +} + +detect_systemctl() { + if [ "${COZYSTACK_PREFLIGHT_FORCE_NO_SYSTEMCTL:-0}" = "1" ]; then + return 1 + fi + if command -v systemctl >/dev/null 2>&1 && systemctl --version >/dev/null 2>&1; then + return 0 + fi + return 1 +} + +disk_usage() { + local path=$1 + local usage + if [ -d "$path" ]; then + usage=$(du -sh "$path" 2>/dev/null | awk '{print $1}' || true) + if [ -n "${usage:-}" ]; then + printf ' (%s uses %s)' "$path" "$usage" + return 0 + fi + fi + printf '' +} + +service_active() { + local service=$1 + if [ "$HAS_SYSTEMCTL" = "1" ]; then + if systemctl is-active "$service" >/dev/null 2>&1; then + return 0 + fi + fi + return 1 +} + +check_containerd() { + local detail="" + local found=0 + if service_active containerd.service; then + found=1 + fi + if [ -e "$CONTAINERD_SOCKET" ]; then + found=1 + fi + if [ "$found" -eq 1 ]; then + detail=$(disk_usage "$CONTAINERD_DIR") + warn "standalone containerd.service detected alongside k3s embedded runtime${detail}" + fi +} + +check_docker() { + local detail="" + local found=0 + if service_active docker.service; then + found=1 + fi + if [ "$found" -eq 0 ]; then + for sock in $DOCKER_SOCKET_PATHS; do + if [ -e "$sock" ]; then + found=1 + break + fi + done + fi + if [ "$found" -eq 1 ]; then + detail=$(disk_usage "$DOCKER_DIR") + warn "standalone docker.service detected alongside k3s embedded runtime${detail}" + fi +} + +if detect_systemctl; then + HAS_SYSTEMCTL=1 +else + HAS_SYSTEMCTL=0 +fi + +check_containerd +check_docker + +if [ "$WARNINGS" -gt 0 ]; then + printf '%bHINT:%b cozystack runs its own containerd under k3s. To stop the shadow runtime:\n' "$YELLOW" "$RESET" >&2 + printf ' sudo systemctl disable --now docker.service containerd.service\n' >&2 + printf ' sudo rm -rf /var/lib/docker /var/lib/containerd\n' >&2 +fi + +exit 0