Airframe

Por que o Airframe

Observável e documentado por padrão

Uma equipe não deveria ter que construir o seu próprio monitoramento nem desenhar os seus próprios diagramas de arquitetura. A entrada do catálogo de um produto lhe dá uma pasta do Grafana, painéis e regras de alerta; os seus logs, métricas e traces chegam até eles sem configuração; e cada merge publica a parte do produto num mapa da organização inteira, que se reconstrói sozinho.

Como um produto se torna observável e documentado

  1. A entrada lhe dá uma pasta e painéis

    Quando a entrada do catálogo de um produto recebe o merge, a raiz do Grafana do repositório operations roda na cadeia de reconciliadores. No único stack do Grafana Cloud da organização, ela cria a pasta do produto, que a sua equipe pode editar e todos podem ver, com um painel de serviço e um painel de SLO que abrem em produção, ao lado do painel de custos da página de FinOps.

  2. As regras de alerta vêm junto

    A mesma raiz cria as regras de alerta básicas do produto, com limites tirados do campo slo da entrada: o orçamento de erros sendo consumido rápido ou devagar, erros do servidor acima de 2 por cento, latência acima do objetivo ou do dobro dele, o Cloud SQL perto dos seus limites, mensagens do Pub/Sub esperando mais de dez minutos e um tópico de mensagens mortas que não está vazio. Elas selecionam a produção pelo rótulo env e mandam um e-mail para o ponto de contato da equipe. Hoje esse ponto de contato chega às contas do próprio mantenedor, porque o Grafana Cloud só aceita endereços dos seus próprios membros e as contas do mantenedor são os seus únicos membros.

  3. A telemetria flui sem configuração

    Uma aplicação escreve logs em JSON na sua saída padrão e envia traces e métricas com OTLP para o endereço que a plataforma lhe dá; ela nunca tem uma credencial do Grafana. A plataforma tem um par de gateways por edição, produção e não produção. Os traces e as métricas vão para o gateway OTLP da edição com o token de identidade do serviço, e os logs viajam pelo Cloud Logging e por um buffer do Pub/Sub até o gateway de logs. Os gateways, Grafana Alloy no Cloud Run, conferem o rótulo env de cada sinal, carimbam nele a sua edição e o encaminham com um token só de escrita. O endereço chega na saída Ready do produto, e os módulos do golden path o passam para cada serviço.

  4. Cada merge publica a sua parte do mapa

    O pipeline de cada repositório de produto inclui o componente catalog-publish, e também o do catálogo e os de quatro repositórios da plataforma. Num merge request, o componente gera o fragmento do repositório, a sua parte do mapa, sem nenhuma credencial, e falha quando falta a visão geral ou o runbook. Depois do merge, ele publica o fragmento sob o prefixo próprio do repositório: para um produto, o seu serviço, as suas especificações de API e de eventos, os produtos que chama, o seu runbook e os seus registros de decisão.

  5. O mapa se reconstrói sozinho

    Um agregador reconstrói o mapa com os últimos fragmentos logo depois de cada publicação e a cada hora, em catalog.projectairframe.dev atrás do IAP, onde todos na organização podem lê-lo. Ele tira a lista de produtos do catálogo, pula um fragmento quebrado para que o resto continue sendo construído e guarda as três últimas versões. O mapa segue o branch main de cada repositório, não o que está implantado.

Um exemplo prático

Esta é uma parte da entrada do produto invoicing no catálogo da demo, e o que a plataforma deriva dela. A pasta, os painéis e as regras de alerta vêm só da entrada; os sinais precisam que os projetos do produto sejam faturados, e hoje nenhum produto da demo é faturado, então a telemetria abaixo é a que fluiria.

