O que é DevOps e Por Que Importa
DevOps é uma cultura que unifica desenvolvimento (Dev) e operações (Ops), quebrando silos organizacionais e promovendo colaboração contínua. O objetivo é acelerar a entrega de software com qualidade, automatizando processos desde o código até a produção. Não é apenas uma ferramenta ou cargo, mas uma mentalidade que valoriza comunicação, automação, medição e compartilhamento (CAMS).
Na prática, DevOps resolve problemas clássicos: deploys demorados, ambientes inconsistentes, falta de visibilidade sobre falhas e sobrecarga operacional. Empresas que adotam DevOps reduzem o tempo de lançamento de funcionalidades de semanas para horas, aumentam a taxa de sucesso de deploys e respondem a incidentes mais rapidamente.
Princípios Fundamentais
- Integração e Entrega Contínua (CI/CD): automatizar build, testes e deploy
- Infraestrutura como Código (IaC): versionar e automatizar infraestrutura
- Monitoramento e Feedback: observabilidade em tempo real
- Colaboração: times multifuncionais com responsabilidade compartilhada
CI/CD: Automatizando o Pipeline
CI/CD é o coração do DevOps. Integração Contínua (CI) automatiza a compilação e testes a cada commit, detectando bugs cedo. Entrega Contínua (CD) garante que o código esteja sempre pronto para deploy, enquanto Deploy Contínuo automatiza o envio para produção.
Ferramentas populares incluem Jenkins, GitLab CI, GitHub Actions e CircleCI. Vamos criar um pipeline completo com GitHub Actions que testa e faz deploy de uma aplicação Node.js:
# .github/workflows/ci-cd.yml
name: CI/CD Pipeline
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Setup Node.js
uses: actions/setup-node@v3
with:
node-version: '18'
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Run tests
run: npm test
- name: Run linter
run: npm run lint
build-and-deploy:
needs: test
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/main'
steps:
- uses: actions/checkout@v3
- name: Build Docker image
run: docker build -t myapp:${{ github.sha }} .
- name: Login to Docker Hub
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: Push image
run: |
docker tag myapp:${{ github.sha }} myuser/myapp:latest
docker push myuser/myapp:latest
- name: Deploy to production
run: |
kubectl set image deployment/myapp \
myapp=myuser/myapp:latest \
--record
Este pipeline executa testes em cada push, constrói a imagem Docker apenas na branch principal e faz deploy automático no Kubernetes. A separação em jobs garante que o deploy só ocorra se os testes passarem.
Estratégias de Deploy Avançadas
Blue-Green Deployment: mantém dois ambientes idênticos (blue e green). O tráfego é redirecionado instantaneamente entre eles, permitindo rollback imediato.
Canary Deployment: libera gradualmente para uma pequena porcentagem de usuários antes do rollout completo, reduzindo riscos.
# Exemplo de Canary com Kubernetes e Istio
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
name: myapp-canary
spec:
hosts:
- myapp.example.com
http:
- match:
- headers:
user-type:
exact: beta
route:
- destination:
host: myapp
subset: v2
- route:
- destination:
host: myapp
subset: v1
weight: 90
- destination:
host: myapp
subset: v2
weight: 10
Infraestrutura como Código com Terraform
IaC trata infraestrutura como software versionado, reproduzível e testável. Terraform é a ferramenta líder, usando HCL (HashiCorp Configuration Language) para declarar recursos em múltiplos provedores de nuvem.
Um exemplo real provisionando infraestrutura AWS completa:
# main.tf
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
}
backend "s3" {
bucket = "terraform-state-prod"
key = "infrastructure/terraform.tfstate"
region = "us-east-1"
}
}
provider "aws" {
region = var.aws_region
}
# VPC e networking
resource "aws_vpc" "main" {
cidr_block = "10.0.0.0/16"
enable_dns_hostnames = true
tags = {
Name = "production-vpc"
Environment = "production"
}
}
resource "aws_subnet" "public" {
count = 2
vpc_id = aws_vpc.main.id
cidr_block = "10.0.${count.index + 1}.0/24"
availability_zone = data.aws_availability_zones.available.names[count.index]
map_public_ip_on_launch = true
}
# EKS Cluster
resource "aws_eks_cluster" "main" {
name = "production-cluster"
role_arn = aws_iam_role.eks_cluster.arn
version = "1.28"
vpc_config {
subnet_ids = aws_subnet.public[*].id
}
depends_on = [
aws_iam_role_policy_attachment.eks_cluster_policy
]
}
# Node Group
resource "aws_eks_node_group" "main" {
cluster_name = aws_eks_cluster.main.name
node_group_name = "production-nodes"
node_role_arn = aws_iam_role.eks_nodes.arn
subnet_ids = aws_subnet.public[*].id
scaling_config {
desired_size = 3
max_size = 5
min_size = 2
}
instance_types = ["t3.medium"]
}
# Outputs para usar em outros módulos
output "cluster_endpoint" {
value = aws_eks_cluster.main.endpoint
}
output "cluster_name" {
value = aws_eks_cluster.main.name
}
Comandos essenciais do Terraform:
# Inicializar e baixar providers
terraform init
# Planejar mudanças (dry-run)
terraform plan
# Aplicar mudanças
terraform apply
# Destruir recursos
terraform destroy
# Importar recurso existente
terraform import aws_instance.example i-1234567890abcdef0
O uso de módulos reutilizáveis e remote state (S3 backend) permite colaboração eficiente entre times. Sempre versione código IaC no Git e use pull requests com terraform plan nos comentários.
Observabilidade: Monitoramento e Logging
Observabilidade vai além de monitoramento tradicional, combinando métricas, logs e traces distribuídos. O stack mais usado é Prometheus (métricas), Grafana (visualização), Loki (logs) e Jaeger (tracing).
Implementando Métricas com Prometheus
# app.py - Aplicação Flask com métricas Prometheus
from flask import Flask, request
from prometheus_client import Counter, Histogram, generate_latest
import time
app = Flask(__name__)
# Métricas customizadas
REQUEST_COUNT = Counter(
'http_requests_total',
'Total de requisições HTTP',
['method', 'endpoint', 'status']
)
REQUEST_DURATION = Histogram(
'http_request_duration_seconds',
'Duração das requisições HTTP',
['method', 'endpoint']
)
@app.before_request
def before_request():
request.start_time = time.time()
@app.after_request
def after_request(response):
duration = time.time() - request.start_time
REQUEST_DURATION.labels(
method=request.method,
endpoint=request.path
).observe(duration)
REQUEST_COUNT.labels(
method=request.method,
endpoint=request.path,
status=response.status_code
).inc()
return response
@app.route('/api/users')
def get_users():
return {'users': ['Alice', 'Bob']}
@app.route('/metrics')
def metrics():
return generate_latest()
if __name__ == '__main__':
app.run(host='0.0.0.0', port=5000)
Configuração do Prometheus para scraping:
# prometheus.yml
global:
scrape_interval: 15s
evaluation_interval: 15s
scrape_configs:
- job_name: 'flask-app'
static_configs:
- targets: ['app:5000']
metrics_path: '/metrics'
- job_name: 'kubernetes-pods'
kubernetes_sd_configs:
- role: pod
relabel_configs:
- source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_scrape]
action: keep
regex: true
Alertas Inteligentes
# alerts.yml - Regras de alerta Prometheus
groups:
- name: application_alerts
interval: 30s
rules:
- alert: HighErrorRate
expr: |
rate(http_requests_total{status=~"5.."}[5m])
/ rate(http_requests_total[5m]) > 0.05
for: 5m
labels:
severity: critical
annotations:
summary: "Taxa de erro alta em {{ $labels.instance }}"
description: "{{ $value | humanizePercentage }} de erros nos últimos 5 minutos"
- alert: PodCrashLooping
expr: rate(kube_pod_container_status_restarts_total[15m]) > 0
for: 5m
labels:
severity: warning
annotations:
summary: "Pod {{ $labels.pod }} reiniciando continuamente"
Conclusão
- DevOps é cultura antes de tecnologia: CI/CD, IaC e observabilidade são ferramentas que viabilizam colaboração, automação e feedback contínuo entre desenvolvimento e operações
- Automatize tudo: desde testes unitários até provisionamento de infraestrutura, automação reduz erros humanos e acelera entregas com qualidade consistente
- Meça para melhorar: observabilidade com métricas, logs e traces permite decisões baseadas em dados reais, identificando gargalos e antecipando problemas antes de impactar usuários