czy publishes no service ports, so Traefik exposes each service's :9464 as https://ledgerline.vione.cloud/metrics/<service> behind basic auth, and the platform's Prometheus gets a `ledgerline` job with one target per service. The targets share an address; a `service` label tells them apart, and relabels derive __metrics_path__ and instance from it. create-secrets.sh now also creates the prometheus-scrape-auth secret (mounted optional, so a missing secret fails only this job) and writes the gitignored htpasswd file Traefik reads, which is copied to czy like .env.observability. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
84 lines
3.0 KiB
Bash
Executable File
84 lines
3.0 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# Create the platform's secrets in the cluster. Idempotent: credentials are
|
|
# generated once into k8s/.credentials (gitignored, mode 600) and reused on
|
|
# every later run, so re-running only re-applies the same secrets.
|
|
#
|
|
# ./k8s/create-secrets.sh
|
|
#
|
|
# Creates, in namespace ledgerline-observability:
|
|
# obs-basic-auth htpasswd for the Traefik basic-auth middleware
|
|
# (Prometheus, Alertmanager, Loki, Tempo, Alloy UI, OTLP)
|
|
# grafana-admin Grafana admin user/password
|
|
# prometheus-scrape-auth
|
|
# username/password Prometheus sends when scraping Ledgerline
|
|
# and writes two gitignored files for czy; copy both to the server after every
|
|
# regeneration (see k8s/README.md):
|
|
# .env.observability for the Alloy log agent and the OTLP auth header of
|
|
# instrumented services
|
|
# observability/traefik/metrics-users
|
|
# htpasswd for Traefik's basic auth on /metrics/<service>
|
|
#
|
|
# KUBECTL defaults to `kubectl`; e.g. KUBECTL="ssh falken kubectl" to run it on
|
|
# the node when the API server isn't reachable from here.
|
|
set -euo pipefail
|
|
|
|
cd "$(dirname "$0")"
|
|
KUBECTL="${KUBECTL:-kubectl}"
|
|
NS=ledgerline-observability
|
|
CREDS=.credentials
|
|
|
|
if [ ! -f "$CREDS" ]; then
|
|
umask 077
|
|
cat > "$CREDS" <<EOF
|
|
OBS_USER=ledgerline
|
|
OBS_PASSWORD=$(openssl rand -hex 24)
|
|
GRAFANA_ADMIN_USER=admin
|
|
GRAFANA_ADMIN_PASSWORD=$(openssl rand -hex 24)
|
|
EOF
|
|
echo "generated $PWD/$CREDS"
|
|
fi
|
|
# shellcheck disable=SC1090
|
|
source "$CREDS"
|
|
|
|
# Secrets are rendered locally (no API access needed) and applied through
|
|
# $KUBECTL, so they never appear on a command line on the remote side.
|
|
$KUBECTL apply -f - < namespace.yaml
|
|
|
|
kubectl create secret generic obs-basic-auth -n "$NS" \
|
|
--from-literal=users="$(htpasswd -nbB "$OBS_USER" "$OBS_PASSWORD")" \
|
|
--dry-run=client -o yaml | $KUBECTL apply -f -
|
|
|
|
kubectl create secret generic grafana-admin -n "$NS" \
|
|
--from-literal=admin-user="$GRAFANA_ADMIN_USER" \
|
|
--from-literal=admin-password="$GRAFANA_ADMIN_PASSWORD" \
|
|
--dry-run=client -o yaml | $KUBECTL apply -f -
|
|
|
|
kubectl create secret generic prometheus-scrape-auth -n "$NS" \
|
|
--from-literal=username="$OBS_USER" \
|
|
--from-literal=password="$OBS_PASSWORD" \
|
|
--dry-run=client -o yaml | $KUBECTL apply -f -
|
|
|
|
# OTLP header for instrumented services: URL-encoded (space -> %20), and
|
|
# newlines stripped because GNU base64 wraps at 76 chars and this is ~80.
|
|
OTLP_BASIC=$(printf '%s:%s' "$OBS_USER" "$OBS_PASSWORD" | base64 | tr -d '\n')
|
|
|
|
(
|
|
umask 077
|
|
cat > ../.env.observability <<EOF
|
|
# Credentials for the Alloy log agent and instrumented services on czy.
|
|
# Generated by k8s/create-secrets.sh -- do not commit.
|
|
LOKI_PUSH_URL=https://loki.vione.cloud/loki/api/v1/push
|
|
LOKI_PUSH_USER=$OBS_USER
|
|
LOKI_PUSH_PASSWORD=$OBS_PASSWORD
|
|
OTEL_EXPORTER_OTLP_HEADERS=Authorization=Basic%20$OTLP_BASIC
|
|
EOF
|
|
)
|
|
echo "wrote $(cd .. && pwd)/.env.observability"
|
|
|
|
(
|
|
umask 077
|
|
mkdir -p ../observability/traefik
|
|
htpasswd -nbB "$OBS_USER" "$OBS_PASSWORD" > ../observability/traefik/metrics-users
|
|
)
|
|
echo "wrote $(cd .. && pwd)/observability/traefik/metrics-users"
|