# ============================================================================= # P4.9 — runtime-saude — saude, nutricao, assistencia-social, pedagogico # # `{{TENANT}}` e substituido pelo nome do tenant ao provisionar. O molde inteiro usa # o mesmo marcador, para `sed`/script nao precisarem conhecer cada arquivo. # ============================================================================= apiVersion: apps/v1 kind: Deployment metadata: name: runtime-saude namespace: {{TENANT}}-prod spec: replicas: 1 selector: matchLabels: { app: runtime-saude } template: metadata: labels: app: runtime-saude athleticmap.io/contexto: runtime-saude spec: # Espera o LOGIN no banco do tenant funcionar antes de subir o runtime. # O Argo aplica este Deployment ANTES de a etapa BANCO_CRIADO criar o papel # e a linha no PgBouncer. Sem esta espera o runtime cai na subida, e o # Kubernetes o religa com espera crescente (10 s, 20 s, 40 s, 80 s...): # era isso que levava a etapa MIGRACOES_CONCLUIDAS a 4-5 min (P4.9). # Aqui o laco e de 2 s e nao ha queda — o runtime sobe logo que o banco existe. initContainers: - name: espera-banco image: docker.io/library/postgres:16 imagePullPolicy: Never command: ["sh", "-c"] args: - | n=0 until psql "host=pgbouncer.plataforma-prod.svc port=6432 dbname=athleticmap_{{TENANT}} user=r_{{TENANT}} connect_timeout=3" -Atc 'select 1' >/dev/null 2>&1; do n=$((n+1)); [ $((n % 15)) -eq 0 ] && echo "ainda sem o banco do tenant ($((n*2)) s)" sleep 2 done echo "banco pronto" env: - name: PGPASSWORD valueFrom: secretKeyRef: { name: db-credentials, key: password } resources: requests: { cpu: 10m, memory: 16Mi } limits: { cpu: 100m, memory: 64Mi } containers: - name: runtime-saude image: docker.io/library/runtime-saude:1.13-sem-fed-admin # `Never`: a imagem tem de estar no containerd do no ANTES do deploy. # "Presente no no" tambem nao e "atual" — conferir a TAG, e nao o nome. imagePullPolicy: Never ports: [{ containerPort: 8083 }] env: # O banco e o PgBouncer do `plataforma-prod` (P4.7), e nao um # Postgres deste namespace: ele nao existe mais aqui. - { name: SPRING_DATASOURCE_URL, value: "jdbc:postgresql://pgbouncer.plataforma-prod.svc:6432/athleticmap_{{TENANT}}" } - { name: SPRING_DATASOURCE_USERNAME, value: "r_{{TENANT}}" } - name: SPRING_DATASOURCE_PASSWORD valueFrom: secretKeyRef: { name: db-credentials, key: password } # O Keycloak tambem e da plataforma (P4.8). O REALM passa a ser o # nome do tenant: uma instancia so nao comporta quatro realms # chamados `athleticmap`. - { name: ATM_JWK_SET_URI, value: "http://keycloak.plataforma-prod.svc:8080/realms/{{REALM}}/protocol/openid-connect/certs" } - { name: ATM_ISSUER, value: "https://auth.athleticmap.com/realms/{{REALM}}" } - { name: ATM_TENANT, value: "{{TENANT}}" } - { name: ATM_PLANO, value: "{{PLANO}}" } # Retencao da trilha de auditoria. O expurgo roda agendado DENTRO # deste runtime — ver RuntimeSaude. # Cifra dos tokens Garmin (RIPD R5, 2026-09-29). Sem o Secret a integracao # Garmin fica DESLIGADA e o runtime sobe normalmente. O provisionamento # ainda NAO sela este Secret: tenant novo precisa dele a mao (pendencia). - name: ATM_GARMIN_TOKEN_CHAVE valueFrom: secretKeyRef: { name: garmin-token-chave, key: chave, optional: true } # 5 anos (P6.3/P6.4, decisao do dono 2026-09-28); era 730. - { name: ATM_AUDITORIA_RETENCAO_DIAS, value: "1825" } resources: requests: { cpu: 50m, memory: 384Mi } limits: { cpu: "1", memory: 768Mi } readinessProbe: httpGet: { path: /actuator/health/readiness, port: 8083 } initialDelaySeconds: 20 periodSeconds: 10 livenessProbe: httpGet: { path: /actuator/health/liveness, port: 8083 } initialDelaySeconds: 60 periodSeconds: 30 --- apiVersion: v1 kind: Service metadata: name: runtime-saude namespace: {{TENANT}}-prod labels: app: runtime-saude athleticmap.io/metricas: tenant spec: selector: { app: runtime-saude } ports: [{ name: http, port: 80, targetPort: 8083 }]