diff --git a/README.md b/README.md index 48c115b..0d46113 100644 --- a/README.md +++ b/README.md @@ -49,6 +49,30 @@ tenant, los placeholders en mayúsculas se sustituyen automáticamente. --- +## Orden de hooks Helm + +El chart usa hooks `pre-install,pre-upgrade` con `hook-weight` para garantizar +el orden de creación. El `helm upgrade --install` funciona **sin `--no-hooks`**: + +| Recurso | Template | `hook-weight` | Motivo | +|---------|----------|---------------|--------| +| `ServiceAccount` | `serviceaccount.yaml` | `-5` | Lo referencia el pod del Job Alembic — debe existir antes | +| `Job` Alembic | `job-alembic-upgrade.yaml` | `0` | Corre `alembic upgrade head` antes de rolar el Deployment | + +El `ServiceAccount` se materializa como hook (no en la fase principal de Helm) +porque el Job Alembic, que también es hook, declara `serviceAccountName`. Si el +SA viviera en la fase principal se crearía **después** del Job → el pod del Job +nunca arrancaría (`serviceaccount not found`) → `helm --wait` haría timeout. + +El SA-hook usa `hook-delete-policy: before-hook-creation` (no `hook-succeeded`): +el Deployment lo necesita vivo en runtime, así que solo se borra/recrea al +inicio del siguiente hook, manteniéndolo idempotente entre upgrades. + +El `imagePullSecret` y el Secret `-db-creds` que referencia el Job los +provee la plataforma (stack-deployer / addon), no el chart. + +--- + ## Endpoints obligatorios | Path | Auth | Propósito | diff --git a/helm/APP_NAME/templates/deployment.yaml b/helm/APP_NAME/templates/deployment.yaml index 526a88e..6226c3c 100644 --- a/helm/APP_NAME/templates/deployment.yaml +++ b/helm/APP_NAME/templates/deployment.yaml @@ -67,13 +67,11 @@ spec: - name: tmp emptyDir: {} --- -apiVersion: v1 -kind: ServiceAccount -metadata: - name: {{ .Release.Name }} - labels: - {{- include "app.labels" . | nindent 4 }} ---- +# El ServiceAccount {{ .Release.Name }} NO se define aqui — vive en +# serviceaccount.yaml como hook pre-install/pre-upgrade (hook-weight "-5") para +# garantizar que exista antes del Job Alembic. El Deployment lo referencia en +# `serviceAccountName` y el SA-hook usa `hook-delete-policy: before-hook-creation` +# para no quedar huerfano entre upgrades. apiVersion: v1 kind: ConfigMap metadata: diff --git a/helm/APP_NAME/templates/serviceaccount.yaml b/helm/APP_NAME/templates/serviceaccount.yaml new file mode 100644 index 0000000..73f4778 --- /dev/null +++ b/helm/APP_NAME/templates/serviceaccount.yaml @@ -0,0 +1,24 @@ +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ .Release.Name }} + labels: + {{- include "app.labels" . | nindent 4 }} + annotations: + # El ServiceAccount se materializa como hook pre-install/pre-upgrade para + # romper el chicken-and-egg con el Job Alembic: + # - El Job (job-alembic-upgrade.yaml) corre como hook pre-install/pre-upgrade + # con hook-weight "0" y declara `serviceAccountName: {{ .Release.Name }}`. + # - Si el SA viviera en la fase principal de Helm se crearía DESPUES del + # hook → el pod del Job nunca arranca ("serviceaccount not found") → + # `helm --wait` hace timeout → `helm install` falla. + # Solucion: el SA es hook con hook-weight "-5" (< "0" del Job) → Helm lo + # aplica antes que el Job. Asi `helm upgrade --install` funciona sin + # `--no-hooks`. + "helm.sh/hook": pre-install,pre-upgrade + "helm.sh/hook-weight": "-5" + # before-hook-creation (NO hook-succeeded): el Deployment de la fase + # principal referencia este SA en runtime — debe seguir vivo tras el hook. + # before-hook-creation lo borra y recrea solo al inicio del proximo hook, + # haciendo el SA-hook idempotente entre upgrades sin dejarlo huerfano. + "helm.sh/hook-delete-policy": before-hook-creation