Files
tools/minio/templates/deployment.yaml
T
arcodangeandClaude Opus 5 3c3690a26b
Helm Charts / Detect changed charts (pull_request) Successful in 21s
Helm Charts / Library charts tool (pull_request) Skipped
Helm Charts / Application charts alloy (pull_request) Skipped
Helm Charts / Application charts chart (pull_request) Skipped
Helm Charts / Application charts crowdsec (pull_request) Skipped
Helm Charts / Application charts grafana (pull_request) Skipped
Helm Charts / Application charts hashicorp-vault (pull_request) Skipped
Helm Charts / Application charts loki (pull_request) Skipped
Helm Charts / Application charts pgbouncer (pull_request) Skipped
Helm Charts / Application charts pgcat (pull_request) Skipped
Helm Charts / Application charts prometheus (pull_request) Skipped
Helm Charts / Application charts redis (pull_request) Skipped
Helm Charts / Application charts minio (pull_request) Successful in 28s
MinIO quitte pi2 : son volume y avait perdu son journal ext4, et aucun redémarrage ne le démontait
Le 14/09, pi2 (109 % de mémoire, sans swap) a fait manquer au moteur
Longhorn son délai de 8 s. Les écritures sont revenues au noyau en
« critical medium error », ext4 a abandonné son journal et remonté le
système de fichiers en lecture seule. Ce montage mort n'a jamais été
démonté : MinIO échoue en boucle sur « drive is faulty » depuis 27 h.

Une affinité requise `kubernetes.io/hostname NotIn [pi2]` (préférence
pi3) : avec la stratégie Recreate, l'ancien pod s'arrête, le volume se
détache de pi2 et se rattache ailleurs, où ext4 rejoue son journal.

Refs arcodange-org/tools#49

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-09-15 10:33:20 +02:00

