ATALAIA
  1. Início
  2. Recursos
  3. Blog
  4. O que está realmente a correr?
Pipeline · Análise a fundo

O que está realmente a correr?

Rastreie um container em produção até ao seu commit, build e pull request usando image digests, labels OCI e attestations.

3 min de leituraEquipa Atalaia

ContainersKubernetesRastreabilidade

Durante um incidente, alguém faz sempre a mesma pergunta: que versão está realmente a correr? A resposta costuma começar com uma tag, como api:1.8.2, seguida de uma longa pausa enquanto as pessoas tentam perceber se essa tag foi reconstruída, de que commit veio e se a correção que entrou ontem está lá.

Não tem de ser uma pausa. Com algumas convenções no build, qualquer container em execução pode ser rastreado até ao commit, à execução do build e ao pull request que o produziram.

As tags descrevem a intenção, não a realidade

Uma tag é um ponteiro. Pode ser publicada outra vez, sobrescrita por um rebuild ou partilhada por várias imagens ao longo do tempo. Dois clusters a correr api:1.8.2 podem estar a correr código diferente. Um digest, o hash sha256: do manifest da imagem, identifica uma imagem exata e mais nenhuma.

O Kubernetes regista o digest resolvido mesmo quando o manifest usou uma tag, por isso consegue sempre ver o que foi realmente descarregado:

kubectl get pods -n prod \
  -o custom-columns=POD:.metadata.name,IMAGE:.status.containerStatuses[0].imageID

O rasto, passo a passo

  1. PodLer o digest da imagem a partir do estado do container.
  2. ImagemLer as labels OCI ou a provenance associadas a esse digest.
  3. CommitA label de revisão indica o commit exato no repositório de código.
  4. BuildO commit leva à execução de CI que construiu e publicou a imagem.
  5. Pull requestO commit leva à alteração revista que o fez merge.

Cada elo é barato de acrescentar. O rasto só se quebra quando falta um deles.

O mesmo rasto funciona no sentido inverso, que é muitas vezes a pergunta mais útil. Quando uma correção faz merge, quer saber que ambientes já a estão a correr. A partir do commit, encontre o digest que o build produziu e depois procure nos clusters pods que corram esse digest. Se a resposta for nenhum, a correção ainda não foi entregue, digam as release notes o que disserem. As equipas que conseguem responder rapidamente nos dois sentidos tendem a ver as chamadas de incidente ficarem mais curtas e os rollbacks menos assustadores.

Ponha a origem na imagem

A especificação de imagens OCI define chaves de anotação standard exatamente para isto. Defina-as no momento do build:

docker build \
  --label org.opencontainers.image.source=https://github.com/acme/api \
  --label org.opencontainers.image.revision=$(git rev-parse HEAD) \
  --label org.opencontainers.image.created=$(date -u +%Y-%m-%dT%H:%M:%SZ) \
  -t ghcr.io/acme/api:1.8.2 .

No GitHub Actions, a docker/metadata-action gera estas labels por si. Lê-las de volta a partir de qualquer digest exige um comando:

crane config ghcr.io/acme/api@sha256:<digest> | jq '.config.Labels'

As labels são fáceis, mas qualquer pessoa que consiga fazer build de uma imagem pode defini-las. Trate-as como uma pista útil e use proveniência assinada quando a resposta tiver de resistir a escrutínio.

Torne o rasto fiável

A proveniência do build é uma declaração assinada pela plataforma de CI que diz que repositório, commit e workflow produziram um digest. Ao contrário de uma label, não pode ser escrita pelos próprios passos do build, por isso mantém-se válida mesmo que alguém tente fazer passar uma imagem construída noutro lado.

gh attestation verify oci://ghcr.io/acme/api@sha256:<digest> --repo acme/api

# from the commit, find the build run and the pull request
gh run list --repo acme/api --commit <commit-sha>
gh api repos/acme/api/commits/<commit-sha>/pulls --jq '.[].html_url'

O que quebra o rasto

  • Imagens construídas em portáteis. Sem execução de CI, sem provenance, muitas vezes sem labels. Bloqueie pushes para registries de produção a partir de tudo o que não seja o CI.
  • Retagging entre ambientes. Promover reconstruindo cria um novo digest. Promova antes o mesmo digest.
  • Squash merges sem links. O commit na main tem de continuar a apontar para o seu pull request. A maioria das plataformas trata disto, mas verifique as suas definições de merge.
  • Desvio da imagem base. O seu commit não mudou, mas a base sim. Fixe as imagens base por digest e deixe o bot de atualizações propor a alteração.

Verifique o seu em 10 minutos

  1. Escolha um serviço de produção e liste os digests das imagens em execução com o comando kubectl acima.
  2. Corra crane config num digest. Existe uma label de revisão?
  3. Siga esse commit até uma execução de build e um pull request. Cronometre quanto tempo demora.
  4. Verifique se os seus manifests de deploy usam tags ou digests.
  5. Verifique se alguém fora da CI consegue fazer push para o registry de produção.

Se o rasto demorar mais do que alguns minutos, ou parar no segundo passo, sabe que elo acrescentar primeiro.

Onde isto fica na linha

Na torre (em desenvolvimento):

Vamos conversar

Uma chamada de 30 minutos. Sem slides, sem tabela de preços, e um próximo passo em qualquer caso.