Pular para conteúdo

Operação

Objetivo

Este documento descreve como a infraestrutura e os sistemas da Page Saúde devem ser operados no dia a dia. Ele serve como referência prática para manter o ambiente estável, previsível e recuperável.

Não é um manual exaustivo. O foco é registrar o que não pode ser esquecido, o que já causou problemas e o que exige atenção recorrente.

Rotinas Operacionais

Atividades recorrentes necessárias para a saúde do ambiente.

  • Verificação geral dos serviços críticos
  • Acompanhamento de alertas de monitoramento
  • Validação de execução de backups
  • Verificação de espaço em disco e recursos

(Detalhamento excessivo deve ser evitado; procedimentos críticos podem ser destacados abaixo.)

Monitoramento

Visão Geral

O monitoramento tem como objetivo detectar problemas antes de impactarem o negócio.

Aspectos monitorados:

  • Disponibilidade de serviços
  • Uso de recursos (CPU, memória, disco)
  • Logs relevantes
  • Alertas de falha ou degradação

Limites e Retenção

A stack de observabilidade foi configurada com limites estritos para uso em servidores com recursos limitados (ex: 50GB Disco).

  • Retenção: 7 Dias para Logs (Loki), Traces (Tempo) e Métricas (Prometheus).
  • Disco: Limites de tamanho configurados (~5GB Prometheus, 1GB Min Free Pyroscope).

Backups e Restauração

Visão Técnica

Utilizamos um serviço robusto de backup e restauração com formato binário customizado (pg_dump -Fc) e compressão Zstd.

  • Formato: YYYYMMDDHHMMSS_<dbname>.sql.zst (Custom Format).
  • Segurança: Restaura backups de produção ignorando owners/privilegios originais (--no-owner --no-privileges) e limpando objetos existentes (--clean).
  • Automação: Detecção automática de banco de destino e criação automática (createdb) se não existir.

Procedimentos de Execução

Rodar via Docker Compose na pasta services/database/postgres/backup/:

# Backup Interativo (Lista bancos disponíveis)
docker compose run --rm backup

# Backup Específico
docker compose run --rm backup pagesaude

# Restore Interativo (Lista arquivos disponíveis)
docker compose run --rm backup restore

# Restore Específico
docker compose run --rm backup restore 20240101120000_pagesaude.sql.zst

Versões da stack

Componentes fixados em versão (nunca latest). Pendências conhecidas de atualização:

Componente Versão atual Pendência
PostgreSQL 14.10 EOL em novembro de 2026. Planejar upgrade de major com janela e teste de restore.

O Pyroscope roda na arquitetura v2 (-architecture.storage=v2), com escrita via segment-writer e blocos em storage local (filesystem). Object storage só seria necessário em deploy distribuído. Os flags da linha 1.x (-storage.tsdb.*, -ingester.*) não existem mais no 2.x — ao ajustar o compose, confira os nomes com docker run --rm --entrypoint /usr/bin/pyroscope grafana/pyroscope:<tag> -help-all. Os perfis antigos da v1 não são migrados: a mudança descarta o histórico de profiling.

Ao atualizar Grafana entre majors, faça backup do volume grafana-data antes: a migração de schema é irreversível e o rollback exige restaurar esse backup.

Notificações de Alertas

Os alertas são avaliados pelo Prometheus e entregues ao Alertmanager (Mimir em modo -target=alertmanager). Os canais são configurados na UI do Grafana — o repositório não versiona webhook, senha nem destinatário.

Criar canais (Grafana → Alerting)

  1. Contact points → + Add contact point. Escolha "Mimir (oficial)" no seletor do topo, não "Grafana". O Grafana não permite alterar globalmente o padrão desse seletor.
  2. Crie os dois contact points abaixo. O webhook do Discord e destinatários de e-mail ficam somente na UI:
Contact point Integrações Uso
alertas-gerais Discord rota padrão, P1 e P2
alertas-criticos Discord e Email P0
  1. Notification policies → crie políticas aninhadas com matchers por severity, apontando cada uma para o contact point desejado.

