Pular para o conteúdo

DevOps

Dockerfile, compose, CI, Kubernetes, Helm, Terraform, nginx, Prometheus e SBOM — gerados do que o projeto realmente usa, e não de um modelo.

dataforge devops gera os arquivos que põem um projeto no ar — e sai da frente. Não há deploy que fale com Docker e Kubernetes por dentro: no dia em que alguém precisa mudar uma camada, tem de haver onde mexer.

bash
dataforge devops              # tudo o que faz sentido para este projeto
dataforge devops doctor       # o que falta para subir
dataforge devops --seco       # mostra o que faria, sem escrever

Os onze subcomandos#

ComandoGera
devops inittudo o que faz sentido para este projeto (o padrão)
devops dockerDockerfile, .dockerignore, docker-compose.yml
devops ci github.github/workflows/ci.yml
devops k8sdeployment, service, ingress, configmap, hpa
devops helmum chart com values.yaml
devops terraformo esqueleto
devops nginxproxy reverso com TLS, WebSocket e SSE
devops observarPrometheus, Grafana e OpenTelemetry
devops sbomo inventário, em CycloneDX
devops secrets.env.example e o .gitignore
devops doctoro que falta para este projeto subir

Os artefatos saem do que o projeto ADOTA#

Não é um modelo com buracos para preencher. O gerador lê o forge.toml e varre os .df procurando o que o código realmente usa:

bash
$ dataforge devops --seco

   loja 2.1.0  (Kiln, banco)

  + .dockerignore              43 linha(s)
  + .env.example               15 linha(s)
  + .github/workflows/ci.yml   75 linha(s)
  + Dockerfile                 40 linha(s)
  + deploy/nginx.conf          67 linha(s)
  + docker-compose.yml         41 linha(s)
  + k8s/configmap.yml          13 linha(s)
  + k8s/deployment.yml         89 linha(s)
  + k8s/hpa.yml                30 linha(s)
  + k8s/ingress.yml            31 linha(s)
  + k8s/service.yml            16 linha(s)

O (Kiln, banco) ali é o que ele detectou — e é o que decide o resultado. Quem não usa banco não ganha um Postgres no compose; quem não usa Kiln não ganha EXPOSE nem sonda de saúde.

O que o Dockerfile carrega, e por quê#

O que ele gera não é esboço: é o que se poria em produção. Cinco decisões, e o problema de cada uma:

No artefatoSem ele
USER forgeum escape de container vira root no host
o manifesto copiado antes do códigoum commit numa linha reinstala tudo — o build vai de 8 s para 2 min
.env no .dockerignoreo segredo fica na camada, e docker history o mostra — mesmo apagado numa camada seguinte
resources + as duas sondas no Deploymentum pod come o nó inteiro; e o Service manda tráfego antes da hora
depends_on: service_healthya aplicação falha na primeira consulta, de forma intermitente
bash
# A sonda usa o proprio Python: 'curl' nao esta na imagem
# slim, e instalar 30 MB para uma sonda de 200 bytes seria
# trocar tamanho por conveniencia.
HEALTHCHECK --interval=30s --timeout=3s --start-period=10s --retries=3 \
  CMD python -c "import urllib.request,sys; sys.exit(0 if urllib.request.urlopen('http://127.0.0.1:8080/saude', timeout=2).status == 200 else 1)"

`doctor` — e ele funciona num projeto que não compila#

bash
$ dataforge devops doctor

   loja 2.1.0  (Kiln, banco)

    um forge.toml
   a entrada existe (src/main.df)
   o código passa no 'check'
    Dockerfile
    .dockerignore
   nenhum segredo versionado
  ! não  .env.example    cada pessoa nova descobre as variáveis por tentativa
    pipeline de CI
    testes

  Para produção:
    ·  um proxy reverso na frente (TLS, compressão, HTTP/2)
    · a sessão do Kiln vive na memória do processo: UM processo por aplicação
    · 'Kiln.secure_headers()' como middleware de saída

  4 coisa(s) a resolver:
    1. gere com 'dataforge devops docker'
    2. sem ele, o '.env' entra na imagem  e continua nela depois de
       apagado numa camada seguinte
    3. gere com 'dataforge devops ci github'

Cada linha vermelha vem com o comando que a resolve. Um diagnóstico que diz "falta X" e não diz como obter X transfere o trabalho de volta.

Segredo versionado: a conferência é no git#

Não no disco. Um .env que existe e está no .gitignore é normal; um .env que o git rastreia já vazou — e apagá-lo agora não o tira do histórico.

`--host=0.0.0.0` é obrigatório dentro de um container#

Vale para o ignite do Kiln (at "0.0.0.0") e para a Vitrine (--host=0.0.0.0). O padrão é 127.0.0.1, que de dentro do container significa o próprio container.

O sintoma é enganoso: o log diz "no ar", a porta está publicada, e o curl de fora não recebe nada. Os artefatos gerados já trazem a forma certa.

dataforge
// 'at "0.0.0.0"' e obrigatorio dentro de um container.
ignite loja on 8080 at "0.0.0.0"

Kubernetes: o que os manifestos trazem#

yaml
spec:
  replicas: 3
  # 'maxUnavailable: 0' faz a atualizacao nao derrubar capacidade: o
  # pod novo entra em servico antes de o velho sair.
  strategy:
    rollingUpdate:
      maxUnavailable: 0

      securityContext:
        runAsNonRoot: true
        runAsUser: 1000
        fsGroup: 1000

Mais resources (requests e limits), readinessProbe, livenessProbe, e um hpa que escala por CPU. O ingress usa o domínio que você passar em --dominio=.

O YAML é escrito à mão#

Escrever o YAML à mão, em vez de depender de uma biblioteca, é a mesma política de zero dependências do resto da linguagem — e aqui ela cobra o preço de conhecer essas armadilhas em vez de herdá-las resolvidas.

Duas metades separadas de propósito#

ArquivoFaz
dataforge/devops.pyproduz texto
dataforge/devops_cli.pyescreve arquivo

A separação deixa os geradores testáveis sem tocar em disco — os 65 testes validam o compose com docker compose config, conferem os manifestos como dado e executam a sonda do HEALTHCHECK — e põe a política de "o que fazer quando o arquivo já existe" num lugar só.

O que ele não é#

Não é um orquestrador. Não sobe nada, não fala com nenhuma nuvem, não guarda estado. Um deploy mágico esconderia o que a imagem é, e a primeira vez que algo desse errado em produção não haveria onde olhar.

O que ele é: a diferença entre saber que você precisa de um readinessProbe e ter um.

Onde continuar#