404 Not Found

404 Not Found


nginx

Prática Completa: Implantação do Projeto OrderFlow

Implantação é a última milha — automação CI/CD, orquestração K8s e monitoramento com alertas garantem uma jornada sem interrupções das aplicações do desenvolvimento à produção.

1. O Que Você Vai Aprender


2. Uma História Real de um Engenheiro DevOps

(1) Dor: Implantação manual é como pisar em uma mina

Bob implantou manualmente o OrderFlow em produção: localmente mvn packagedocker build → fez push da imagem → kubectl apply → verificou health status. O processo inteiro leva 30 minutos e é propenso a erros: esquecer de atualizar a configuração, fazer push da versão errada da imagem ou Pods antigos não desligarem graciosamente durante rolling updates, resultando em erros 502.

(2) Soluções CI/CD

Serviço Completo para Linhas de Produção Automatizadas:

100%
graph LR
    A["Git Push"] --> B["GitHub Actions<br/>Build + Test"]
    B --> C["Docker Build<br/>+ Push para Registry"]
    C --> D["K8s Rolling<br/>Deploy"]
    D --> E["Health Check<br/>+ Smoke Test"]
    E --> F["Monitor<br/>Grafana"]

(3) Resultado

Depois que Bob configurou CI/CD, pushes de código dispararam implantações automáticas, completando o processo do código à produção em 5 minutos. Com HPA cuidando do auto-scaling e Prometheus cuidando dos alertas automáticos, Bob passou de "bombeiro" a "observador de monitoramento."


3. Pipeline CI/CD

(1) ▶ Exemplo: Workflow do GitHub Actions

YAML
# .github/workflows/deploy.yml
name: OrderFlow CI/CD

on:
  push:
    branches: [main]
    tags: ['v*']

env:
  REGISTRY: registry.example.com
  IMAGE_NAME: orderflow-service

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v4

    - name: Set up JDK 17
      uses: actions/setup-java@v4
      with:
        java-version: '17'
        distribution: 'temurin'

    - name: Run tests
      run: mvn verify -B

    - name: Build Docker image
      run: docker build -t ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ github.sha }} .

    - name: Login to Registry
      run: echo "${{ secrets.REGISTRY_PASSWORD }}" | docker login ${{ env.REGISTRY }} -u ${{ secrets.REGISTRY_USERNAME }} --password-stdin

    - name: Push image
      run: docker push ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ github.sha }}

  deploy:
    needs: build
    runs-on: ubuntu-latest
    if: startsWith(github.ref, 'refs/tags/v')
    steps:
    - uses: actions/checkout@v4

    - name: Deploy to Kubernetes
      run: |
        kubectl set image deployment/orderflow \
          orderflow=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ github.sha }} \
          -n orderflow
        kubectl rollout status deployment/orderflow -n orderflow --timeout=300s

    - name: Smoke test
      run: |
        sleep 10
        curl -sf https://api.orderflow.example.com/actuator/health | grep '"status":"UP"'

Saída:

TEXT
CONTAINER ID   IMAGE          STATUS         PORTS
abc123         nginx:latest   Up 2 hours     0.0.0.0:80->80/tcp
Estágio do Pipeline Operação Tratamento de Falha
Build + Test mvn verify Bloquear Implantação
Docker Build Build de imagem multi-stage Bloquear Implantação
Push Registry Push para repositório de imagens Retentar 3 vezes
K8s Deploy kubectl set image + rollout Rollback automático
Smoke Test Validação de Health Check Rollback + Notificação

4. Implantação K8s de Produção

(1) ▶ Exemplo: Deployment de Produção + HPA

YAML
apiVersion: apps/v1
kind: Deployment
metadata:
  name: orderflow
  namespace: orderflow