202 lines
9.1 KiB
YAML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# -----------------------------------------------------------------------------
# MinIO — Deployment écrit À LA MAIN, et voici pourquoi.
#
# ⚠⚠ LE CHART OFFICIEL `minio/minio` N'OFFRE AUCUNE SONDE DE SANTÉ.
# Vérifié sur la 5.4.0 (la dernière au 2026-09-02) : aucune clé `livenessProbe`
# dans ses `values.yaml`, aucun rendu de sonde dans ses `templates/`. Ce n'était
# donc pas un oubli de configuration de notre part — il n'y avait rien à
# configurer. On reprend le manifeste à notre charge pour pouvoir poser la sonde.
#
# CE QUE ÇA A COÛTÉ, MESURÉ (arcodange-org/tools#31) :
# le 2026-08-29 à 14 h 11, les répliques Longhorn se perdent de vue sur le réseau
# (`R/W Timeout. No response received in 8s`) ; le moteur les marque `ERR` une à
# une ; à 15 h 32 le périphérique bloc disparaît sous MinIO ; à 17 h 54 **ext4
# abandonne son journal** (`comm minio: Detected aborted journal`). À partir de
# là, toute écriture rend `EIO`.
#
# Longhorn s'est rétabli TOUT SEUL le 30 août à 11 h 50. Mais un journal ext4
# abandonné ne se répare jamais seul : il le reste jusqu'au démontage. MinIO est
# donc resté assis sur un montage mort DEUX JOURS APRÈS la réparation du
# stockage, pendant que Longhorn (`healthy`), les répliques (`RW`), les nœuds,
# ArgoCD (`Synced, Healthy`) et le pod lui-même (`1/1 Running`, `0 restart`)
# affichaient tous vert. Trois jours de panne totale du stockage objet, et pas
# un seul indicateur rouge.
#
# ⚠ LE POD NE REDÉMARRE PAS QUAND SON SYSTÈME DE FICHIERS MEURT. Le processus
# vit ; c'est tout ce que Kubernetes regardait, faute de sonde.
# -----------------------------------------------------------------------------
apiVersion: apps/v1
kind: Deployment
metadata:
name: minio
namespace: tools
labels:
app: minio
release: minio
spec:
replicas: 1
# ⚠ IMMUABLE, et repris À L'IDENTIQUE de ce que le sous-chart avait posé :
# changer un `selector` sur un Deployment existant fait ÉCHOUER l'application,
# et ArgoCD le recréerait — donc détacherait puis rattacherait le volume.
selector:
matchLabels:
app: minio
release: minio
strategy:
# ⚠ `Recreate`, PAS `RollingUpdate` : le volume est ReadWriteOnce. Un
# roulement voudrait deux pods à la fois, le second resterait en
# `ContainerCreating` sur un `Multi-Attach error` jusqu'au timeout, et le
# déploiement paraîtrait « en cours » pendant des minutes. Le chart amont
# posait `maxSurge: 100%`, ce qui est le mauvais réglage pour un RWO.
type: Recreate
template:
metadata:
labels:
app: minio
release: minio
spec:
serviceAccountName: minio
# ---------------------------------------------------------------
# ⚠⚠ JAMAIS SUR pi2 (incident arcodange-org/tools#49, 2026-09-14).
#
# pi2 tourne à ~110 % de mémoire, sans swap. Le moteur Longhorn d'un
# volume vit sur le nœud du POD : sur pi2, il a manqué son délai de 8 s
# (`R/W Timeout`), les écritures sont revenues au noyau en
# `critical medium error`, et ext4 a ABANDONNÉ son journal (04:05 puis
# 07:19). Le montage mort n'est jamais démonté par un redémarrage de
# conteneur : 314 redémarrages sur « drive is faulty » en 26 h.
#
# Même mécanisme que tools#31. Déplacer le pod déplace le moteur, et le
# déplacement démonte le volume — ext4 rejoue son journal au remontage.
# ---------------------------------------------------------------
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: kubernetes.io/hostname
operator: NotIn
values: [pi2]
preferredDuringSchedulingIgnoredDuringExecution:
# pi3 est le moins chargé en mémoire (58 % au 2026-09-15, pi1 81 %).
- weight: 50
preference:
matchExpressions:
- key: kubernetes.io/hostname
operator: In
values: [pi3]
securityContext:
# Repris tel quel : la donnée déjà écrite sur le volume appartient à
# 1000:1000. Changer ces valeurs rendrait le bucket illisible.
runAsUser: 1000
runAsGroup: 1000
fsGroup: 1000
fsGroupChangePolicy: OnRootMismatch
terminationGracePeriodSeconds: 30
containers:
- name: minio
image: "{{ .Values.minio.image.repository }}:{{ .Values.minio.image.tag }}"
imagePullPolicy: {{ .Values.minio.image.pullPolicy }}
command:
- /bin/sh
- -ce
- /usr/bin/docker-entrypoint.sh minio server /export -S /etc/minio/certs/ --address :9000 --console-address :9001
env:
# Identifiants JAMAIS dans le dépôt : le secret est matérialisé par
# le Vault Secrets Operator depuis kvv2/minio/config.
- name: MINIO_ROOT_USER
valueFrom:
secretKeyRef:
name: {{ .Values.minio.existingSecret }}
key: rootUser
- name: MINIO_ROOT_PASSWORD
valueFrom:
secretKeyRef:
name: {{ .Values.minio.existingSecret }}
key: rootPassword
{{- range $cle, $valeur := .Values.minio.environment }}
- name: {{ $cle }}
value: {{ $valeur | quote }}
{{- end }}
ports:
- name: http
containerPort: 9000
protocol: TCP
- name: http-console
containerPort: 9001
protocol: TCP
# ---------------------------------------------------------------
# LES SONDES — la raison d'être de ce fichier.
#
# ⚠ `/minio/health/live` NE SUFFIT PAS, et c'est mesuré : il répond
# 200 sur un magasin QUI NE PEUT PLUS ÉCRIRE. C'est précisément
# pourquoi la panne du 29 août est restée invisible trois jours.
#
# `/minio/health/cluster` vérifie le QUORUM D'ÉCRITURE — la propriété
# qu'on veut réellement garder.
#
# SABOTAGE RELEVÉ (2026-09-02, MinIO jetable, quatre disques, les deux
# moitiés dans LE MÊME POD, même image) :
#
# | état du magasin | /health/live | /health/cluster |
# |------------------------|--------------|-----------------|
# | 4 disques sains | 200 | **200** |
# | quorum d'écriture perdu| **200** | **503** |
#
# Sabotage : `format.json` de deux disques sur quatre écrasé. La bascule
# de `cluster` est survenue entre t+20 s et t+40 s. `live` n'a jamais
# bougé. Les DEUX moitiés comptent : la sonde rougit quand la propriété
# est violée, ET reste verte sinon.
# ---------------------------------------------------------------
startupProbe:
# Au démarrage on interroge `live` : tant que MinIO monte, `cluster`
# répond 503 pour une raison légitime, et l'interroger ici tuerait
# le pod avant qu'il ait fini de démarrer.
# 24 × 5 s = 2 min accordées au démarrage.
httpGet:
path: /minio/health/live
port: 9000
periodSeconds: 5
timeoutSeconds: 5
failureThreshold: 24
readinessProbe:
# Retire MinIO du Service quand il ne peut plus écrire : les clients
# reçoivent un refus franc au lieu d'un dépôt qui part dans le vide.
httpGet:
path: /minio/health/cluster
port: 9000
periodSeconds: 15
timeoutSeconds: 5
failureThreshold: 3
livenessProbe:
# ⚠ C'EST CELLE-CI QUI AURAIT LEVÉ LA PANNE : le remède au journal
# ext4 abandonné est un démontage, donc un redémarrage du pod.
#
# ⚠ 6 × 30 s = 3 MINUTES de refus SOUTENU avant de redémarrer. Cette
# grappe connaît des à-coups Longhorn de quelques secondes (le
# déclencheur du 29 août était un `R/W Timeout` de 8 s) : une sonde
# nerveuse redémarrerait MinIO sur un hoquet. C'est l'erreur exacte
# que redis a payée ici en 2026-07 — 836 échecs de sonde, 135
# redémarrages, et un `.fr` en 403 (voir redis/values.yaml).
httpGet:
path: /minio/health/cluster
port: 9000
periodSeconds: 30
timeoutSeconds: 5
failureThreshold: 6
resources:
{{- toYaml .Values.minio.resources | nindent 12 }}
volumeMounts:
- name: export
mountPath: /export
- name: minio-user
mountPath: /tmp/credentials
readOnly: true
volumes:
- name: export
persistentVolumeClaim:
claimName: minio
- name: minio-user
secret:
secretName: {{ .Values.minio.existingSecret }}