forked from roger/k3s-cluster
loki + promtail new monitoring services
This commit is contained in:
@@ -17,8 +17,8 @@ spec:
|
||||
labels:
|
||||
app: hermes
|
||||
spec:
|
||||
serviceAccountName: platform-engineer
|
||||
# No imagePullSecrets — using the public stock Hermes image from Docker Hub.
|
||||
# No serviceAccountName — the agent has NO k8s API access. It manages the
|
||||
# cluster via git commits (→ ArgoCD sync) and reads via Loki/Prometheus/ArgoCD.
|
||||
|
||||
# Pin to the powerful amd64 node (image is linux/amd64; the NUC has 24 GiB).
|
||||
nodeSelector:
|
||||
@@ -42,29 +42,33 @@ spec:
|
||||
topologyKey: kubernetes.io/hostname
|
||||
|
||||
initContainers:
|
||||
# Download kubectl + helm into a shared emptyDir so the stock Hermes image
|
||||
# (which doesn't ship kubectl) can still drive the cluster. Avoids building
|
||||
# and pushing a custom image through a slow / size-capped registry.
|
||||
- name: install-tools
|
||||
image: curlimages/curl:8.12.1
|
||||
# Clone the k3s-cluster repo into a persistent workspace so the agent can
|
||||
# commit + push remediations. The token is injected via envFrom.
|
||||
- name: git-clone
|
||||
image: alpine/git:2.43.0
|
||||
command: ["sh", "-c"]
|
||||
args:
|
||||
- |
|
||||
set -e
|
||||
echo "Downloading kubectl v1.35.0..."
|
||||
curl -fsSL -o /tools/kubectl \
|
||||
https://dl.k8s.io/release/v1.35.0/bin/linux/amd64/kubectl
|
||||
chmod +x /tools/kubectl
|
||||
echo "Downloading helm v3.16.3..."
|
||||
curl -fsSL https://get.helm.sh/helm-v3.16.3-linux-amd64.tar.gz \
|
||||
| tar -xz -C /tools --strip-components=1 linux-amd64/helm
|
||||
chmod +x /tools/helm
|
||||
echo "Tools installed:"; ls -la /tools
|
||||
cd /workspace
|
||||
if [ -d k3s-cluster/.git ]; then
|
||||
echo "Repo exists, pulling latest..."
|
||||
cd k3s-cluster && git pull --rebase || true
|
||||
else
|
||||
echo "Cloning repo..."
|
||||
git clone "${GITEA_REPO_URL}" k3s-cluster
|
||||
cd k3s-cluster
|
||||
git config user.name "Platform Engineer"
|
||||
git config user.email "platform-engineer@rogi.casa"
|
||||
fi
|
||||
envFrom:
|
||||
- secretRef:
|
||||
name: hermes-env
|
||||
volumeMounts:
|
||||
- name: tools
|
||||
mountPath: /tools
|
||||
- name: workspace
|
||||
mountPath: /workspace
|
||||
|
||||
# Seed /opt/data with config.yaml + SOUL.md on first boot only.
|
||||
# Seed /opt/data with config.yaml + SOUL.md + .env on first boot only.
|
||||
# ArgoCD owns the manifests; the PVC is runtime state and is NOT reconciled.
|
||||
- name: seed-data
|
||||
image: busybox:1.36
|
||||
@@ -73,14 +77,28 @@ spec:
|
||||
- |
|
||||
set -e
|
||||
if [ ! -f /opt/data/config.yaml ]; then
|
||||
echo "First boot: seeding /opt/data from ConfigMap..."
|
||||
echo "First boot: seeding /opt/data from ConfigMap + env..."
|
||||
cp /seed/config.yaml /opt/data/config.yaml
|
||||
cp /seed/SOUL.md /opt/data/SOUL.md
|
||||
chmod 600 /opt/data/config.yaml
|
||||
# Write .env from the injected Secret env vars so the s6 gateway
|
||||
# finds API keys (the hermes container reads keys from /opt/data/.env).
|
||||
: > /opt/data/.env
|
||||
chmod 600 /opt/data/.env
|
||||
for k in OPENAI_API_KEY OPENAI_BASE_URL DISCORD_BOT_TOKEN DISCORD_HOME_CHANNEL \
|
||||
GITEA_TOKEN GITEA_REPO_URL ARGOCD_API_TOKEN ARGOCD_SERVER \
|
||||
HERMES_DASHBOARD HERMES_DASHBOARD_BASIC_AUTH_USERNAME \
|
||||
HERMES_DASHBOARD_BASIC_AUTH_PASSWORD HERMES_DASHBOARD_BASIC_AUTH_SECRET; do
|
||||
eval "v=\${$k:-}"
|
||||
[ -n "$v" ] && echo "$k=$v" >> /opt/data/.env
|
||||
done
|
||||
else
|
||||
echo "/opt/data already initialized — leaving runtime state intact."
|
||||
fi
|
||||
mkdir -p /opt/data/home/.kube /opt/data/cron/output /opt/data/scripts /workspace
|
||||
mkdir -p /opt/data/home/.kube /opt/data/cron/output /opt/data/scripts
|
||||
envFrom:
|
||||
- secretRef:
|
||||
name: hermes-env
|
||||
volumeMounts:
|
||||
- name: data
|
||||
mountPath: /opt/data
|
||||
@@ -93,8 +111,7 @@ spec:
|
||||
imagePullPolicy: Always
|
||||
# IMPORTANT: do NOT set `command:` — it would override the image's
|
||||
# ENTRYPOINT (/init, s6-overlay), which sets up the hermes user, seeds
|
||||
# config on first boot, and supervises the gateway. The image's CMD
|
||||
# (main-wrapper.sh) already routes `gateway run` through s6.
|
||||
# config on first boot, and supervises the gateway.
|
||||
args: ["gateway", "run"]
|
||||
ports:
|
||||
- name: gateway
|
||||
@@ -105,21 +122,13 @@ spec:
|
||||
- secretRef:
|
||||
name: hermes-env
|
||||
env:
|
||||
# k3s injects KUBERNETES_SERVICE_HOST/PORT + the SA token automatically;
|
||||
# kubectl inside the pod authenticates as the platform-engineer SA.
|
||||
- name: HERMES_HOME
|
||||
value: /opt/data
|
||||
# Put the initContainer-installed kubectl/helm on PATH for the hermes user.
|
||||
- name: PATH
|
||||
value: /opt/hermes/bin:/opt/hermes/.venv/bin:/tools:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
|
||||
volumeMounts:
|
||||
- name: data
|
||||
mountPath: /opt/data
|
||||
- name: workspace
|
||||
mountPath: /workspace
|
||||
- name: tools
|
||||
mountPath: /tools
|
||||
readOnly: true
|
||||
resources:
|
||||
requests:
|
||||
memory: "512Mi"
|
||||
@@ -129,10 +138,7 @@ spec:
|
||||
cpu: "1000m"
|
||||
livenessProbe:
|
||||
# Probe the dashboard port (9119, always enabled via HERMES_DASHBOARD=1
|
||||
# and binds 0.0.0.0). The gateway API on 8642 is off by default
|
||||
# (API_SERVER_ENABLED not set), so 9119 is the reliable liveness signal.
|
||||
# s6 auto-restarts the gateway itself; this probe only catches a wedged
|
||||
# container.
|
||||
# and binds 0.0.0.0). The gateway API on 8642 is off by default.
|
||||
tcpSocket:
|
||||
port: 9119
|
||||
initialDelaySeconds: 90
|
||||
@@ -148,8 +154,6 @@ spec:
|
||||
claimName: hermes-data
|
||||
- name: workspace
|
||||
emptyDir: {}
|
||||
- name: tools
|
||||
emptyDir: {}
|
||||
- name: seed
|
||||
configMap:
|
||||
name: hermes-seed
|
||||
|
||||
Reference in New Issue
Block a user