spec:
  replicas: 3
  selector:
    matchLabels: { app: orderflow }
  strategy:
    rollingUpdate: { maxUnavailable: 0, maxSurge: 1 }
  template:
    metadata:
      labels: { app: orderflow }
    spec:
      terminationGracePeriodSeconds: 60
      containers:
      - name: orderflow
        image: registry.example.com/orderflow-service:latest
        ports:
        - { containerPort: 8080 }
        - { containerPort: 8081 }
        envFrom:
        - configMapRef: { name: orderflow-config }
        - secretRef: { name: orderflow-secrets }
        resources:
          requests: { memory: "512Mi", cpu: "250m" }
          limits: { memory: "1Gi", cpu: "1000m" }
        lifecycle:
          preStop:
            exec:
              command: ["sh", "-c", "sleep 10"]
        livenessProbe:
          httpGet: { path: /actuator/health/liveness, port: 8080 }
          initialDelaySeconds: 60
          periodSeconds: 30
        readinessProbe:
          httpGet: { path: /actuator/health/readiness, port: 8080 }
          initialDelaySeconds: 30
          periodSeconds: 10
---
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: orderflow-hpa
  namespace: orderflow
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: orderflow
  minReplicas: 3
  maxReplicas: 10
  metrics:
  - type: Resource
    resource:
      name: cpu
      target:
        type: Utilization
        averageUtilization: 70
  - type: Resource
    resource:
      name: memory
      target:
        type: Utilization
        averageUtilization: 80

Saída:

TEXT
Deployment.apps/my-app created
Service/my-app-service exposed
Ingress/my-app-ingress created
Configuração K8s de Produção Valor Motivo
maxUnavailable: 0 Zero Downtime Sempre Manter o Número Alvo de Cópias
terminationGracePeriodSeconds: 60 Fechamento gracoso Aguardar limpeza das requisições
preStop: sleep 10 Término Atrasado K8s Continua Drenando Tráfego Mesmo Após Remoção do Service
resources.requests/limits Configurar QoS Garantir Alocação de Recursos + Limitar Excessos

(2) ▶ Exemplo: Ingress + TLS

YAML
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: orderflow-ingress
  namespace: orderflow
  annotations:
    cert-manager.io/cluster-issuer: letsencrypt-prod
    nginx.ingress.kubernetes.io/rate-limit: "100"
    nginx.ingress.kubernetes.io/ssl-redirect: "true"
spec:
  ingressClassName: nginx
  tls:
  - hosts: [api.orderflow.example.com]
    secretName: orderflow-tls
  rules:
  - host: api.orderflow.example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service: { name: orderflow, port: { number: 80 } }

Saída:

TEXT
Deployment.apps/my-app created
Service/my-app-service exposed
Ingress/my-app-ingress created

5. Lançamento de Observabilidade

(1) ▶ Exemplo: Prometheus + AlertManager

YAML
# prometheus.yml
scrape_configs:
- job_name: orderflow
  metrics_path: /actuator/prometheus
  scrape_interval: 15s
  kubernetes_sd_configs:
  - role: pod
    namespaces:
      names: [orderflow]
  relabel_configs:
  - source_labels: [__meta_kubernetes_pod_label_app]
    action: keep
    regex: orderflow

Saída:

TEXT
Deployment.apps/my-app created
Service/my-app-service exposed
Ingress/my-app-ingress created
YAML
# alert_rules.yml
groups:
- name: orderflow-slo
  rules:
  - alert: SLOErrorRateExceeded
    expr: |
      sum(rate(http_server_requests_seconds_total{namespace="orderflow",status=~"5.."}[5m]))
      / sum(rate(http_server_requests_seconds_total{namespace="orderflow"}[5m])) > 0.001
    for: 5m
    labels: { severity: critical }
    annotations:
      summary: "OrderFlow taxa de erro excede SLO (0,1%)"

  - alert: SLOLatencyExceeded
    expr: |
      histogram_quantile(0.99,
        sum(rate(http_server_requests_seconds_bucket{namespace="orderflow"}[5m])) by (le))
      > 0.1
    for: 5m
    labels: { severity: warning }
    annotations:
      summary: "OrderFlow latência P99 excede SLO (100ms)"

(2) ▶ Exemplo: Métricas do Dashboard SLO Grafana

