Fix race su rs.initiate: attendi i 3 pod Mongo + directConnection in mongosh

Due bug che bloccavano deploy.sh su tenant con provisioning PVC lento:

1. Race DNS: lo step 8 aspettava solo mongodb-tenant-0 prima di rs.initiate.
   Se i pod 1/2 erano ancora in provisioning, i loro record DNS nel service
   headless non esistevano e rs.initiate falliva il quorum check con
   "Could not find address for mongodb-tenant-1...". Ora si attende che tutti
   e 3 i pod siano Ready.

2. mongosh "connection <monitor> closed": con --host 127.0.0.1, appena il
   replica set è inizializzato mongosh passa in modalità topology e prova a
   monitorare il PRIMARY via hostname annunciato, chiudendo la connessione.
   Sostituito con URI directConnection=true, compatibile con la localhost
   exception per la creazione del primo utente.

Allineati gli hint diagnostici in deploy.sh e l'esempio rs.status() nel README
al nuovo form directConnection.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Luca
2026-06-05 12:18:14 +02:00
parent 468d4562c7
commit d3a9739f2f
2 changed files with 27 additions and 13 deletions
+2 -2
View File
@@ -119,8 +119,8 @@ kubectl -n <ns> logs deploy/tenant-api --tail=100 -f
```bash
ROOT_PASS=$(kubectl -n <ns> get secret mongodb-tenant-auth -o jsonpath='{.data.root-password}' | base64 -d)
kubectl -n <ns> exec mongodb-tenant-0 -c mongodb -- mongosh \
--tls --tlsCAFile /etc/mongo-tls/ca.crt --tlsAllowInvalidHostnames --host 127.0.0.1 \
kubectl -n <ns> exec mongodb-tenant-0 -c mongodb -- mongosh --quiet \
'mongodb://127.0.0.1:27017/?directConnection=true&tls=true&tlsCAFile=/etc/mongo-tls/ca.crt&tlsAllowInvalidHostnames=true' \
-u admin -p "$ROOT_PASS" --authenticationDatabase admin \
--eval 'rs.status()'
```
+25 -11
View File
@@ -113,11 +113,17 @@ kc_cluster() { kubectl --context "$CONTEXT" "$@"; }
# mongosh dentro pod-0 — JS letto da stdin per non esporre credenziali in argv
# (kubectl exec mette argv nei log audit dell'API server e nel command line del kubelet).
# Connessione mongosh dentro pod-0 con TLS verso 127.0.0.1.
# - --tls + --tlsCAFile: valida il cert via la CA interna.
# - --tlsAllowInvalidHostnames: il cert non include 'localhost' nei SAN; la CA però
# - tls=true + tlsCAFile: valida il cert via la CA interna.
# - tlsAllowInvalidHostnames: il cert non include 'localhost' nei SAN; la CA però
# è validata, quindi MITM resta impossibile (siamo già dentro al pod).
# - 127.0.0.1: necessario per la "localhost exception" di mongo (creazione primo utente).
MONGO_TLS_ARGS=(--tls --tlsCAFile /etc/mongo-tls/ca.crt --tlsAllowInvalidHostnames --host 127.0.0.1)
# - directConnection=true: OBBLIGATORIO. Appena il replica set è inizializzato,
# senza directConnection mongosh passa in modalità topology e prova a monitorare
# il PRIMARY tramite l'hostname annunciato (mongodb-tenant-0.<headless>): la
# connessione di monitoring si chiude e ogni comando fallisce con
# "connection <monitor> closed". directConnection forza la sessione sul solo
# 127.0.0.1, restando compatibile con la localhost exception.
MONGO_TLS_ARGS=('mongodb://127.0.0.1:27017/?directConnection=true&tls=true&tlsCAFile=/etc/mongo-tls/ca.crt&tlsAllowInvalidHostnames=true')
mongo_eval() {
# Localhost exception: usabile solo prima della creazione del primo utente.
@@ -358,16 +364,22 @@ done
render "$TEMPLATES_DIR/04-mongodb.yaml" | kc_cluster apply -f -
log " Attendo che $POD0 sia Ready (timeout 10 min — il provisioning PVC+attach può essere lento)"
# kubectl wait sfrutta direttamente la readiness probe del pod. Dieci minuti
log " Attendo che i 3 membri ($POD0, $POD1, $POD2) siano Ready (timeout 10 min — il provisioning PVC+attach può essere lento)"
# kubectl wait sfrutta direttamente la readiness probe dei pod. Dieci minuti
# coprono provisioning PVC + attach + boot Mongo anche su CSI lenti (vSphere,
# Scaleway block storage in cold start, ecc.).
if ! kc wait "pod/$POD0" --for=condition=Ready --timeout=600s 2>&1; then
err "$POD0 non è Ready dopo 10 minuti. Diagnostica:
# IMPORTANTE: aspettiamo TUTTI e 3 i pod, non solo pod-0. Il record DNS per-pod
# del service headless (es. mongodb-tenant-1.<headless>) viene pubblicato solo
# quando il pod è Ready: lanciare rs.initiate con il solo pod-0 pronto fa fallire
# il quorum check con "Could not find address for mongodb-tenant-1...". Questo
# accade quando pod-0 parte veloce e 1/2 sono ancora in provisioning PVC.
if ! kc wait "pod/$POD0" "pod/$POD1" "pod/$POD2" --for=condition=Ready --timeout=600s 2>&1; then
err "Uno dei pod mongodb-tenant-{0,1,2} non è Ready dopo 10 minuti. Diagnostica:
kubectl --context '$CONTEXT' -n '$NAMESPACE' get pods
kubectl --context '$CONTEXT' -n '$NAMESPACE' describe pod $POD0
kubectl --context '$CONTEXT' -n '$NAMESPACE' logs $POD0 -c mongodb"
fi
ok "$POD0 pronto"
ok "I 3 membri del replica set sono Ready"
# -----------------------------------------------------------------------------
# Init replica set + utenti
@@ -398,8 +410,9 @@ EOF
STATE=$(echo "try { print('@@RES@@' + rs.status().members.find(m=>m.self).stateStr) } catch(e) { print('@@RES@@') }" | mongo_get)
[[ "$STATE" == *"PRIMARY"* ]] && { ok "$POD0 è PRIMARY"; break; }
[[ $i -eq 150 ]] && err "Nessun PRIMARY eletto entro 5 minuti.
Diagnostica: kc exec $POD0 -c mongodb -- mongosh --tls --tlsCAFile /etc/mongo-tls/ca.crt \\
--tlsAllowInvalidHostnames --host 127.0.0.1 --eval 'rs.status()'"
Diagnostica: kc exec $POD0 -c mongodb -- mongosh --quiet \\
'mongodb://127.0.0.1:27017/?directConnection=true&tls=true&tlsCAFile=/etc/mongo-tls/ca.crt&tlsAllowInvalidHostnames=true' \\
--eval 'rs.status()'"
sleep 2
done
else
@@ -516,7 +529,8 @@ echo "Verifiche:"
echo " kc get all"
echo " kc logs deploy/tenant-api --tail=100 -f"
echo " # Per rs.status() recupera la root password da $CREDS_FILE:"
echo " kc exec $POD0 -c mongodb -- mongosh \\"
echo " kc exec $POD0 -c mongodb -- mongosh --quiet \\"
echo " 'mongodb://127.0.0.1:27017/?directConnection=true&tls=true&tlsCAFile=/etc/mongo-tls/ca.crt&tlsAllowInvalidHostnames=true' \\"
echo " -u '$ROOT_USER' -p \"\$MONGO_ROOT_PASSWORD\" --authenticationDatabase admin \\"
echo " --eval 'rs.status()'"
echo