Em tenant ainda sem configuração ativa, o receiver fallback-noop aparece na UI: ele pode ser renomeado para alertas-gerais e receber a integração Discord. O arquivo montado permanece vazio e não ganha credenciais.

Não crie policy por owner agora: o label fica reservado para roteamento futuro, abaixo da policy de severidade correspondente.

Sugestão de roteamento

Matcher Contact point group_wait / repetição
padrão alertas-gerais 30 s / 4 h
severity = p0 alertas-criticos 10 s / 30 min
severity = p1 alertas-gerais 30 s / 4 h
severity = p2 alertas-gerais 5 min / 24 h

Agrupar por alertname, service e environment.

O que já vem pronto do repositório

services/observability/stack/config/alertmanager.yml é o fallback imutável: traz agrupamento, inibições e o receiver vazio fallback-noop. HostDown silencia alertas derivados do host, banco fora do ar silencia alertas derivados do serviço e AlloyAgentDown silencia alertas de container do host. As policies por severidade e os contact points são criados somente na UI.

Atenção: esse arquivo só vale enquanto não houver configuração salva pela UI. Ao salvar a primeira vez, a configuração da UI substitui o fallback por completo — as inibições precisam ser recriadas na UI ou reenviadas pela API de configuração, já que a tela do Grafana não expõe inhibit_rules.

SMTP contratado

O Ansible configura o SMTP do Grafana e gera o fallback do Alertmanager com global.smtp_*. Os valores não secretos vêm das Variables do GitHub Environment (SMTP_SMARTHOST, SMTP_FROM, SMTP_AUTH_USERNAME e SMTP_REQUIRE_TLS); a senha vem do secret SMTP_PASSWORD, é gravada com modo 0600 e é lida pelos dois containers via arquivo. Portanto, ela não aparece em YAML versionado, .env nem em docker inspect.

Use a mesma identidade remetente já autorizada pela aplicação. Antes de ativar, confirme SPF com um único registro, DKIM e DMARC para o domínio. Como o relay é gerenciado, não é necessário manter PTR/rDNS próprio nem liberar a porta 25 de saída; use a porta e TLS indicados pelo fornecedor.

O Grafana usa GF_SMTP_* apenas para seus próprios e-mails. O Alertmanager do Mimir usa seu global.smtp_* e smtp_auth_password_file; é essa configuração que permite salvar o contact point de e-mail de alertas-criticos.

Migração de configuração ativa: se a UI já salvou uma configuração, o fallback não é aplicado. Antes de criar ou editar o e-mail, exporte a configuração ativa pela API do Mimir (mimirtool alertmanager get), acrescente o bloco global.smtp_* com smtp_auth_password_file: /run/secrets/smtp_password e reenvie preservando routes, receivers, templates e inibições (mimirtool alertmanager load). Faça backup do export antes. O Ansible não sobrescreve essa configuração para preservar as edições da UI.

Depois do provisionamento, envie uma notificação de teste do contact point alertas-criticos; confirme a entrega no Discord e no e-mail e remova qualquer contato de teste que não deva receber incidentes.

Health Checks externos (Cloudflare)

Para cada endpoint público crítico, crie um Cloudflare Health Check (Pro) HTTPS para um /health que não exija autenticação, com código esperado 2xx. Escolha regiões e intervalo compatíveis com o tráfego do endpoint; as mudanças de estado só são notificadas após consenso das regiões selecionadas.

  1. Em Notifications → Destinations → Webhooks → Create, crie um destino do tipo Discord, cole a URL e use Save and Test. A URL do webhook é secret e fica apenas na Cloudflare.
  2. Em Traffic → Health Checks → Create, configure o endpoint e use Save and Deploy.
  3. Na página Health Checks, selecione Configure an alert, escolha os checks e o gatilho de mudança de estado, e associe o destino Discord criado anteriormente.
  4. Force uma resposta não-2xx em ambiente seguro e confirme a notificação de falha e a de recuperação. Reponha o endpoint e registre o resultado.

