observability: fix alloy ui component, busybox healthchecks for loki/alloy
- alloy 1.x renamed the server component to ui; the old block failed the initial load and the container crash-looped - grafana/loki is distroless and grafana/alloy lacks wget, so their healthchecks could never run; local images add a static busybox from alpine for that one command - deploy.sh builds all three local images if missing - tests: 3 new seams
This commit is contained in:
@@ -0,0 +1,15 @@
|
|||||||
|
# Alloy + a static busybox.
|
||||||
|
#
|
||||||
|
# grafana/alloy has a shell but no wget/curl, so the compose healthcheck
|
||||||
|
# cannot run anything inside the container. This image drops a static
|
||||||
|
# busybox into it for the healthcheck command only. All Alloy behavior is
|
||||||
|
# unchanged.
|
||||||
|
#
|
||||||
|
# Build on dankclaw:
|
||||||
|
# podman build -t franksdank/alloy:latest -f dankclaw/alloy/Containerfile .
|
||||||
|
|
||||||
|
FROM docker.io/library/alpine:latest AS tools
|
||||||
|
# busybox provides wget for the healthcheck.
|
||||||
|
|
||||||
|
FROM docker.io/grafana/alloy:latest
|
||||||
|
COPY --from=tools /bin/busybox /usr/local/bin/busybox
|
||||||
@@ -149,7 +149,8 @@ services:
|
|||||||
retries: 3
|
retries: 3
|
||||||
|
|
||||||
loki:
|
loki:
|
||||||
image: docker.io/grafana/loki:latest
|
# Local build: grafana/loki + static busybox (healthcheck).
|
||||||
|
image: franksdank/loki:latest
|
||||||
container_name: loki
|
container_name: loki
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
# Rootless: container root maps to the invoking user (dank), which
|
# Rootless: container root maps to the invoking user (dank), which
|
||||||
@@ -163,13 +164,14 @@ services:
|
|||||||
- /opt/loki/config:/etc/loki
|
- /opt/loki/config:/etc/loki
|
||||||
- /opt/loki/data:/loki
|
- /opt/loki/data:/loki
|
||||||
healthcheck:
|
healthcheck:
|
||||||
test: ["CMD", "wget", "--spider", "-q", "http://localhost:3100/ready"]
|
test: ["CMD", "/usr/local/bin/busybox", "wget", "--spider", "-q", "http://localhost:3100/ready"]
|
||||||
interval: 30s
|
interval: 30s
|
||||||
timeout: 10s
|
timeout: 10s
|
||||||
retries: 3
|
retries: 3
|
||||||
|
|
||||||
alloy:
|
alloy:
|
||||||
image: docker.io/grafana/alloy:latest
|
# Local build: grafana/alloy + static busybox (healthcheck).
|
||||||
|
image: franksdank/alloy:latest
|
||||||
container_name: alloy
|
container_name: alloy
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
volumes:
|
volumes:
|
||||||
@@ -180,7 +182,7 @@ services:
|
|||||||
depends_on:
|
depends_on:
|
||||||
- loki
|
- loki
|
||||||
healthcheck:
|
healthcheck:
|
||||||
test: ["CMD", "wget", "--spider", "-q", "http://localhost:12345/-/healthy"]
|
test: ["CMD", "/usr/local/bin/busybox", "wget", "--spider", "-q", "http://localhost:12345/-/healthy"]
|
||||||
interval: 30s
|
interval: 30s
|
||||||
timeout: 10s
|
timeout: 10s
|
||||||
retries: 3
|
retries: 3
|
||||||
|
|||||||
@@ -0,0 +1,15 @@
|
|||||||
|
# Loki + a static busybox.
|
||||||
|
#
|
||||||
|
# grafana/loki is distroless: no shell, no wget, so the compose healthcheck
|
||||||
|
# cannot run anything inside the container. This image drops a static
|
||||||
|
# busybox into it for the healthcheck command only. All Loki behavior is
|
||||||
|
# unchanged.
|
||||||
|
#
|
||||||
|
# Build on dankclaw:
|
||||||
|
# podman build -t franksdank/loki:latest -f dankclaw/loki/Containerfile .
|
||||||
|
|
||||||
|
FROM docker.io/library/alpine:latest AS tools
|
||||||
|
# busybox provides wget for the healthcheck.
|
||||||
|
|
||||||
|
FROM docker.io/grafana/loki:latest
|
||||||
|
COPY --from=tools /bin/busybox /usr/local/bin/busybox
|
||||||
+10
-4
@@ -139,10 +139,16 @@ fi
|
|||||||
|
|
||||||
if [ '${COMPOSE_UP[$TARGET]}' = '1' ]; then
|
if [ '${COMPOSE_UP[$TARGET]}' = '1' ]; then
|
||||||
echo '[4/4] Restarting stack...'
|
echo '[4/4] Restarting stack...'
|
||||||
if ! podman image exists franksdank/caddy-porkbun:latest; then
|
# Locally built images: caddy + porkbun module, and loki/alloy + a static
|
||||||
echo ' franksdank/caddy-porkbun image missing; building it (a few minutes)...'
|
# busybox (their upstream images lack the wget the healthchecks need).
|
||||||
podman build -t franksdank/caddy-porkbun:latest -f dankclaw/caddy/Containerfile .
|
for dir in caddy loki alloy; do
|
||||||
fi
|
img=franksdank/$dir
|
||||||
|
[ "$dir" = "caddy" ] && img=franksdank/caddy-porkbun
|
||||||
|
if ! podman image exists $img:latest; then
|
||||||
|
echo " $img image missing; building it..."
|
||||||
|
podman build -t $img:latest -f dankclaw/$dir/Containerfile .
|
||||||
|
fi
|
||||||
|
done
|
||||||
podman-compose -f '${COMPOSE[$TARGET]}' up -d
|
podman-compose -f '${COMPOSE[$TARGET]}' up -d
|
||||||
else
|
else
|
||||||
echo '[4/4] Skipping compose restart (stack runs as bare containers on this host)'
|
echo '[4/4] Skipping compose restart (stack runs as bare containers on this host)'
|
||||||
|
|||||||
@@ -6,9 +6,10 @@ logging {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Local listener so the container healthcheck can probe us.
|
// Local listener so the container healthcheck can probe us.
|
||||||
server {
|
// Alloy >= 1.0 renamed the server component to ui.
|
||||||
http_listen_addr = "0.0.0.0:12345"
|
ui {
|
||||||
grpc_listen_addr = "0.0.0.0:12346"
|
host = "0.0.0.0"
|
||||||
|
port = 12345
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ship logs to Loki (container name on the podman network).
|
// Ship logs to Loki (container name on the podman network).
|
||||||
|
|||||||
@@ -136,3 +136,29 @@ CADDYFILE="$REPO_ROOT/dankclaw/Caddyfile"
|
|||||||
}
|
}
|
||||||
done
|
done
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# --- distroless healthchecks (loki/alloy carry a static busybox) ---
|
||||||
|
|
||||||
|
@test "loki and alloy run from local images carrying a static busybox" {
|
||||||
|
local compose="$REPO_ROOT/dankclaw/compose.yaml"
|
||||||
|
grep -q 'image: franksdank/loki:latest' "$compose" || { echo "loki image not local"; return 1; }
|
||||||
|
grep -q 'image: franksdank/alloy:latest' "$compose" || { echo "alloy image not local"; return 1; }
|
||||||
|
local img
|
||||||
|
for img in loki alloy; do
|
||||||
|
local cf="$REPO_ROOT/dankclaw/$img/Containerfile"
|
||||||
|
[ -f "$cf" ] || { echo "missing $cf"; return 1; }
|
||||||
|
grep -q 'busybox' "$cf" || { echo "$cf does not install busybox"; return 1; }
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
@test "loki and alloy healthchecks use the busybox wget" {
|
||||||
|
local compose="$REPO_ROOT/dankclaw/compose.yaml"
|
||||||
|
local n
|
||||||
|
n=$(grep -c '/usr/local/bin/busybox' "$compose")
|
||||||
|
[ "$n" -ge 2 ] || { echo "expected >=2 busybox healthchecks, found $n"; return 1; }
|
||||||
|
}
|
||||||
|
|
||||||
|
@test "alloy config uses the ui component (the server component was renamed)" {
|
||||||
|
grep -qE '^ui \{' "$REPO_ROOT/shared/alloy/config.alloy"
|
||||||
|
! grep -qE '^server \{' "$REPO_ROOT/shared/alloy/config.alloy"
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user