706a6e67ab
Cliente: Teste5 Assinatura: sub_zx7fdtz40b8is2gk Plano: (nao informado) Realm: athleticmap-9 Gerado pelo provisionamento automatico (P5.2/P5.3) a partir do molde consolidado de P4.9. O ApplicationSet cria a Application sozinho pelo gerador de diretorio sobre tenants/*.
177 lines
7.4 KiB
YAML
177 lines
7.4 KiB
YAML
# =============================================================================
|
|
# P4.9 — o molde consolidado: 4 Deployments no lugar de 15.
|
|
#
|
|
# ── POR QUE FORA DE `tenants/` ───────────────────────────────────────────────
|
|
#
|
|
# O ApplicationSet do ArgoCD tem um gerador de diretorio sobre `tenants/*`. Uma
|
|
# pasta de MOLDE ali dentro seria tratada como tenant e implantada — com nome de
|
|
# namespace de mentira e tudo. Por isso os moldes vivem em `moldes/`, que o
|
|
# gerador nao enxerga.
|
|
#
|
|
# `scripts/provisionar_tenant.py` procura o molde em `tenants/<nome>`: ele
|
|
# precisa aprender este caminho novo. Esta no diario.
|
|
#
|
|
# ── A COTA, COM OS NUMEROS MEDIDOS ───────────────────────────────────────────
|
|
#
|
|
# Hoje, um tenant (`escolinha`, medido em 2026-09-18): **5253 Mi em 18 pods**.
|
|
#
|
|
# Com a consolidacao, medido container a container no mesmo dia:
|
|
#
|
|
# runtime-core 384 MiB
|
|
# runtime-operacao 403 MiB
|
|
# runtime-saude 366 MiB
|
|
# frontend-spa 24 MiB
|
|
# ----------------------------
|
|
# soma 1.177 MiB
|
|
#
|
|
# OS NUMEROS DA TABELA ACIMA SAO DE QUANDO ERAM QUATRO DEPLOYMENTS. Hoje sao
|
|
# cinco (o `servico-bff` entrou em 2026-09-24), e os tetos ja viveram duas
|
|
# correcoes: requests.memory 1.5Gi -> 2Gi, limits.memory 2.5Gi -> 3.5Gi ->
|
|
# 4352Mi, pods 8 -> 10. A razao de cada valor esta ao lado dele, la embaixo.
|
|
#
|
|
# A REGRA QUE VALE PARA TODOS: a cota tem de caber o REPOUSO MAIS UMA TROCA.
|
|
# Um Deployment sobe o pod novo ANTES de derrubar o velho, entao no pico existe
|
|
# um pod a mais do que o desenho sugere -- e o `maxSurge: 25%` sobre uma unica
|
|
# replica arredonda para cima, ou seja, sempre um inteiro.
|
|
#
|
|
# Ja custou duas vezes, pela mesma causa em dimensoes diferentes: derrubou o
|
|
# provisionamento do `plataforma` em 2026-09-17 (faltou `pods`), e prendeu os
|
|
# dois tenants pagos por 12h em 2026-09-24 (faltou `limits.memory`), com o
|
|
# ArgoCD dizendo "Synced" enquanto o pod novo era recusado pela cota.
|
|
#
|
|
#
|
|
# NAO ha Postgres nem Keycloak aqui: os dois passam a viver em `plataforma-prod`
|
|
# (P4.7 e P4.8).
|
|
# =============================================================================
|
|
apiVersion: v1
|
|
kind: Namespace
|
|
metadata:
|
|
name: teste5-prod
|
|
labels:
|
|
kubernetes.io/metadata.name: teste5-prod
|
|
athleticmap.io/tenant: teste5
|
|
---
|
|
apiVersion: v1
|
|
kind: ResourceQuota
|
|
metadata:
|
|
name: cota
|
|
namespace: teste5-prod
|
|
spec:
|
|
hard:
|
|
# SUBIU em 2026-09-24 para caber o BFF, o quinto Deployment.
|
|
#
|
|
# Nao e folga generosa: com quatro Deployments o tenant ja usava 1232Mi dos
|
|
# 1536Mi, e o BFF pede 256Mi. Caberia no limite antigo em repouso, e
|
|
# estouraria no primeiro rollout — que e quando um Deployment sobe o pod
|
|
# novo antes de derrubar o velho. Foi essa conta que derrubou o
|
|
# provisionamento do `plataforma` em 17/09, e o registro dela esta ali.
|
|
#
|
|
# `pods` vai a 10 pelo mesmo motivo: cinco Deployments, um surge cada.
|
|
requests.cpu: "1.5"
|
|
requests.memory: 2Gi
|
|
limits.cpu: "5"
|
|
# SUBIU de 3.5Gi em 2026-09-25: faltava por 128Mi na hora da troca.
|
|
#
|
|
# A conta que o comentario acima comecou, agora terminada. Em repouso os
|
|
# cinco Deployments somam 2944Mi (128 + 768*3 + 512). O `maxSurge: 25%` sobre
|
|
# UMA replica arredonda para cima e pede um pod inteiro a mais: 768Mi, se o
|
|
# que esta trocando e um runtime. 2944 + 768 = 3712, contra um teto de 3584.
|
|
#
|
|
# Nao foi hipotese: os dois tenants pagos ficaram 12h presos em `1.1-demo`
|
|
# sem conseguir ir para `1.2-auditoria`, com o ArgoCD dizendo "Synced" e o
|
|
# pod novo recusado pela cota a cada ~17min.
|
|
#
|
|
# 4352Mi = 2944 de repouso + 768 da troca + 640 de sobra.
|
|
#
|
|
# So `limits.memory` travava. Medido em 2026-09-25: requests.memory tinha
|
|
# 560Mi livres (a troca pede 400), requests.cpu 1100m (pede 100), limits.cpu
|
|
# 1300m (pede 1000) e pods 5 de 10. Subir a memoria basta.
|
|
limits.memory: 4352Mi
|
|
pods: "10"
|
|
---
|
|
# =============================================================================
|
|
# A politica de rede.
|
|
#
|
|
# ── O QUE MUDOU EM RELACAO AO MOLDE ANTIGO ──────────────────────────────────
|
|
#
|
|
# O `deny-cross-tenant` antigo liberava egress para `ipBlock: 10.43.0.0/16` — a
|
|
# CIDR de Services do cluster INTEIRO. Era mais largo do que o nome dizia: um pod
|
|
# de qualquer tenant alcancava, pela rede, o ClusterIP de qualquer outro.
|
|
#
|
|
# Aqui o egress interno e nominal: DNS, os pods do proprio namespace, e o
|
|
# namespace `plataforma-prod` nas portas que importam.
|
|
#
|
|
# ── O QUE NAO FOI POSSIVEL, E O MOTIVO E O CNI ──────────────────────────────
|
|
#
|
|
# O card pede "egress so ... os destinos externos reais (Asaas, provedor fiscal,
|
|
# Garmin) — nada de egress irrestrito".
|
|
#
|
|
# **Nao da com o CNI deste cluster.** Conferido em 2026-09-19: k3s com flannel
|
|
# embutido, sem Cilium e sem Calico (nenhum CRD dos dois). NetworkPolicy padrao
|
|
# do Kubernetes so aceita `ipBlock` — CIDR, nao nome. E Asaas, provedor fiscal e
|
|
# Garmin sao SaaS atras de CDN: os IPs mudam, e uma lista de CIDR quebraria a
|
|
# cobranca sem aviso, num dia qualquer.
|
|
#
|
|
# Entao a regra de 443 continua, e continua sendo egress irrestrito para a
|
|
# internet. O `except` preserva o que a politica de fato protege: um tenant nao
|
|
# alcanca a rede interna do outro.
|
|
#
|
|
# **O caminho para fechar isso de verdade** esta no diario: um proxy de saida no
|
|
# `plataforma-prod`, com lista de hosts permitidos, e os tenants alcancando so
|
|
# ele. Funciona com flannel, e nao exige trocar o CNI.
|
|
# =============================================================================
|
|
apiVersion: networking.k8s.io/v1
|
|
kind: NetworkPolicy
|
|
metadata:
|
|
name: deny-cross-tenant
|
|
namespace: teste5-prod
|
|
spec:
|
|
podSelector: {}
|
|
policyTypes: [Ingress, Egress]
|
|
ingress:
|
|
- from:
|
|
- podSelector: {} # mesma namespace
|
|
- namespaceSelector:
|
|
matchLabels:
|
|
kubernetes.io/metadata.name: kube-system # Traefik (ingress)
|
|
egress:
|
|
# 1. Dentro do proprio namespace.
|
|
- to:
|
|
- podSelector: {}
|
|
|
|
# 2. DNS.
|
|
- to:
|
|
- namespaceSelector:
|
|
matchLabels:
|
|
kubernetes.io/metadata.name: kube-system
|
|
ports:
|
|
- { protocol: UDP, port: 53 }
|
|
- { protocol: TCP, port: 53 }
|
|
|
|
# 3. A plataforma: banco e identidade, so nas portas que importam.
|
|
#
|
|
# 5432 direto no Postgres e para o `pg_dump` do backup: ele abre uma
|
|
# transacao unica e longa, o oposto do que transaction pooling serve.
|
|
# 6432 e o PgBouncer, por onde os runtimes falam.
|
|
# 8080 e o Keycloak (P4.8).
|
|
- to:
|
|
- namespaceSelector:
|
|
matchLabels:
|
|
kubernetes.io/metadata.name: plataforma-prod
|
|
ports:
|
|
- { protocol: TCP, port: 5432 }
|
|
- { protocol: TCP, port: 6432 }
|
|
- { protocol: TCP, port: 8080 }
|
|
|
|
# 4. HTTPS para a internet publica. Ver o cabecalho: nao da para estreitar
|
|
# com flannel, e uma lista de CIDR de SaaS quebraria a cobranca sem aviso.
|
|
#
|
|
# O `except` e o que a politica de fato garante: nenhum tenant alcanca a
|
|
# rede interna de outro por este caminho.
|
|
- to:
|
|
- ipBlock:
|
|
cidr: 0.0.0.0/0
|
|
except: [10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16]
|
|
ports:
|
|
- { protocol: TCP, port: 443 }
|