Vault est resté scellé onze jours en silence, et c'était le pod le plus faible du cluster #46
@@ -0,0 +1,33 @@
|
|||||||
|
{{/*
|
||||||
|
F—: VAULT NE DOIT PLUS ÊTRE LE POD LE PLUS FAIBLE DU CLUSTER.
|
||||||
|
|
||||||
|
Constat du 2026-09-11, mesuré : `priorityClassName=""`, `priority=0`, QoS `BestEffort`.
|
||||||
|
Autrement dit Vault était littéralement dernier servi et premier évincé, alors que le
|
||||||
|
Vault Secrets Operator en dépend pour TOUS les Secrets du cluster. Quand il tombe, il
|
||||||
|
repart scellé (Shamir 1/1, pas d'auto-unseal — décision assumée) et plus rien ne se
|
||||||
|
réconcilie jusqu'à ce qu'un humain vienne le desceller.
|
||||||
|
|
||||||
|
POURQUOI 900000000. Il existe déjà `longhorn-critical` à 1000000000. Vault stocke ses
|
||||||
|
données sur un PVC : si Longhorn tombe, Vault ne repart pas. Le stockage doit donc rester
|
||||||
|
AU-DESSUS. En dessous de Vault, tout le reste — applications comprises.
|
||||||
|
|
||||||
|
CE QUE ÇA ACHÈTE, ET CE QUE ÇA N'ACHÈTE PAS. La priorité joue sur la préemption par le
|
||||||
|
scheduler et sert de critère de tri à l'éviction par le kubelet sous pression. Elle
|
||||||
|
n'empêche PAS la suppression décidée par le node-lifecycle controller quand un nœud
|
||||||
|
devient injoignable — c'est exactement ce qui s'est produit le 30/08 et aucun réglage de
|
||||||
|
pod ne l'évite. Ce qui traite ce cas-là, c'est l'alerte VaultIndisponible.
|
||||||
|
*/}}
|
||||||
|
apiVersion: scheduling.k8s.io/v1
|
||||||
|
kind: PriorityClass
|
||||||
|
metadata:
|
||||||
|
name: vault-critical
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/managed-by: {{ .Release.Service }}
|
||||||
|
app.kubernetes.io/part-of: hashicorp-vault
|
||||||
|
value: 900000000
|
||||||
|
globalDefault: false
|
||||||
|
preemptionPolicy: PreemptLowerPriority
|
||||||
|
description: >-
|
||||||
|
Vault et son opérateur : tout le cluster en dépend pour ses Secrets, et un Vault tombé
|
||||||
|
repart scellé, donc muet jusqu'à intervention humaine. Sous longhorn-critical (le
|
||||||
|
stockage doit survivre à Vault), au-dessus de tout le reste.
|
||||||
@@ -8,6 +8,17 @@
|
|||||||
# d'une panne de nœud ni d'une suppression manuelle. Avec un seul réplica et
|
# d'une panne de nœud ni d'une suppression manuelle. Avec un seul réplica et
|
||||||
# aucun auto-unseal, toute interruption exige un unseal humain ensuite ; ce PDB
|
# aucun auto-unseal, toute interruption exige un unseal humain ensuite ; ce PDB
|
||||||
# réduit seulement les interruptions évitables.
|
# réduit seulement les interruptions évitables.
|
||||||
|
#
|
||||||
|
# ⚠ CONSÉQUENCE À CONNAÎTRE AVANT LA PROCHAINE MAINTENANCE D'UN NŒUD.
|
||||||
|
# `maxUnavailable: 0` sur un StatefulSet à UN réplica donne `ALLOWED DISRUPTIONS: 0`
|
||||||
|
# en permanence — vérifié : `kubectl get pdb -n tools` le montre depuis 20 jours.
|
||||||
|
# Un `kubectl drain <nœud>` sur le nœud qui héberge Vault ne se terminera donc JAMAIS,
|
||||||
|
# il bouclera en silence sur « cannot evict pod as it would violate the budget ».
|
||||||
|
# C'est le comportement voulu — il force à traiter Vault consciemment — mais il faut
|
||||||
|
# savoir en sortir :
|
||||||
|
# kubectl drain <nœud> --disable-eviction # contourne le PDB (supprime le pod)
|
||||||
|
# ou kubectl delete pod -n tools hashicorp-vault-0 # puis descellement à la main
|
||||||
|
# Dans les deux cas Vault repart scellé : avoir la clé sous la main AVANT de drainer.
|
||||||
apiVersion: policy/v1
|
apiVersion: policy/v1
|
||||||
kind: PodDisruptionBudget
|
kind: PodDisruptionBudget
|
||||||
metadata:
|
metadata:
|
||||||
|
|||||||
@@ -6,6 +6,36 @@ vault: &vault_config
|
|||||||
server:
|
server:
|
||||||
enabled: true
|
enabled: true
|
||||||
logLevel: trace
|
logLevel: trace
|
||||||
|
# ---- NE PLUS ÊTRE LE POD LE PLUS FAIBLE DU CLUSTER -----------------------------
|
||||||
|
# Mesuré le 2026-09-11, avant ce changement : `priorityClassName=""`, `priority=0`,
|
||||||
|
# QoS `BestEffort`. Vault était donc dernier servi par le scheduler et PREMIER évincé
|
||||||
|
# par le kubelet sous pression mémoire — alors que le Vault Secrets Operator en dépend
|
||||||
|
# pour tous les Secrets du cluster, et qu'un Vault tombé repart SCELLÉ, donc muet
|
||||||
|
# jusqu'à ce qu'un humain vienne le desceller à la main.
|
||||||
|
#
|
||||||
|
# Contexte : 78 pods du cluster sont BestEffort contre 35 Burstable et 1 Guaranteed.
|
||||||
|
# Vault était noyé dans le premier groupe.
|
||||||
|
priorityClassName: vault-critical # cf. templates/priorityclass.yaml
|
||||||
|
resources:
|
||||||
|
# DES REQUESTS, ET DÉLIBÉRÉMENT AUCUNE LIMITE.
|
||||||
|
#
|
||||||
|
# Ce sont les `requests` qui protègent : le kubelet évince d'abord les BestEffort,
|
||||||
|
# puis les Burstable qui DÉPASSENT leur requête, et en dernier ceux qui restent
|
||||||
|
# dessous. Vault consomme ~175 Mio (kubectl top, 11/09) : avec 512 Mio demandés il
|
||||||
|
# est très en dessous, donc tout en bas de la liste des candidats à l'éviction.
|
||||||
|
#
|
||||||
|
# Pourquoi pas de `limits.memory`, qui donnerait du Guaranteed : une limite trop
|
||||||
|
# basse déclenche un OOMKill, et un OOMKill sur CE pod coûte un descellement manuel.
|
||||||
|
# Or je n'ai pas pu établir de pic de mémoire fiable — les séries cAdvisor de ce
|
||||||
|
# cluster rendent huit valeurs contradictoires pour ce pod (jusqu'à 2,3 Gio, ce qui
|
||||||
|
# est invraisemblable pour un Vault en storage "file"). On ne pose pas une limite sur
|
||||||
|
# un chiffre auquel on ne croit pas : le gain marginal ne vaut pas le risque.
|
||||||
|
#
|
||||||
|
# Pourquoi pas de `limits.cpu` : le throttling CPU sur un ARM64 à 4 cœurs ralentirait
|
||||||
|
# les opérations de descellement et de scellement, pour un pod qui consomme 26 m.
|
||||||
|
requests:
|
||||||
|
memory: 512Mi
|
||||||
|
cpu: 100m
|
||||||
auditStorage:
|
auditStorage:
|
||||||
enabled: true
|
enabled: true
|
||||||
|
|
||||||
|
|||||||
@@ -1265,6 +1265,61 @@ prometheus: &prometheus_config
|
|||||||
annotations:
|
annotations:
|
||||||
summary: "Homelab — cert {{ $labels.namespace }}/{{ $labels.name }} expire dans {{ $value | humanizeDuration }}"
|
summary: "Homelab — cert {{ $labels.namespace }}/{{ $labels.name }} expire dans {{ $value | humanizeDuration }}"
|
||||||
description: "Le renouvellement automatique (cert-manager → step-issuer → step-ca) est en échec. Vérifier : kubectl get certificaterequest -A, logs step-issuer (résolution DNS de ssl-ca.arcodange.lab), santé de step-ca sur pi1:8443."
|
description: "Le renouvellement automatique (cert-manager → step-issuer → step-ca) est en échec. Vérifier : kubectl get certificaterequest -A, logs step-issuer (résolution DNS de ssl-ca.arcodange.lab), santé de step-ca sur pi1:8443."
|
||||||
|
# ---- VAULT SCELLÉ ------------------------------------------------------
|
||||||
|
# Incident 2026-08-30 → 2026-09-10 : Vault est resté SCELLÉ ONZE JOURS.
|
||||||
|
# Le VSO ne pouvait plus s'authentifier (503 « Vault is sealed »), donc les
|
||||||
|
# Secrets de plusieurs applications ont cessé d'être réconciliés — en silence.
|
||||||
|
# Découvert par hasard, en enquêtant sur tout autre chose.
|
||||||
|
#
|
||||||
|
# CE QUI A MARCHÉ CE JOUR-LÀ : `NoeudInjoignable` a bien tiré à 11:46 quand pi3
|
||||||
|
# a cessé de répondre. L'infra a parlé. CE QUI A MANQUÉ : la CONSÉQUENCE. Le
|
||||||
|
# nœud est revenu, les pods ont été recréés, l'alerte s'est éteinte — et
|
||||||
|
# personne n'a su que Vault, lui, était reparti scellé et le resterait.
|
||||||
|
#
|
||||||
|
# POURQUOI `kube_pod_status_ready` ET PAS `vault_core_unsealed` : Vault n'expose
|
||||||
|
# ses métriques que via /v1/sys/metrics, qui exige soit un token, soit
|
||||||
|
# `unauthenticated_metrics_access = true` dans la stanza telemetry. Le second
|
||||||
|
# ouvre un endpoint non authentifié pour gagner… le même signal. Or la
|
||||||
|
# readinessProbe du chart est littéralement `vault status` : un Vault scellé est
|
||||||
|
# NotReady, point. kube-state-metrics est déjà scrapé, ça ne coûte rien, et ça
|
||||||
|
# ne touche pas à la configuration de Vault.
|
||||||
|
#
|
||||||
|
# ⚠ Cette alerte ne distingue pas « scellé » de « en train de démarrer » ou
|
||||||
|
# « planté ». C'est VOULU : dans les trois cas Vault ne sert plus de secrets, et
|
||||||
|
# le geste de l'opérateur commence pareil — aller voir `vault status`.
|
||||||
|
- alert: VaultIndisponible
|
||||||
|
# ⚠ LE SÉLECTEUR EST ANCRÉ SUR `[0-9]+`, ET CE N'EST PAS COSMÉTIQUE : un
|
||||||
|
# `hashicorp-vault-.*` attrape aussi les pods du Vault Secrets Operator
|
||||||
|
# (`hashicorp-vault-vault-secrets-operator-controller-manager-xxxxx`), dont un
|
||||||
|
# exemplaire terminé traîne en permanence — la règle aurait donc tiré sans
|
||||||
|
# arrêt, et une alerte qui crie tout le temps ne se lit plus. Vérifié contre le
|
||||||
|
# Prometheus du cluster : `[0-9]+` ne rend que hashicorp-vault-0. Toute
|
||||||
|
# évolution de ce sélecteur se re-teste de la même façon, sur le vrai serveur.
|
||||||
|
#
|
||||||
|
# `absent()` : si le pod disparaît (évincé, nœud perdu), la série n'existe plus
|
||||||
|
# et une simple comparaison `== 0` serait muette — exactement le mode de panne
|
||||||
|
# qu'on essaie de couvrir. Même motif que IngressLabIndisponible ci-dessus.
|
||||||
|
expr: >-
|
||||||
|
kube_pod_status_ready{namespace="tools", pod=~"hashicorp-vault-[0-9]+", condition="true"} == 0
|
||||||
|
or absent(kube_pod_status_ready{namespace="tools", pod=~"hashicorp-vault-[0-9]+", condition="true"})
|
||||||
|
# 10 min : large devant un redémarrage normal (le pod est Ready en ~30 s),
|
||||||
|
# court devant onze jours.
|
||||||
|
for: 10m
|
||||||
|
labels:
|
||||||
|
severity: critical
|
||||||
|
app: homelab
|
||||||
|
annotations:
|
||||||
|
summary: "Homelab — Vault ne sert plus de secrets (probablement scellé)"
|
||||||
|
description: >-
|
||||||
|
hashicorp-vault n'est plus Ready depuis 10 min. Le cas le plus fréquent est
|
||||||
|
un Vault SCELLÉ : il repart toujours scellé après recréation du pod (Shamir
|
||||||
|
1/1, pas d'auto-unseal — c'est une décision assumée, cf. factory
|
||||||
|
vibe/guidebooks/lab-ecosystem/secrets-and-vault.md). Tant qu'il l'est, le
|
||||||
|
Vault Secrets Operator ne réconcilie plus AUCUN Secret : les applications
|
||||||
|
tournent sur leurs Secrets existants et cassent dès qu'un pod redémarre.
|
||||||
|
Vérifier - kubectl -n tools exec hashicorp-vault-0 -- vault status.
|
||||||
|
Desceller - le rôle ansible arcodange.factory/hashicorp_vault, tâche
|
||||||
|
unseal.yml (clé dans ~/.arcodange/cluster-keys.json sur le poste).
|
||||||
# Le veilleur (arcodange-org/tools#36). Du 2026-09-04 02:41 au
|
# Le veilleur (arcodange-org/tools#36). Du 2026-09-04 02:41 au
|
||||||
# 2026-09-07 07:37, Prometheus n'a rien enregistré et les 11 règles
|
# 2026-09-07 07:37, Prometheus n'a rien enregistré et les 11 règles
|
||||||
# ci-dessus se sont TUES — sans échantillon frais, une règle ne se
|
# ci-dessus se sont TUES — sans échantillon frais, une règle ne se
|
||||||
|
|||||||
Reference in New Issue
Block a user