Esse alerta é externo e complementar ao Prometheus; não cria regra, serviço ou credencial na stack local.

Referências: criar Health Check, notificações de Health Checks e destino webhook.

Publicação da documentação

Esta documentação (incluindo os runbooks referenciados pelos alertas) é publicada no Cloudflare Pages, em https://docs-ops.pagesaude.com.br. O GitHub Pages não atende: o repositório é privado e publicar Pages a partir de repositório privado exige plano Enterprise, que não temos.

O deploy é automático pelo workflow .github/workflows/docs.yml, disparado por mudanças em docs/ ou mkdocs.yml. Ele constrói o site com MkDocs Material em modo --strict (link quebrado falha o build) e verifica que todo runbook citado por um alerta existe como página publicada — se um alerta apontar para runbook inexistente, o build falha.

Configuração inicial (uma vez)

O projeto precisa ser criado no modo Direct Upload (sem vínculo com repositório) — é o que permite o deploy vir do GitHub Actions. O dashboard esconde essa opção atrás de Workers & Pages → Create application → Get started → Drag and drop your files; criar pela CLI é mais direto e não exige subir arquivo nenhum:

npx wrangler login
npx wrangler pages project create pagesaude-ops-docs --production-branch=main

Atenção: um projeto Direct Upload não pode ser convertido para integração Git depois. Para trocar, é preciso criar outro projeto.

Depois:

  1. My Profile → API Tokens → Create Token, com a permissão Account → Cloudflare Pages → Edit. Copiar o token.
  2. No GitHub, em Settings → Secrets and variables → Actions, criar:
  3. CLOUDFLARE_PAGES_API_TOKEN — o token do passo anterior;
  4. CLOUDFLARE_ACCOUNT_ID — visível na barra lateral do dashboard Cloudflare.
  5. No projeto Pages, Custom domains → Set up a custom domaindocs-ops.pagesaude.com.br. O registro DNS é criado automaticamente por estar na mesma conta Cloudflare.

Alternativa descartada: a integração Git do Cloudflare funciona com repositório privado, mas moveria o build para a Cloudflare e tiraria do CI a checagem que garante que todo alerta aponta para um runbook existente. Por isso o deploy fica no GitHub Actions.

Restringir o acesso (recomendado)

Os runbooks descrevem procedimentos e nomes internos de host. Para não deixá-los públicos, proteger o domínio com Cloudflare Access (Zero Trust, gratuito até 50 usuários):

  1. Zero Trust → Access → Applications → Add an application → Self-hosted.
  2. Domínio: docs-ops.pagesaude.com.br.
  3. Política de permissão: Emails ending in @pagesaude.com.br (ou lista explícita).
  4. Método de login: One-time PIN por e-mail já resolve, sem provedor de identidade.

Quem estiver de plantão abre o link do alerta, recebe o PIN por e-mail e acessa. Vale testar esse fluxo no celular antes de considerá-lo pronto — é onde ele será usado.

Administração de banco de dados

O pgAdmin foi removido (nunca operou adequadamente). Se uma ferramenta de administração visual voltar a ser necessária, avaliar CloudBeaver.

Incidentes Relevantes

Registro sintético de incidentes que geraram aprendizado.

  • (Data)(Descrição breve do incidente)(Ação tomada)

Incidentes recorrentes ou de alto impacto podem justificar a criação de um documento específico ou decisão técnica.

Procedimentos Importantes

Procedimentos que não podem depender apenas de memória ou improviso.

  • Procedimento de restauração
  • Procedimento de manutenção crítica
  • Procedimento de contingência

(Somente o essencial deve estar aqui.)

Pontos de Atenção

  • Dependências externas críticas
  • Componentes sensíveis a falhas
  • Áreas que exigem maior cuidado em mudanças

Referências