Dashboard PromQL Alvo SLO
Latência P99 histogram_quantile(0.99, sum(rate(http_server_requests_seconds_bucket{namespace="orderflow"}[5m])) by (le)) < 100 ms
Taxa de Erro sum(rate(http_server_requests_seconds_total{namespace="orderflow",status=~"5.."}[5m])) / sum(rate(http_server_requests_seconds_total{namespace="orderflow"}[5m])) < 0,1%
Disponibilidade 1 - (sum(rate(http_server_requests_seconds_total{namespace="orderflow",status=~"5.."}[5m])) / sum(rate(http_server_requests_seconds_total{namespace="orderflow"}[5m]))) > 99,9%
Throughput de Pedidos rate(orderflow_orders_created_total[1m]) * 60 > 100/min

6. Hardening de Segurança de Produção

(1) ▶ Exemplo: NetworkPolicy + Pod Security

YAML
# NetworkPolicy: restringir acesso
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: orderflow-netpol
  namespace: orderflow
spec:
  podSelector:
    matchLabels: { app: orderflow }
  policyTypes: [Ingress]
  ingress:
  - from:
    - namespaceSelector:
        matchLabels: { name: ingress-nginx }
    ports:
    - { port: 8080, protocol: TCP }
  - from:
    - namespaceSelector:
        matchLabels: { name: monitoring }
    ports:
    - { port: 8081, protocol: TCP }
---
# Segurança do Pod: executar como não-root
apiVersion: v1
kind: LimitRange
metadata:
  name: orderflow-limits
  namespace: orderflow
spec:
  limits:
  - type: Container
    default:
      memory: "1Gi"
      cpu: "500m"
    defaultRequest:
      memory: "256Mi"
      cpu: "100m"

Saída:

TEXT
Deployment.apps/my-app created
Service/my-app-service exposed
Ingress/my-app-ingress created
Item de Hardening de Segurança Medida Descrição
Execução Não-root Dockerfile USER appuser Prevenir Escape de Contêiner
NetworkPolicy Restringir Fontes de Entrada Permitir Apenas Ingress e Monitoramento
Criptografia de Secret Configuração de Criptografia etcd Prevenir Secrets Armazenadas em Texto Puro
TLS Certificados automáticos cert-manager Transmissão Criptografada
Limites de Recursos LimitRange Prevenir Contenção de Recursos

7. Exemplo Completo: Checklist Completo de Implantação do OrderFlow

YAML
# k8s/orderflow-complete.yaml
---
apiVersion: v1
kind: Namespace
metadata:
  name: orderflow
  labels: { name: orderflow }

---
apiVersion: v1
kind: ConfigMap
metadata: { name: orderflow-config, namespace: orderflow }
data:
  SPRING_PROFILES_ACTIVE: "prod"
  DB_HOST: "mysql.orderflow.svc.cluster.local"
  REDIS_HOST: "redis.orderflow.svc.cluster.local"
  MANAGEMENT_SERVER_PORT: "8081"

---
apiVersion: v1
kind: Secret
metadata: { name: orderflow-secrets, namespace: orderflow }
type: Opaque
data:
  DB_PASSWORD: <base64-encoded>
  REDIS_PASSWORD: <base64-encoded>
  JWT_PRIVATE_KEY: <base64-encoded>

---
apiVersion: apps/v1
kind: Deployment
metadata: { name: orderflow, namespace: orderflow }
spec:
  replicas: 3
  selector: { matchLabels: { app: orderflow } }
  strategy: { rollingUpdate: { maxUnavailable: 0, maxSurge: 1 } }
  template:
    metadata: { labels: { app: orderflow } }
    spec:
      terminationGracePeriodSeconds: 60
      containers:
      - name: orderflow
        image: registry.example.com/orderflow-service:1.0.0
        ports: [{ containerPort: 8080 }, { containerPort: 8081 }]
        envFrom:
        - { configMapRef: { name: orderflow-config } }
        - { secretRef: { name: orderflow-secrets } }
        resources:
          requests: { memory: "512Mi", cpu: "250m" }
          limits: { memory: "1Gi", cpu: "1000m" }
        lifecycle:
          preStop: { exec: { command: ["sh", "-c", "sleep 10"] } }
        livenessProbe:
          httpGet: { path: /actuator/health/liveness, port: 8080 }
          initialDelaySeconds: 60; periodSeconds: 30
        readinessProbe:
          httpGet: { path: /actuator/health/readiness, port: 8080 }
          initialDelaySeconds: 30; periodSeconds: 10

