feat(plataforma): infraestrutura da etapa BANCO_CRIADO

RBAC amarrado por resourceNames (db-credentials nos tenants, pgbouncer-userlist
so aqui), netpol do PgBouncer por ROTULO em vez de por nome, e a credencial de
administracao do Postgres compartilhado para o servico-captacao.
This commit is contained in:
deploy
2026-09-24 21:36:33 +00:00
parent 642e091641
commit 85ee182b43
3 changed files with 79 additions and 0 deletions
@@ -31,5 +31,21 @@ spec:
matchLabels: { kubernetes.io/metadata.name: piloto-prod }
- namespaceSelector:
matchLabels: { kubernetes.io/metadata.name: acme-prod }
# Todo tenant PROVISIONADO, por rotulo e nao por nome.
#
# Os tres acima foram criados a mao e nao tem o rotulo; os novos nascem
# com `athleticmap.io/tenant` no proprio molde do namespace. Enumerar
# nomes aqui significaria editar esta politica a cada venda — e esquecer
# de editar da um tenant que sobe inteiro e nao conecta no banco, com
# `connection timed out` e nenhuma pista de que a culpa e de rede.
- namespaceSelector:
matchExpressions:
- { key: athleticmap.io/tenant, operator: Exists }
# O provisionamento, que CONFERE o pool antes de dar a etapa por feita.
# So o pod do servico-captacao, e nao o namespace inteiro.
- namespaceSelector:
matchLabels: { kubernetes.io/metadata.name: plataforma-prod }
podSelector:
matchLabels: { app: servico-captacao }
ports:
- { protocol: TCP, port: 6432 }
@@ -52,3 +52,48 @@ rules:
- apiGroups: ["apps"]
resources: ["deployments/scale"]
verbs: ["get", "patch"]
# A senha do papel do tenant no Postgres.
#
# Ela e gerada em MEMORIA pela etapa de selagem, selada e zerada na mesma
# linha — em claro ela nunca encosta em disco nosso. Depois que o Argo aplica
# o SealedSecret, o Secret aberto e o unico lugar de onde da para le-la, e a
# etapa BANCO_CRIADO precisa dela para dar a senha ao papel.
#
# `resourceNames` amarra ao NOME: este ClusterRole nao le `asaas-credentials`
# nem nenhum outro Secret do cliente. E o RoleBinding do molde o limita aos
# namespaces de tenant — nao ha binding cluster-wide.
- apiGroups: [""]
resources: ["secrets"]
verbs: ["get"]
resourceNames: ["db-credentials"]
---
# O userlist do PgBouncer, que a etapa BANCO_CRIADO acrescenta.
#
# Role, e nao ClusterRole: este Secret vive so aqui. E `resourceNames` de novo,
# porque `plataforma-prod` guarda a chave do Asaas, o token do webhook e a
# credencial do Gitea — nenhuma delas tem nada a ver com criar banco de cliente.
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: atm-provisionamento-userlist
namespace: plataforma-prod
rules:
- apiGroups: [""]
resources: ["secrets"]
verbs: ["get"]
resourceNames: ["pgbouncer-userlist"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: atm-provisionamento-userlist
namespace: plataforma-prod
subjects:
- kind: ServiceAccount
name: atm-provisionamento
namespace: plataforma-prod
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: atm-provisionamento-userlist
@@ -235,6 +235,24 @@ spec:
# O molde do realm. Sem ele a etapa recusa nomeando a propriedade; o
# arquivo vive no mesmo clone do GitOps que o /gitops monta.
- { name: PROVISIONAMENTO_REALM_TEMPLATE, value: "/gitops/moldes/realm-do-tenant.json" }
# ── o banco do cliente novo (etapa BANCO_CRIADO) ──────────────
#
# DIRETO no pg-compartilhado, e nao pelo PgBouncer: o pool so serve
# databases que ja estao na lista dele, e aqui o database ainda NAO
# existe. E a netpol egress-banco-compartilhado ja permite os dois.
- { name: PROVISIONAMENTO_PG_ADMIN_URL, value: "jdbc:postgresql://pg-compartilhado:5432/{database}" }
- { name: PROVISIONAMENTO_PG_ADMIN_USUARIO, value: "postgres" }
- name: PROVISIONAMENTO_PG_ADMIN_SENHA
valueFrom:
secretKeyRef: { name: pg-compartilhado-admin, key: password }
# As etapas de migracao e de catalogos, que conectam num banco que JA
# existe. Tambem direto: elas rodam com a conta de administracao, e
# passar pelo pool so acrescentaria uma peca ao caminho.
- { name: PROVISIONAMENTO_BANCO_URL, value: "jdbc:postgresql://pg-compartilhado:5432/athleticmap_{tenant}" }
- { name: PROVISIONAMENTO_BANCO_USUARIO, value: "postgres" }
- name: PROVISIONAMENTO_BANCO_SENHA
valueFrom:
secretKeyRef: { name: pg-compartilhado-admin, key: password }
resources:
requests: { cpu: 150m, memory: 320Mi }
limits: { cpu: "1", memory: 768Mi }