Instalação completa do ambiente local¶
Esta jornada instala o backend no Kind, com MongoDB, Valkey, RabbitMQ, PostgreSQL, MinIO, Elasticsearch, OpenTelemetry, Keycloak e o Platform API Mock. É um ambiente experimental de desenvolvimento. DEV, STAGING e PROD pertencem ao TOTVS Apps.
Instalação nova e cluster existente
Os comandos de instalação, carregamento de imagens e limpeza abaixo modificam o ambiente. Não os execute sobre um cluster existente sem revisar os valores e o plano de aplicação. Credenciais geradas para uma instalação nova não substituem automaticamente as credenciais dos bancos existentes.
O registro de validação distingue builds e verificações estáticas dos cenários funcionais ainda pendentes de execução no cluster.
1. Preparar a máquina e obter o código¶
Use Docker com containers Linux, Git, Python 3.12 ou superior, Kind, kubectl, Helm 3 e Helmfile. helmfile apply também utiliza o plugin Helm Diff. Consulte Preparar o ambiente para instalação das ferramentas. As versões utilizadas na revisão foram Docker 28.4, Helm 3.18.6 e Helmfile 1.1.7; isso não constitui uma matriz completa de compatibilidade.
No Windows, use Docker Desktop com WSL2 e PowerShell, ou execute toda a jornada dentro do WSL2. No Ubuntu, use Docker Engine e o perfil local-ubuntu. Não misture contexts Docker, arquivos de credenciais e executáveis de ambientes diferentes durante a instalação.
Obtenha os repositórios backend autorizados na organização e mantenha a organização services/ e infra/totvs-gateway-infra-local/. A relação exata dos repositórios, commits e Dockerfiles está em install/local-images.json. Os scripts recusam construir um serviço cujo HEAD difira do commit revisado nesse arquivo. Para uma nova versão, revise e atualize esse inventário e as tags em conjunto.
Execute os comandos seguintes na raiz de totvs-gateway-infra-local:
python -m pip install -r scripts/local/requirements.txt
python scripts/local/images.py check
docker info
kind get clusters
kubectl config current-context
helm version
helmfile --version
helm plugin list
O cluster declarado possui quatro nós. Não há dimensionamento mínimo validado para executar todos os serviços simultaneamente. Reserve capacidade para JVMs, bancos, Elasticsearch e builds; confira requests/limits nos manifests antes de aplicar. Falta de capacidade não deve ser corrigida desabilitando probes ou segurança.
2. Preparar valores privados e imagens¶
python scripts/local/prepare.py
python scripts/local/images.py build
prepare.py cria .local/values.yaml, ignorado pelo Git, com credenciais aleatórias e referências às imagens locais. Não sobrescreve arquivo existente. Guarde esse arquivo com acesso restrito e reutilize-o nas atualizações. No Windows, confira também as permissões NTFS da pasta; chmod não substitui a revisão das ACLs.
O build exporta os commits com git archive para uma pasta temporária em .local/build; não compila dentro dos repositórios dos microserviços. Java usa Maven 3.9.11/JDK 21 em container, executa verify e utiliza o Dockerfile JVM existente. Broker e Security Checker utilizam seus Dockerfiles locais. Discovery, Auth Provider, Router e Outbox Dispatcher utilizam o Dockerfile Go do repositório de infraestrutura, com toolchain/entrypoint declarados no inventário e execução de go test ./.... Cache Monitor utiliza o Dockerfile cron existente.
As imagens são JVM, não native: o suporte a JDWP depende disso. Os Dockerfiles dos serviços são preservados. As bases e dependências precisam estar acessíveis pela rede; tags fixadas não garantem reprodução byte a byte de bases externas mutáveis. Falhas de testes ou dependências privadas interrompem o build e devem ser investigadas, sem saltar os testes para declarar sucesso.
Para construir apenas um componente:
python scripts/local/images.py build --only json-handler
O inventário contém 22 imagens de componentes backend, incluindo Outbox Dispatcher e Cache Monitor, além de Keycloak e mocks. Todos os charts atualmente habilitados pelo agregador permanecem contemplados. Tunnel e Web Pages não são adicionados artificialmente ao agregador.
3. Criar o Kind e configurar o acesso¶
Somente para uma instalação nova, após confirmar a ausência de cluster com o mesmo nome:
kind create cluster --config kind/kind-config.yaml
kubectl --context kind-totvs-gateway get nodes
python scripts/local/images.py load --cluster totvs-gateway
O arquivo Kind mapeia as portas 80/443 do host para NodePorts 30080/30443. O perfil Windows utiliza esses NodePorts. No Ubuntu, o perfil utiliza MetalLB/LoadBalancer: defina global.metallb.ipRange em .local/values.yaml com um intervalo livre e alcançável da rede Docker efetivamente utilizada. O perfil recusa renderizar um pool vazio; o Ingress recebe um endereço desse pool, sem IP de uma máquina antiga fixado nos values. Confira a rede com docker network inspect kind e evite endereços usados por nós, gateway ou outros containers.
Configure no arquivo hosts da máquina api.gateway.local.test, auth.gateway.local.test e company-a.gateway.local.test. No Windows, a entrada aponta para 127.0.0.1 se o mapeamento de portas do Docker Desktop estiver disponível. No Ubuntu/MetalLB, utilize o IP atribuído ao Service do Ingress. Arquivos hosts não aceitam wildcard. O acesso por IP sem o Host correto não seleciona o Ingress esperado.
4. Renderizar, revisar e instalar¶
Os valores são aplicados nesta ordem: install/common/local-platform.yaml, perfil em install/NGiNX/environments/, .local/values.yaml. O último arquivo é privado. Não aplique apenas o arquivo do perfil diretamente com Helm: ele contém somente as diferenças entre sistemas operacionais.
helmfile -f install/NGiNX/helmfile.yaml --environment local-win list
helmfile -f install/NGiNX/helmfile.yaml --environment local-win template > .local/rendered.yaml
Substitua local-win por local-ubuntu quando aplicável. Os manifests renderizados contêm Secrets; não os publique. Revise imagens, namespaces, credenciais, volumes e endpoints antes da aplicação.
Após autorização para modificar o cluster:
helmfile -f install/NGiNX/helmfile.yaml --environment local-win apply
O DAG needs estabelece as dependências de instalação:
| Grupo | Componentes e responsabilidade |
|---|---|
| Base | Namespaces, permissões e recursos de base; MetalLB no Ubuntu |
| Entrada | Ingress NGINX; a entrada pública mantém a chamada ao Security Checker |
| Persistência e processamento | MongoDB, Valkey, RabbitMQ, PostgreSQL, MinIO |
| Observabilidade | Elasticsearch e OpenTelemetry Collector |
| Simulação externa | Release mocks, com workload no namespace totvs-gateway |
| Plataforma | Release totvs-gateway-server: microserviços, Keycloak e Job de importação dos realms |
As versões dos charts externos estão fixadas no Helmfile. O Keycloak é parte do release da plataforma, não um release independente. Helm aguarda readiness e Jobs conforme helmDefaults. Um Pod Ready não comprova que as integrações funcionam.
Os namespaces das dependências são mongodb, valkey, rabbitmq, postgresql, minio, data-lake, telemetry, ingress-nginx e keycloak. Os microserviços e o mock ficam em totvs-gateway. Os releases base, mocks e agregador têm metadados Helm no namespace default; isso não muda os namespaces declarados pelos templates.
5. Keycloak local e autenticação¶
O bootstrap configura o realm técnico usado pelo Security Checker e o realm local. Neste último, o client confidencial account habilita os fluxos já previstos no projeto e emite apps: ["ipaas"], companyId e userIdpId. Os usuários locais A/B pertencem a tenants distintos. Seus nomes, senhas e client secret estão em global.keycloak.bootstrap no arquivo privado; não há senha a copiar deste tutorial.
O issuer local é http://auth.gateway.local.test/realms/local. O BFF consulta as chaves em http://keycloak.keycloak.svc.cluster.local/realms/local/protocol/openid-connect/certs. Auth Provider usa discovery/JWKS internos e issuer configurado por realm. O Keycloak habilita backchannel dinâmico para clientes internos, mantendo o hostname público completo para o issuer. Não substitua o JWT por um token do mock.
kubectl --context kind-totvs-gateway -n keycloak rollout status deployment/keycloak
kubectl --context kind-totvs-gateway -n totvs-gateway get jobs -l app=keycloak-config-cli-import
kubectl --context kind-totvs-gateway -n totvs-gateway logs -l job-name=keycloak-config-cli-import-1 -c keycloak-config-cli
O sufixo do Job é a revisão Helm; consulte get jobs antes de selecionar o nome. Jobs concluídos têm TTL de 600 segundos. Não procure indefinidamente um Job já removido pelo TTL; confira os realms e o token.
O realm ERP depende do provider totvs-form-parameter-claim-protocol-mapper, cujo JAR não está disponível neste workspace. global.keycloak.erpEnabled: false exclui apenas essa importação, sem substituir o provider e sem desligar validação de tokens. Integrações ERP com claims derivados de parâmetros de formulário permanecem indisponíveis.
6. Mocks e dependências externas¶
O Platform API Mock já simula recursos, aplicações, serviços, ambientes e validação de recursos do iPaaS, além de Accounts/OAuth e do destino /teste/service. A instalação agora utiliza o chart existente pelo Helmfile. Core, BFF e Builder recebem URLs internas do mock; o ambiente env-1 aponta para http://mocks:8080, e resource-1 descreve GET /teste/service, com isErp: false.
O mock de Authenticator implementa GET /authenticator/v1/roles/by-user-tenant, com userCode/tenantCode e resposta features[].resources[].group.code/code. local-user-a no tenant company-a recebe a fixture VariableV2/VariableV2.create; outros pares recebem lista vazia, e ausência de Bearer retorna 401. Essa permissão vem do teste do BFF, não representa um endpoint administrativo protegido já em uso.
O mock verifica a presença de Bearer, não a assinatura criptográfica: a validação real de JWT continua no BFF. Não exponha o mock como serviço corporativo de autorização.
kubectl --context kind-totvs-gateway -n totvs-gateway port-forward service/mocks 18084:8080
Em outro terminal, consulte http://127.0.0.1:18084/teste/service e os mappings em http://127.0.0.1:18084/__admin/mappings. Finalize o port-forward após a inspeção. Diagramas iPaaS, ERP, serviços corporativos e integrações não cobertas pelos mappings não são considerados simulados apenas porque o mock está disponível.
7. Validar infraestrutura e aplicação¶
kubectl --context kind-totvs-gateway get nodes
kubectl --context kind-totvs-gateway get pods -A
kubectl --context kind-totvs-gateway get services -A
kubectl --context kind-totvs-gateway -n totvs-gateway get deployments
kubectl --context kind-totvs-gateway -n totvs-gateway get events --sort-by=.lastTimestamp
Verifique separadamente readiness dos bancos, conexão dos serviços e processamento funcional. O endpoint do BFF é /gateway/q/health/ready; não presuma que todos os serviços Java/Go compartilham o mesmo caminho. Consulte as probes de cada Deployment e Diagnóstico.
Cenário B — Control Plane¶
Após autorização e instalação, execute:
python scripts/local/check_control_plane.py
O script emite token pelo Keycloak local, confere os claims esperados, consulta GET /gateway/api/v1/gateways no BFF com Bearer e x-tenant-id, e verifica que a mesma entrada sem token é rejeitada. O token de curta duração fica em .local/access-token.txt para a etapa seguinte; não é impresso. Decodificar os claims não verifica a assinatura: essa verificação pertence ao BFF.
Limitação de autorização por recurso: no BFF atual, os endpoints administrativos analisados não aplicam @RequiresResource. Portanto, sucesso nessa consulta não comprova a aplicação da permissão retornada pelo Authenticator. Não utilize sysadmin, não desligue RESOURCE_AUTHORIZATION_ENABLED e não regrida a versão do serviço. A conclusão integral dessa parte do cenário B depende de evolução do BFF fora do escopo deste trabalho.
Cenário A — Data Plane¶
Este roteiro prepara uma rota administrativa autenticada, publica sua revisão e utiliza a entrada pública protegida pelo Security Checker. Execute depois do cenário B. Os comandos PowerShell abaixo utilizam os DTOs atuais do BFF/Core; ainda precisam de execução integrada autorizada para confirmar o resultado.
$api = 'http://api.gateway.local.test/gateway/api/v1'
$headers = @{ Authorization = 'Bearer ' + (Get-Content .local/access-token.txt -Raw); 'x-tenant-id' = 'company-a' }
function Invoke-GatewayJson($method, $path, $body) {
Invoke-RestMethod -Method $method -Uri "$api$path" -Headers $headers -ContentType 'application/json' -Body ($body | ConvertTo-Json -Depth 15)
}
$suffix = Get-Date -Format yyyyMMddHHmmss
$routePassword = [guid]::NewGuid().ToString('N')
$auth = Invoke-GatewayJson POST '/authorizations' @{ name = "Local $suffix"; type = 'BASIC'; userName = 'local-probe'; password = $routePassword }
$gateway = Invoke-GatewayJson POST '/gateways' @{ name = "Local $suffix"; description = 'Validacao do destino mock'; basePath = "/local-$suffix"; enabled = $true; authentication = @{ id = $auth.id; type = 'BASIC' } }
$category = Invoke-GatewayJson POST "/gateways/$($gateway.id)/categories" @{ name = 'Validacao local' }
$route = Invoke-GatewayJson POST "/gateways/$($gateway.id)/routes" @{ name = 'Destino mock'; categoryId = $category.id }
$null = Invoke-GatewayJson PATCH "/gateways/$($gateway.id)/routes/$($route.id)" @{
enabled = $true
client = @{ path = '/probe'; method = 'GET'; authentication = @{ id = $auth.id; type = 'BASIC'; heritageType = 'OWN' } }
ipaasResource = @{ applicationId = '9ed673d9-8791-45dd-9409-8d35dd16e85b'; serviceId = '9ed673d9-8791-45dd-9409-8d35dd16e85b'; resourceId = 'resource-1'; environmentId = 'env-1' }
}
Invoke-RestMethod -Method POST -Uri "$api/gateways/$($gateway.id)/routes/$($route.id)/complete" -Headers $headers
Invoke-RestMethod -Method POST -Uri "$api/gateways/$($gateway.id)/revision/$($gateway.revisionId)/promote" -Headers $headers
$basic = [Convert]::ToBase64String([Text.Encoding]::UTF8.GetBytes("local-probe:$routePassword"))
Invoke-RestMethod -Uri "http://company-a.gateway.local.test/local-$suffix/probe" -Headers @{ Authorization = "Basic $basic" }
BASIC é um mecanismo real do Security, configurado apenas nessa nova rota; não desliga JWT do BFF nem a autenticação da entrada pública. Utilize esse HTTP somente no ambiente local. Repita a chamada pública sem Authorization e confirme a rejeição. Compare o corpo recebido com o mapping /teste/service e confirme no journal do WireMock que o destino foi chamado; HTTP 200 isolado não prova o caminho completo. Registre os IDs criados para remoção posterior pelas APIs administrativas, sem apagar collections diretamente.
Se qualquer etapa de configuração/publicação falhar, interrompa o roteiro e registre o erro. Não altere o banco manualmente nem remova validações para forçar a publicação. Falhas desse roteiro representam uma pendência funcional, não uma instalação completa validada.
8. Desenvolvimento e atualização¶
Os manifests locais usam imagens gateway-local/* com política Never para os serviços e o mock. Construa e carregue a tag em todos os nós antes de aplicar. Não misture tags carregadas localmente com imagePullPolicy: Always. Keycloak utiliza IfNotPresent e também deve ser carregado. Imagens de terceiros continuam sendo obtidas dos respectivos registries públicos.
Para atualizar código, revise commits/tags em install/local-images.json e as referências correspondentes em .local/values.yaml, construa, carregue e reaplique o Helmfile. Não gere novas credenciais para atualizar uma imagem. Reutilizar a mesma tag pode exigir rollout explícito; prefira tags novas associadas ao commit.
global.devMode já habilita JDWP nos charts compatíveis. Consulte Debug remoto Java, sem modificar Dockerfiles. Continue com Primeiro deploy local, Imagens Docker e Deploy no Kind.
9. Diagnóstico¶
| Sintoma | Verificação |
|---|---|
| Kind não inicia | Docker Linux ativo, portas 80/443 livres, memória/disco e context corretos |
| ErrImageNeverPull | Tag exata construída e carregada em todos os nós; confira install/local-images.json |
| ImagePullBackOff | Registry da imagem externa acessível; imagens locais não devem utilizar Always |
| Ubuntu sem EXTERNAL-IP | Pool MetalLB real, não vazio, sem conflito e alcançável pelo host |
| CrashLoopBackOff | kubectl logs --previous, configuração, requests/limits e dependências; não desligue probes |
| Falha Mongo/Valkey/Rabbit | Service/DNS, Secret e credencial do banco efetivamente instalado; values novos não rotacionam bancos antigos |
| Keycloak não importa | Logs do Job da revisão atual, PostgreSQL, imagens do bootstrap e realm ERP desabilitado sem seu provider |
| Token rejeitado | Issuer, expiração, JWKS, apps, companyId, userIdpId e tenant; não imprima tokens em logs |
| Mock retorna 404 | Método, path, query e mapping exatos; não assuma que todos os contratos externos têm fixture |
| Rota não publica | Categoria, configuração iPaaS, autenticação e estado PUBLISHABLE antes da promoção do gateway |
| BFF responde, mas permissões não mudam | Limitação de aplicação de @RequiresResource; não concluir que o mock está sendo consultado |
| Observabilidade incompleta | Conexão Collector/Elasticsearch, exportadores e recursos; saúde HTTP não comprova ingestão |
10. Limpeza e preservação de dados¶
Um rollout não é um backup. Alguns values históricos de dependências desabilitam persistência; confira os PVCs e volumes renderizados antes de reiniciar bancos. Helm rollback também não restaura os dados de bancos nem desfaz importações do Keycloak.
Somente após autorização para a remoção desejada:
helm --kube-context kind-totvs-gateway uninstall totvs-gateway-server -n default
helm --kube-context kind-totvs-gateway uninstall mocks -n default
Esses comandos removem os recursos desses releases; não são uma forma de preservar todos os dados. Para destruir integralmente um cluster descartável, kind delete cluster --name totvs-gateway remove seus nós e armazenamento local. Não execute no cluster existente desta revisão. Apague tokens temporários após uso; mantenha os valores privados necessários para recuperar os bancos que forem preservados.
Base técnica e limites¶
As fontes de configuração são kind/kind-config.yaml, install/NGiNX/helmfile.yaml, install/common/local-platform.yaml, os charts em helm-releases/ e install/local-images.json. Os contratos do roteiro estão em GatewayResource, RouteResource, AuthorizationResource e DTOs associados no BFF; GatewayController, RouteController e seus DTOs no Core; e nos mappings do Platform API Mock. A revisão de referência do BFF é 4c0161acad09968433589f132dd640dcf624bec9.
Istio e Kubernetes Gateway API continuam estudos separados, não são pré-requisitos desta jornada NGINX. ERP, diagramas iPaaS e integrações corporativas não simuladas continuam limitados. A disponibilidade de todos os Pods não elimina essas limitações.