---
apiVersion: v1
kind: Service
metadata: { name: orderflow, namespace: orderflow }
spec:
  selector: { app: orderflow }
  ports:
  - { name: http, port: 80, targetPort: 8080 }
  - { name: management, port: 8081, targetPort: 8081 }

---
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata: { name: orderflow-hpa, namespace: orderflow }
spec:
  scaleTargetRef: { apiVersion: apps/v1, kind: Deployment, name: orderflow }
  minReplicas: 3
  maxReplicas: 10
  metrics:
  - { type: Resource, resource: { name: cpu, target: { type: Utilization, averageUtilization: 70 } } }

---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: orderflow-ingress
  namespace: orderflow
  annotations:
    cert-manager.io/cluster-issuer: letsencrypt-prod
spec:
  ingressClassName: nginx
  tls:
  - { hosts: [api.orderflow.example.com], secretName: orderflow-tls }
  rules:
  - host: api.orderflow.example.com
    http:
      paths:
      - { path: /, pathType: Prefix, backend: { service: { name: orderflow, port: { number: 80 } } } }

❓ Perguntas Frequentes

P Qual escolher, GitHub Actions ou Jenkins?
R GitHub Actions integra-se ao ecossistema GitHub e é fácil de configurar, sendo adequado para projetos de pequeno e médio porte. Jenkins oferece recursos mais poderosos mas é mais complexo de configurar, sendo adequado para grandes empresas. Se você já tem um repositório GitHub, recomendamos usar GitHub Actions.
P Como garantir zero downtime durante rolling updates?
R 1) maxUnavailable=0; 2) Usar readinessProbe para garantir que Pods estejam prontos antes de serem adicionados ao Service; 3) Definir preStop sleep 10 para permitir que o K8s drene requisições após o Pod ser removido do Service; 4) Aplicar a configuração server.shutdown=graceful.
P Como definir minReplicas e maxReplicas para o HPA?
R minReplicas = número de réplicas necessárias para carga normal (OrderFlow = 3); maxReplicas = carga estimada de pico (OrderFlow = 10). Ajuste com base em dados de monitoramento históricos. A utilização alvo de CPU recomendada é 70%.
P Quais são as melhores práticas para gerenciamento de secrets?
R 1) K8s Secrets + criptografia etcd (abordagem básica); 2) External Secrets Operator + AWS Secrets Manager/Vault (abordagem recomendada); 3) Sealed Secrets (amigável para GitOps). Não faça commit de Secrets em texto puro no Git.
P Como implementar implantações blue-green ou canary?
R O K8s não suporta nativamente implantações blue-green ou canary; ferramentas como Istio ou Argo Rollouts são necessárias. Argo Rollouts suporta canary (migração gradual de tráfego) e blue-green (troca instantânea), com validação via Prometheus.
P O que os alertas de monitoramento em ambiente de produção devem cobrir?
R Três categorias principais: 1) Alertas SLO (latência P99, taxa de erro, disponibilidade); 2) Alertas de recursos (CPU > 80%, memória > 85%, disco > 90%); 3) Alertas de negócio (queda anormal no volume de pedidos, declínio na taxa de sucesso de pagamentos).

📖 Resumo


📝 Exercícios

  1. Problema Básico (Dificuldade: ⭐): Escreva um workflow do GitHub Actions para testar e construir automaticamente uma imagem Docker após o push de código.

  2. Exercício Avançado (Dificuldade: ⭐⭐): Escreva um YAML completo de implantação K8s de produção (Deployment + Service + Ingress + HPA + ConfigMap + Secret) para implementar rolling updates com zero downtime.

  3. Desafio (Dificuldade: ⭐⭐⭐): Configure um sistema de observabilidade completo (Prometheus + Grafana + AlertManager + Jaeger), configure dashboards SLO e regras de alerta e simule uma falha para testar as capacidades de alerta e recuperação automática.

Web-Tutorial.com

Equipe Técnica Web-Tutorial

Uma plataforma de tutoriais mantida por diversos desenvolvedores. Cada tutorial é escrito e revisado por profissionais da área correspondente. Trabalhamos para manter nosso conteúdo preciso e confiável — se encontrar algum problema, avise-nos.

100%