From 1ed00120c0c7c516f634bf83940ba0e1f3f83cc9 Mon Sep 17 00:00:00 2001 From: deploy Date: Mon, 21 Sep 2026 02:30:31 +0000 Subject: [PATCH] feat(plataforma,tenants): coleta de metricas e permissao do provisionamento --- .../acme/16-rolebinding-provisionamento.yaml | 22 ++++++++ tenants/acme/60-monitoring-netpol.yaml | 29 ++++++++-- .../demo/16-rolebinding-provisionamento.yaml | 22 ++++++++ tenants/demo/60-monitoring-netpol.yaml | 29 ++++++++-- .../16-rolebinding-provisionamento.yaml | 22 ++++++++ tenants/escolinha/60-monitoring-netpol.yaml | 29 ++++++++-- .../16-rolebinding-provisionamento.yaml | 22 ++++++++ tenants/piloto/60-monitoring-netpol.yaml | 29 ++++++++-- .../plataforma/16-rbac-provisionamento.yaml | 54 +++++++++++++++++++ .../17-netpol-api-do-kubernetes.yaml | 44 +++++++++++++++ tenants/plataforma/60-monitoring-netpol.yaml | 48 +++++++---------- tenants/plataforma/82-servico-captacao.yaml | 2 + 12 files changed, 307 insertions(+), 45 deletions(-) create mode 100644 tenants/acme/16-rolebinding-provisionamento.yaml create mode 100644 tenants/demo/16-rolebinding-provisionamento.yaml create mode 100644 tenants/escolinha/16-rolebinding-provisionamento.yaml create mode 100644 tenants/piloto/16-rolebinding-provisionamento.yaml create mode 100644 tenants/plataforma/16-rbac-provisionamento.yaml create mode 100644 tenants/plataforma/17-netpol-api-do-kubernetes.yaml diff --git a/tenants/acme/16-rolebinding-provisionamento.yaml b/tenants/acme/16-rolebinding-provisionamento.yaml new file mode 100644 index 0000000..85de3a0 --- /dev/null +++ b/tenants/acme/16-rolebinding-provisionamento.yaml @@ -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 diff --git a/tenants/acme/60-monitoring-netpol.yaml b/tenants/acme/60-monitoring-netpol.yaml index 9bebb76..c8d819b 100644 --- a/tenants/acme/60-monitoring-netpol.yaml +++ b/tenants/acme/60-monitoring-netpol.yaml @@ -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: diff --git a/tenants/demo/16-rolebinding-provisionamento.yaml b/tenants/demo/16-rolebinding-provisionamento.yaml new file mode 100644 index 0000000..895a5a3 --- /dev/null +++ b/tenants/demo/16-rolebinding-provisionamento.yaml @@ -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 diff --git a/tenants/demo/60-monitoring-netpol.yaml b/tenants/demo/60-monitoring-netpol.yaml index 0754624..d517b45 100644 --- a/tenants/demo/60-monitoring-netpol.yaml +++ b/tenants/demo/60-monitoring-netpol.yaml @@ -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: diff --git a/tenants/escolinha/16-rolebinding-provisionamento.yaml b/tenants/escolinha/16-rolebinding-provisionamento.yaml new file mode 100644 index 0000000..4fb7342 --- /dev/null +++ b/tenants/escolinha/16-rolebinding-provisionamento.yaml @@ -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 diff --git a/tenants/escolinha/60-monitoring-netpol.yaml b/tenants/escolinha/60-monitoring-netpol.yaml index daf4911..181fe26 100644 --- a/tenants/escolinha/60-monitoring-netpol.yaml +++ b/tenants/escolinha/60-monitoring-netpol.yaml @@ -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: diff --git a/tenants/piloto/16-rolebinding-provisionamento.yaml b/tenants/piloto/16-rolebinding-provisionamento.yaml new file mode 100644 index 0000000..dde42e5 --- /dev/null +++ b/tenants/piloto/16-rolebinding-provisionamento.yaml @@ -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 diff --git a/tenants/piloto/60-monitoring-netpol.yaml b/tenants/piloto/60-monitoring-netpol.yaml index 26dd359..caa57ef 100644 --- a/tenants/piloto/60-monitoring-netpol.yaml +++ b/tenants/piloto/60-monitoring-netpol.yaml @@ -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: diff --git a/tenants/plataforma/16-rbac-provisionamento.yaml b/tenants/plataforma/16-rbac-provisionamento.yaml new file mode 100644 index 0000000..62e6a2e --- /dev/null +++ b/tenants/plataforma/16-rbac-provisionamento.yaml @@ -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/-prod/deployments/ +# — esperar o rollout do tenant novo terminar (P5.6); +# PATCH /apis/apps/v1/namespaces/-prod/deployments//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//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"] diff --git a/tenants/plataforma/17-netpol-api-do-kubernetes.yaml b/tenants/plataforma/17-netpol-api-do-kubernetes.yaml new file mode 100644 index 0000000..3a8ee06 --- /dev/null +++ b/tenants/plataforma/17-netpol-api-do-kubernetes.yaml @@ -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 } diff --git a/tenants/plataforma/60-monitoring-netpol.yaml b/tenants/plataforma/60-monitoring-netpol.yaml index 0b54183..be6858b 100644 --- a/tenants/plataforma/60-monitoring-netpol.yaml +++ b/tenants/plataforma/60-monitoring-netpol.yaml @@ -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: diff --git a/tenants/plataforma/82-servico-captacao.yaml b/tenants/plataforma/82-servico-captacao.yaml index 98948cb..e77f136 100644 --- a/tenants/plataforma/82-servico-captacao.yaml +++ b/tenants/plataforma/82-servico-captacao.yaml @@ -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