product: invoicing
journey: settle
domain: billing
context: invoicing
team: billing-core
slo: { availability: 99.5, latency_p95_ms: 400 }
  • Uma pasta para o produto sob settle, billing e invoicing, que a billing-core edita e todos veem
  • Os painéis "invoicing service" e "invoicing SLO", que abrem em prod, ao lado de "invoicing cost"
  • Regras de alerta com os limites da entrada: um orçamento de erros para uma disponibilidade de 99,5 por cento, um ticket quando a latência p95 fica acima de 400 ms e um alerta urgente acima de 800 ms
  • Alertas para o ponto de contato da billing-core, que hoje manda e-mails para as contas do próprio mantenedor
  • Traces e métricas que levam o nome de serviço do invoicing, o seu domínio e o seu ambiente, e métricas de recursos da nuvem rotuladas com o caminho do produto, settle/billing/invoicing/invoicing, sem nenhuma credencial do Grafana no repositório
  • Uma página de serviço para o invoicing em catalog.projectairframe.dev, construída a partir do fragmento que o seu repositório publica a cada merge na main: a sua visão geral, os seus responsáveis, o seu runbook e os seus registros de decisão

O que torna isso verdade

Todo produto tem os seus painéis e as suas regras de alerta a partir da sua entrada.
A raiz do Grafana de operations, que roda quando o catálogo muda, cria a pasta de cada produto do catálogo, que a sua equipe edita e todos veem, os seus painéis de serviço e de SLO e as suas regras de alerta básicas, com limites tirados do campo slo da entrada; as regras selecionam a produção pelo rótulo env, e uma série ausente não é um alerta.
Um alerta chega à equipe do produto, e hoje isso quer dizer ao mantenedor.
Cada regra é direcionada pelo rótulo da equipe ao ponto de contato da equipe, que manda um e-mail para os membros da equipe que têm conta no Grafana, e um alerta urgente se repete a cada quatro horas até ser resolvido. O Grafana Cloud só aceita endereços dos seus próprios membros, e hoje esses membros são as contas do próprio mantenedor, então os alertas de cada equipe, e os da plataforma, chegam ao mantenedor.
Uma aplicação não precisa de configuração e não tem nenhuma credencial do Grafana.
A saída Ready da fábrica de projetos traz o endereço do gateway da edição do produto, produção ou não produção, e o módulo de Cloud Run do golden path o injeta em cada serviço. Os traces e as métricas chegam ao gateway OTLP com o token de identidade do serviço, que a verificação de invocador do gateway admite; os logs chegam ao gateway de logs pelo sink do projeto do produto e pelo buffer do Pub/Sub. Os gateways têm o token só de escrita da edição, a única credencial do Grafana desse lado.
Todo sinal diz de que edição veio.
O gateway OTLP mantém o env de um sinal só quando ele é válido para a sua própria edição e troca um valor ausente ou alheio por unknown; o gateway de logs mantém um env válido e, se não houver, dá à linha o do seu perímetro, então só as entradas de auditoria ficam em unknown. Os dois marcam a edição como perimeter. O módulo de Cloud Run do golden path dá aos traces e às métricas de um serviço seu nome de serviço, seu domínio e seu ambiente, e o agente da plataforma rotula as métricas de recursos do Cloud de cada projeto de produto faturado com o caminho do produto e sua jornada e domínio.
Cada produto publica a sua própria parte do mapa, e só a sua.
O job validate:fragment do componente catalog-publish gera o fragmento no merge request sem nenhuma credencial e falha se falta a visão geral ou o runbook; na main protegida, release:catalog o publica com a identidade que o repositório já tem. A identidade de aplicação de produção de um produto só pode escrever sob o prefixo do seu produto, e o repositório do catálogo escreve como platform-catalog@ sob o seu. Os quatro repositórios da plataforma compartilham uma identidade, platform-docs@, cuja permissão cobre todo o prefixo da plataforma, então nada impede que um deles escreva a parte de outro.
O mapa se reconstrói sozinho a partir dos últimos fragmentos.
O agregador, um job de Cloud Run, roda quando uma identidade que publica o pede depois de uma publicação, que é tudo o que essa identidade pode fazer no projeto, e a cada hora por agendamento. Ele lê a lista de produtos do catálogo, pula um fragmento quebrado com os motivos no registro da execução e guarda as três últimas versões. O site atrás do IAP procura uma versão nova a cada minuto e continua servindo a última se não consegue lê-la.