feat(plataforma,tenants): coleta de metricas e permissao do provisionamento

This commit is contained in:
deploy
2026-09-21 02:30:31 +00:00
parent aec24e06c3
commit 1ed00120c0
12 changed files with 307 additions and 45 deletions
@@ -0,0 +1,22 @@
# =============================================================================
# P5.6/P5.9 — a plataforma pode esperar rollout e suspender ESTE tenant.
#
# O ClusterRole (`atm-provisionamento-tenants`, em
# `tenants/plataforma/16-rbac-provisionamento.yaml`) e so a lista de verbos;
# quem concede e este RoleBinding, e ele vale SO neste namespace. Um tenant sem
# este arquivo simplesmente nao e alcancado pelo provisionamento — a etapa falha
# com 403 dizendo o caminho que tentou, que e melhor do que um acesso amplo.
# =============================================================================
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: atm-provisionamento
namespace: acme-prod
subjects:
- kind: ServiceAccount
name: atm-provisionamento
namespace: plataforma-prod
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: atm-provisionamento-tenants
+25 -4
View File
@@ -1,13 +1,34 @@
# Permite o namespace 'monitoring' (Prometheus) raspar o backend (porta 8083). Additivo a deny-cross-tenant.
# =============================================================================
# Deixa o Prometheus raspar as metricas deste tenant.
#
# Aditivo a `deny-cross-tenant` (em `00-namespace-quota-netpol.yaml`), que fecha
# ingresso de fora do namespace. Sem esta politica o tenant sobe, funciona e fica
# INVISIVEL no Grafana — e um tenant sem metrica e um tenant em que ninguem
# percebe consumo subindo nem pod reiniciando.
#
# ── POR QUE `podSelector: {}` (2026-09-20) ──────────────────────────────────
#
# Antes a politica citava pods por NOME (`app: backend`, ou uma lista). Resultado:
# quando o `ServiceMonitor` passou a raspar os runtimes e os 13 servicos, TODOS os
# alvos novos ficaram `up=0` e o cluster acendeu 48 alertas de `TargetDown` — a
# coleta chegava ao Service e morria na rede.
#
# Lista de nomes aqui e a mesma lista do `ServiceMonitor` escrita duas vezes, em
# lugares diferentes, com o erro aparecendo so em producao. Agora vale para
# qualquer pod DESTE namespace, e a fronteira e a mesma de antes:
#
# - SO a porta 8083, que e a das metricas (`/actuator/prometheus`);
# - SO do namespace `monitoring`.
#
# O `frontend-spa` escuta na 80 e continua fora, sem precisar ser citado.
# =============================================================================
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-monitoring
namespace: acme-prod
spec:
podSelector:
matchLabels:
app: backend
podSelector: {}
policyTypes: [Ingress]
ingress:
- from:
@@ -0,0 +1,22 @@
# =============================================================================
# P5.6/P5.9 — a plataforma pode esperar rollout e suspender ESTE tenant.
#
# O ClusterRole (`atm-provisionamento-tenants`, em
# `tenants/plataforma/16-rbac-provisionamento.yaml`) e so a lista de verbos;
# quem concede e este RoleBinding, e ele vale SO neste namespace. Um tenant sem
# este arquivo simplesmente nao e alcancado pelo provisionamento — a etapa falha
# com 403 dizendo o caminho que tentou, que e melhor do que um acesso amplo.
# =============================================================================
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: atm-provisionamento
namespace: demo-prod
subjects:
- kind: ServiceAccount
name: atm-provisionamento
namespace: plataforma-prod
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: atm-provisionamento-tenants
+25 -4
View File
@@ -1,13 +1,34 @@
# Permite o namespace 'monitoring' (Prometheus) raspar o backend (porta 8083). Additivo a deny-cross-tenant.
# =============================================================================
# Deixa o Prometheus raspar as metricas deste tenant.
#
# Aditivo a `deny-cross-tenant` (em `00-namespace-quota-netpol.yaml`), que fecha
# ingresso de fora do namespace. Sem esta politica o tenant sobe, funciona e fica
# INVISIVEL no Grafana — e um tenant sem metrica e um tenant em que ninguem
# percebe consumo subindo nem pod reiniciando.
#
# ── POR QUE `podSelector: {}` (2026-09-20) ──────────────────────────────────
#
# Antes a politica citava pods por NOME (`app: backend`, ou uma lista). Resultado:
# quando o `ServiceMonitor` passou a raspar os runtimes e os 13 servicos, TODOS os
# alvos novos ficaram `up=0` e o cluster acendeu 48 alertas de `TargetDown` — a
# coleta chegava ao Service e morria na rede.
#
# Lista de nomes aqui e a mesma lista do `ServiceMonitor` escrita duas vezes, em
# lugares diferentes, com o erro aparecendo so em producao. Agora vale para
# qualquer pod DESTE namespace, e a fronteira e a mesma de antes:
#
# - SO a porta 8083, que e a das metricas (`/actuator/prometheus`);
# - SO do namespace `monitoring`.
#
# O `frontend-spa` escuta na 80 e continua fora, sem precisar ser citado.
# =============================================================================
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-monitoring
namespace: demo-prod
spec:
podSelector:
matchLabels:
app: backend
podSelector: {}
policyTypes: [Ingress]
ingress:
- from:
@@ -0,0 +1,22 @@
# =============================================================================
# P5.6/P5.9 — a plataforma pode esperar rollout e suspender ESTE tenant.
#
# O ClusterRole (`atm-provisionamento-tenants`, em
# `tenants/plataforma/16-rbac-provisionamento.yaml`) e so a lista de verbos;
# quem concede e este RoleBinding, e ele vale SO neste namespace. Um tenant sem
# este arquivo simplesmente nao e alcancado pelo provisionamento — a etapa falha
# com 403 dizendo o caminho que tentou, que e melhor do que um acesso amplo.
# =============================================================================
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: atm-provisionamento
namespace: escolinha-prod
subjects:
- kind: ServiceAccount
name: atm-provisionamento
namespace: plataforma-prod
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: atm-provisionamento-tenants
+25 -4
View File
@@ -1,13 +1,34 @@
# Permite o namespace 'monitoring' (Prometheus) raspar o backend (porta 8083). Additivo a deny-cross-tenant.
# =============================================================================
# Deixa o Prometheus raspar as metricas deste tenant.
#
# Aditivo a `deny-cross-tenant` (em `00-namespace-quota-netpol.yaml`), que fecha
# ingresso de fora do namespace. Sem esta politica o tenant sobe, funciona e fica
# INVISIVEL no Grafana — e um tenant sem metrica e um tenant em que ninguem
# percebe consumo subindo nem pod reiniciando.
#
# ── POR QUE `podSelector: {}` (2026-09-20) ──────────────────────────────────
#
# Antes a politica citava pods por NOME (`app: backend`, ou uma lista). Resultado:
# quando o `ServiceMonitor` passou a raspar os runtimes e os 13 servicos, TODOS os
# alvos novos ficaram `up=0` e o cluster acendeu 48 alertas de `TargetDown` — a
# coleta chegava ao Service e morria na rede.
#
# Lista de nomes aqui e a mesma lista do `ServiceMonitor` escrita duas vezes, em
# lugares diferentes, com o erro aparecendo so em producao. Agora vale para
# qualquer pod DESTE namespace, e a fronteira e a mesma de antes:
#
# - SO a porta 8083, que e a das metricas (`/actuator/prometheus`);
# - SO do namespace `monitoring`.
#
# O `frontend-spa` escuta na 80 e continua fora, sem precisar ser citado.
# =============================================================================
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-monitoring
namespace: escolinha-prod
spec:
podSelector:
matchLabels:
app: backend
podSelector: {}
policyTypes: [Ingress]
ingress:
- from:
@@ -0,0 +1,22 @@
# =============================================================================
# P5.6/P5.9 — a plataforma pode esperar rollout e suspender ESTE tenant.
#
# O ClusterRole (`atm-provisionamento-tenants`, em
# `tenants/plataforma/16-rbac-provisionamento.yaml`) e so a lista de verbos;
# quem concede e este RoleBinding, e ele vale SO neste namespace. Um tenant sem
# este arquivo simplesmente nao e alcancado pelo provisionamento — a etapa falha
# com 403 dizendo o caminho que tentou, que e melhor do que um acesso amplo.
# =============================================================================
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: atm-provisionamento
namespace: piloto-prod
subjects:
- kind: ServiceAccount
name: atm-provisionamento
namespace: plataforma-prod
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: atm-provisionamento-tenants
+25 -4
View File
@@ -1,13 +1,34 @@
# Permite o namespace 'monitoring' (Prometheus) raspar o backend (porta 8083). Additivo a deny-cross-tenant.
# =============================================================================
# Deixa o Prometheus raspar as metricas deste tenant.
#
# Aditivo a `deny-cross-tenant` (em `00-namespace-quota-netpol.yaml`), que fecha
# ingresso de fora do namespace. Sem esta politica o tenant sobe, funciona e fica
# INVISIVEL no Grafana — e um tenant sem metrica e um tenant em que ninguem
# percebe consumo subindo nem pod reiniciando.
#
# ── POR QUE `podSelector: {}` (2026-09-20) ──────────────────────────────────
#
# Antes a politica citava pods por NOME (`app: backend`, ou uma lista). Resultado:
# quando o `ServiceMonitor` passou a raspar os runtimes e os 13 servicos, TODOS os
# alvos novos ficaram `up=0` e o cluster acendeu 48 alertas de `TargetDown` — a
# coleta chegava ao Service e morria na rede.
#
# Lista de nomes aqui e a mesma lista do `ServiceMonitor` escrita duas vezes, em
# lugares diferentes, com o erro aparecendo so em producao. Agora vale para
# qualquer pod DESTE namespace, e a fronteira e a mesma de antes:
#
# - SO a porta 8083, que e a das metricas (`/actuator/prometheus`);
# - SO do namespace `monitoring`.
#
# O `frontend-spa` escuta na 80 e continua fora, sem precisar ser citado.
# =============================================================================
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-monitoring
namespace: piloto-prod
spec:
podSelector:
matchLabels:
app: backend
podSelector: {}
policyTypes: [Ingress]
ingress:
- from:
@@ -0,0 +1,54 @@
# =============================================================================
# P5.6/P5.9 — a permissao que o provisionamento precisa nos tenants.
#
# ── O QUE O CODIGO FAZ (e nada alem disso) ──────────────────────────────────
#
# `ApiDoKubernetes`, no `servico-captacao`, faz exatamente duas coisas com o
# token do proprio pod:
#
# GET /apis/apps/v1/namespaces/<tenant>-prod/deployments/<nome>
# — esperar o rollout do tenant novo terminar (P5.6);
# PATCH /apis/apps/v1/namespaces/<tenant>-prod/deployments/<nome>/scale
# — suspender o cliente inadimplente, zerando replicas (P5.9).
#
# Sem estas regras a etapa falha com 403. No caso da suspensao, o 403 vem DEPOIS
# de o realm ja ter sido desligado: o cliente fica bloqueado com os pods de pe —
# gasta memoria, mas nenhum dado corre risco — e o evento fica FALHOU ate a
# permissao existir.
#
# ── POR QUE ClusterRole + RoleBinding, E NAO ClusterRoleBinding ─────────────
#
# O ClusterRole aqui e so a LISTA de verbos (um ClusterRole sem binding nao da
# acesso a nada). Quem concede e o RoleBinding, que vive DENTRO do namespace do
# tenant — um por tenant, em `tenants/<tenant>/16-rolebinding-provisionamento.yaml`.
# Com um ClusterRoleBinding, a plataforma passaria a ler e escalar Deployment de
# QUALQUER namespace, inclusive `kube-system` e `argocd`.
#
# Tenant novo entra pelo molde consolidado, que ja traz o RoleBinding.
#
# ── A ServiceAccount ────────────────────────────────────────────────────────
#
# Dedicada. Ate aqui o `servico-captacao` rodava com a `default` do namespace, e
# dar poder a `default` significa dar poder a QUALQUER pod que suba sem
# `serviceAccountName` — inclusive um pod de teste.
# =============================================================================
apiVersion: v1
kind: ServiceAccount
metadata:
name: atm-provisionamento
namespace: plataforma-prod
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: atm-provisionamento-tenants
rules:
# Esperar o rollout: so leitura.
- apiGroups: ["apps"]
resources: ["deployments"]
verbs: ["get"]
# Suspender e reativar: o subrecurso `scale` altera SO as replicas. Escrever no
# Deployment inteiro deixaria trocar imagem e variavel de ambiente.
- apiGroups: ["apps"]
resources: ["deployments/scale"]
verbs: ["get", "patch"]
@@ -0,0 +1,44 @@
# =============================================================================
# P5.6/P5.9 — o provisionamento alcanca a API do Kubernetes.
#
# ── O QUE ESTAVA ACONTECENDO (achado em 2026-09-20, com o RBAC ja no ar) ────
#
# Com o ClusterRole e o RoleBinding aplicados, um `curl` de dentro do pod do
# `servico-captacao` ainda devolvia `000` — nem chegava a receber 403. A
# internet respondia (200 de fora), a API nao.
#
# O motivo: a `deny-cross-tenant` deste namespace libera saida para
# `ipBlock: 0.0.0.0/0` **na porta 443**, e a API do k3s atende na **6443**. O
# pod fala com `10.43.0.1:443` (o ClusterIP do Service `kubernetes`), mas o
# controlador de rede avalia DEPOIS do DNAT — e ali o destino ja e
# `187.77.37.184:6443`, que nao casa com nenhuma regra.
#
# Sem esta politica o RBAC nao adianta: a etapa de espera de rollout (P5.6) e a
# de suspensao (P5.9) falham por REDE, com uma mensagem que fala de HTTP.
#
# ── O IP ESTA ESCRITO AQUI, E ISSO E LIMITACAO DA FERRAMENTA ────────────────
#
# NetworkPolicy so entende IP e porta; nao existe "o Service kubernetes" como
# destino. O endereco e o do no (`kubectl -n default get endpoints kubernetes`).
# **No dia em que o no mudar de IP, este arquivo muda junto** — e o sintoma
# sera de novo `000` no lugar de 403.
#
# So o `servico-captacao` precisa disso: nenhum outro pod do namespace fala com
# a API. Por isso o `podSelector` e por app, e nao vazio.
# =============================================================================
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: egress-api-do-kubernetes
namespace: plataforma-prod
spec:
podSelector:
matchLabels:
app: servico-captacao
policyTypes: [Egress]
egress:
- to:
- ipBlock:
cidr: 187.77.37.184/32
ports:
- { protocol: TCP, port: 6443 }
+19 -29
View File
@@ -1,44 +1,34 @@
# =============================================================================
# Deixa o Prometheus raspar as metricas deste tenant.
#
# Aditivo a `deny-cross-tenant` (em `00-namespace-quota-netpol.yaml`), que
# fecha ingresso de fora do namespace. Sem esta politica o tenant sobe, funciona
# e fica INVISIVEL no Grafana — e um tenant sem metrica e um tenant em que
# ninguem percebe consumo subindo nem pod reiniciando.
# Aditivo a `deny-cross-tenant` (em `00-namespace-quota-netpol.yaml`), que fecha
# ingresso de fora do namespace. Sem esta politica o tenant sobe, funciona e fica
# INVISIVEL no Grafana — e um tenant sem metrica e um tenant em que ninguem
# percebe consumo subindo nem pod reiniciando.
#
# ── Por que nao foi copiado do piloto ────────────────────────────────────────
# ── POR QUE `podSelector: {}` (2026-09-20) ──────────────────────────────────
#
# Este arquivo NAO existe no `tenants/piloto` do repositorio de codigo; so no
# Gitea de dentro do cluster, que e a fonte real do GitOps. Foi encontrado em
# 2026-09-17 ao comparar os dois, depois que a quota defasada do molde impediu
# tres pods de subir.
# Antes a politica citava pods por NOME (`app: backend`, ou uma lista). Resultado:
# quando o `ServiceMonitor` passou a raspar os runtimes e os 13 servicos, TODOS os
# alvos novos ficaram `up=0` e o cluster acendeu 48 alertas de `TargetDown` — a
# coleta chegava ao Service e morria na rede.
#
# E o de la seleciona `app: backend` — o stub legado que P0.5 mediu nao atender
# trafego nenhum. Copiado ao pe da letra, nao casaria com pod nenhum aqui, e o
# tenant continuaria sem metrica com um arquivo que parece resolver o problema.
# Por isso este seleciona os pods que EXISTEM neste tenant.
# Lista de nomes aqui e a mesma lista do `ServiceMonitor` escrita duas vezes, em
# lugares diferentes, com o erro aparecendo so em producao. Agora vale para
# qualquer pod DESTE namespace, e a fronteira e a mesma de antes:
#
# A porta e 8083 nos quatro contextos e no bff, por convencao do projeto. O
# `frontend-spa` (nginx, porta 80) nao expoe metrica em formato Prometheus e
# fica de fora de proposito.
# - SO a porta 8083, que e a das metricas (`/actuator/prometheus`);
# - SO do namespace `monitoring`.
#
# O `frontend-spa` escuta na 80 e continua fora, sem precisar ser citado.
# =============================================================================
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-monitoring
namespace: plataforma-prod
spec:
# Sem `matchLabels` fixo: `In` cobre os cinco pods de aplicacao de uma vez, e
# um contexto novo entra acrescentando o nome aqui — em vez de exigir uma
# NetworkPolicy por servico.
podSelector:
matchExpressions:
- key: app
operator: In
values:
- servico-configuracao
- servico-cadastro
- servico-financeiro
- servico-captacao
- servico-bff
podSelector: {}
policyTypes: [Ingress]
ingress:
- from:
@@ -28,6 +28,8 @@ spec:
app: servico-captacao
athleticmap.io/contexto: financeiro
spec:
# P5.6/P5.9: conta DEDICADA (ver 16-rbac-provisionamento.yaml).
serviceAccountName: atm-provisionamento
containers:
- name: servico-captacao
image: docker.io/library/servico-captacao:1.0