<h2>SRE: O Fundamento para Confiabilidade em Produção</h2>
<p>Site Reliability Engineering (SRE) é uma disciplina que aplica princípios de engenharia de software à operação de sistemas. Criada pelo Google, ela reconhece uma verdade fundamental: sistemas perfeitos não existem. Em vez de buscar confiabilidade absoluta (impossível e economicamente inviável), SRE define o nível de confiabilidade que o negócio realmente necessita e trabalha para mantê-lo de forma sustentável.</p>
<p>A proposta de SRE é revolucionária porque muda o paradigma. Não se trata mais de "quanto mais disponibilidade, melhor". Em vez disso, perguntamos: "Qual é a disponibilidade adequada para este serviço?" e "Como operamos de forma eficiente dentro dessa margem?". Isso cria um contrato claro entre produto, negócio e operações, eliminando conflitos invisíveis e permitindo que engenheiros façam escolhas arquiteturais informadas.</p>
<h2>SLI, SLO e SLA: A Tríade de Confiabilidade</h2>
<h3>O que é um SLI (Service Level Indicator)?</h3>
<p>Um SLI é uma métrica que mede o comportamento observável do seu sistema. É um número entre 0 e 100% que indica "o quanto de tempo meu sistema se comportou como esperado?". SLIs não são opiniões — são dados mensuráveis e objetivos extraídos diretamente da observabilidade.</p>
<p>Exemplos concretos de SLIs incluem: latência de requisições HTTP (percentual de requisições respondidas em menos de 200ms), taxa de erro (percentual de requisições que não retornaram 5xx), disponibilidade de conexões de banco de dados, ou taxa de sucesso de transações de pagamento. A escolha do SLI deve refletir o que o usuário realmente percebe.</p>
<h3>O que é um SLO (Service Level Objective)?</h3>
<p>Um SLO é uma meta que você se compromete a atingir para um SLI específico. Se o SLI é "percentual de requisições com latência < 200ms", o SLO seria algo como "99.9% das requisições devem responder em menos de 200ms, medido em janelas de 30 dias". O SLO transforma uma métrica em um alvo negociado.</p>
<p>SLOs devem ser escolhidos estrategicamente. Não defina SLOs que são impossíveis de manter — isto causa esgotamento. Defina SLOs que seu negócio realmente necessita. Um serviço crítico pode ter 99.99% de disponibilidade, enquanto uma API interna pode ter 99.5%. A diferença é enorme em custo operacional.</p>
<h3>O que é um SLA (Service Level Agreement)?</h3>
<p>Um SLA é um contrato legal ou comercial com consequências financeiras ou de outro tipo se não for cumprido. Um SLA geralmente é mais restritivo que o SLO correspondente (para deixar margem de segurança). Por exemplo: seu SLO pode ser 99.95%, mas seu SLA com clientes é 99.9% — isso deixa 0.05% como amortecedor.</p>
<p>SLAs existem principalmente em contextos B2B, onde você oferece um serviço a clientes externos. SLOs existem em contextos onde você define metas internas. Muitas organizações confundem os termos, o que causa problemas. Deixe claro: SLA = contrato com consequências; SLO = meta operacional interna.</p>
<h2>Medindo SLIs na Prática</h2>
<h3>Exemplos de SLIs Bem Estruturados</h3>
<p>A escolha do SLI determinará tudo que vem depois. Um bom SLI deve ser: (1) mensurável com ferramentas que você já possui, (2) correlacionado com a satisfação do usuário, e (3) acionável — você consegue fazer algo quando ele piora.</p>
<p>SLIs ruins geralmente medem componentes de infraestrutura em vez de experiência do usuário. "CPU em 85%" é um indicador de saúde, não de confiabilidade. "99% das requisições respondidas em menos de 500ms" é um bom SLI.</p>
<pre><code class="language-python"># Exemplo: Calculando SLI de latência usando Prometheus
Este código coleta métricas e calcula o percentual de requisições rápidas
from prometheus_client import Counter, Histogram, start_http_server
import time
Histograma para rastrear latências
request_latency = Histogram(
'http_request_duration_seconds',
'Latência de requisições HTTP',
buckets=(0.1, 0.2, 0.5, 1.0, 2.0)
)
Contador para requisições bem-sucedidas
requests_success = Counter(
'http_requests_success_total',
'Total de requisições bem-sucedidas'
)
Contador para requisições falhadas
requests_failed = Counter(
'http_requests_failed_total',
'Total de requisições falhadas'
)
def simulated_request():
"""Simula uma requisição e registra sua latência"""
import random
start = time.time()
95% das requisições levam entre 50 e 200ms
5% levam mais de 500ms
if random.random() < 0.95:
time.sleep(random.uniform(0.05, 0.2))
requests_success.inc()
else:
time.sleep(random.uniform(0.5, 2.0))
requests_failed.inc()
duration = time.time() - start
request_latency.observe(duration)
Iniciando servidor Prometheus
if __name__ == '__main__':
start_http_server(8000)
print("Métricas disponíveis em http://localhost:8000/metrics")
Loop simulando requisições
for _ in range(100):
simulated_request()</code></pre>
<h3>Instrumentação e Coleta de Dados</h3>
<p>Para medir SLIs, você precisa de instrumentação. A abordagem mais comum é usar logs estruturados ou métricas de tempo real. Logs são úteis para análise histórica, mas métricas são melhores para alertas em tempo real.</p>
<pre><code class="language-python"># Exemplo: Capturando SLI de taxa de erro com logging estruturado
import json
import logging
from datetime import datetime
Configurar logger estruturado
class StructuredLogger:
def __init__(self, name):
self.logger = logging.getLogger(name)
handler = logging.StreamHandler()
handler.setFormatter(logging.Formatter('%(message)s'))
self.logger.addHandler(handler)
self.logger.setLevel(logging.INFO)
def log_request(self, endpoint, status_code, duration_ms, user_id):
event = {
'timestamp': datetime.utcnow().isoformat(),
'endpoint': endpoint,
'status_code': status_code,
'duration_ms': duration_ms,
'user_id': user_id,
'success': status_code < 400
}
self.logger.info(json.dumps(event))
Usar o logger
logger = StructuredLogger('api')
Simulando requisições
logger.log_request('/api/users', 200, 145, 'user_123')
logger.log_request('/api/products', 500, 2340, 'user_456')
logger.log_request('/api/orders', 200, 256, 'user_789')
Saída:
{"timestamp": "2024-01-15T10:30:00.123456", "endpoint": "/api/users",
"status_code": 200, "duration_ms": 145, "user_id": "user_123", "success": true}</code></pre>
<h2>Error Budget: O Controle Financeiro de Falhas</h2>
<h3>O Conceito de Error Budget</h3>
<p>Um error budget é literalmente o "orçamento de erros" que você pode ter sem violar seu SLO. Se seu SLO é 99.9% de disponibilidade mensal, você tem um orçamento de 0.1% de downtime. Em 30 dias, isso equivale a aproximadamente 43 minutos de downtime permissível.</p>
<p>O error budget muda radicalmente como você toma decisões. Se seu erro budget está se esgotando (poucas horas restantes), você para deployments. Se seu error budget está abundante (semanas restantes), você pode fazer experiências, refatorar agressivamente ou deployar features mais frequentemente. O error budget alinha os incentivos de produto, desenvolvimento e operações.</p>
<h3>Calculando e Monitorando Error Budget</h3>
<pre><code class="language-python"># Exemplo: Calculadora de error budget e monitoramento
from datetime import datetime, timedelta
class ErrorBudgetTracker:
def __init__(self, slo_percentage, period_days=30):
"""
slo_percentage: seu SLO em percentual (ex: 99.9)
period_days: período de medição (geralmente 30 dias)
"""
self.slo_percentage = slo_percentage
self.period_days = period_days
Calcular o orçamento máximo de erros
Se SLO é 99.9%, o error budget é 0.1%
self.error_budget_percentage = 100 - slo_percentage
Converter em minutos (para um mês de 30 dias)
total_minutes = period_days 24 60
self.budget_minutes = (self.error_budget_percentage / 100) * total_minutes
self.remaining_budget = self.budget_minutes
def record_downtime(self, downtime_minutes):
"""Registra um período de downtime"""
self.remaining_budget -= downtime_minutes
utilization = ((self.budget_minutes - self.remaining_budget) / self.budget_minutes) * 100
return {
'downtime_recorded_minutes': downtime_minutes,
'remaining_budget_minutes': max(0, self.remaining_budget),
'budget_utilization_percent': round(utilization, 2),
'status': self._get_status()
}
def _get_status(self):
"""Retorna status do error budget"""
if self.remaining_budget <= 0:
return 'EXHAUSTED'
elif self.remaining_budget < (self.budget_minutes * 0.1):
return 'CRITICAL'
elif self.remaining_budget < (self.budget_minutes * 0.3):
return 'LOW'
else:
return 'HEALTHY'
Exemplo de uso
tracker = ErrorBudgetTracker(slo_percentage=99.9, period_days=30)
print(f"Error Budget Total: {tracker.budget_minutes:.1f} minutos (~{tracker.budget_minutes/60:.1f} horas)")
print(f"SLO: {tracker.slo_percentage}%\n")
Simulando downtimes
incidents = [
('Database crash', 15),
('Network issue', 8),
('Bad deployment', 5),
]
for incident_name, minutes in incidents:
result = tracker.record_downtime(minutes)
print(f"Incidente: {incident_name}")
print(f" Status: {result['status']}")
print(f" Restante: {result['remaining_budget_minutes']:.1f} minutos")
print(f" Utilização: {result['budget_utilization_percent']}%\n")
Saída esperada:
Error Budget Total: 43.2 minutos (~0.7 horas)
SLO: 99.9%
#
Incidente: Database crash
Status: HEALTHY
Restante: 28.2 minutos
Utilização: 34.72%
#
Incidente: Network issue
Status: LOW
Restante: 20.2 minutos
Utilização: 53.24%
#
Incidente: Bad deployment
Status: CRITICAL
Restante: 15.2 minutos
Utilização: 64.81%</code></pre>
<h3>Usando Error Budget para Tomar Decisões</h3>
<p>O error budget não é apenas uma métrica — é um instrumento de governança. Quando o error budget está saudável, você investe em melhorias de produto. Quando está crítico, você congela deploys e foca em confiabilidade. Quando está esgotado, você trabalha em modo de crise.</p>
<pre><code class="language-python"># Exemplo: Sistema que ajusta comportamento baseado em error budget
class DeploymentGatekeeper:
def __init__(self, tracker):
self.tracker = tracker
def can_deploy_feature(self):
"""Decide se é seguro deployar uma feature nova"""
if self.tracker.remaining_budget < (self.tracker.budget_minutes * 0.2):
Menos de 20% do budget restante
return False, "Error budget crítico. Apenas fixes de segurança."
return True, "Deployment autorizado."
def deployment_strategy(self):
"""Recomenda estratégia de deployment baseada em budget"""
budget_percent = (self.tracker.remaining_budget / self.tracker.budget_minutes) * 100
if budget_percent > 50:
return "canary" # Pequena porção, rápido feedback
elif budget_percent > 20:
return "blue_green" # Mais controlado
else:
return "manual_approval" # Aprovação humana necessária
Usando o gatekeeper
gatekeeper = DeploymentGatekeeper(tracker)
authorized, reason = gatekeeper.can_deploy_feature()
print(f"Deploy autorizado: {authorized}")
print(f"Razão: {reason}")
print(f"Estratégia recomendada: {gatekeeper.deployment_strategy()}")</code></pre>
<h2>Implementando SRE em Uma Arquitetura Real</h2>
<h3>Arquitetura de Observabilidade</h3>
<p>Para colocar SRE em prática, você precisa de uma pilha de observabilidade robusta. Isso inclui métricas (Prometheus), logs (ELK, Loki) e traces distribuídos (Jaeger). Sem observabilidade, você não consegue medir SLIs, portanto não consegue operar SRE.</p>
<pre><code class="language-python"># Exemplo: Instrumentação completa de uma aplicação Flask com SRE em mente
from flask import Flask, request, jsonify
from prometheus_client import Counter, Histogram, Gauge, generate_latest
import time
import random
app = Flask(__name__)
Métricas Prometheus
http_requests_total = Counter(
'http_requests_total',
'Total de requisições HTTP',
['method', 'endpoint', 'status']
)
http_request_duration = Histogram(
'http_request_duration_seconds',
'Duração das requisições HTTP',
['endpoint'],
buckets=(0.05, 0.1, 0.25, 0.5, 1.0, 2.5)
)
database_connections = Gauge(
'database_connections_active',
'Conexões ativas com banco de dados'
)
Middleware para capturar métricas
@app.before_request
def before_request():
request.start_time = time.time()
@app.after_request
def after_request(response):
duration = time.time() - request.start_time
Registrar métrica de duração
http_request_duration.labels(endpoint=request.path).observe(duration)
Registrar métrica de contagem
http_requests_total.labels(
method=request.method,
endpoint=request.path,
status=response.status_code
).inc()
return response
Endpoints da aplicação
@app.route('/api/users/<user_id>', methods=['GET'])
def get_user(user_id):
"""Buscar um usuário por ID"""
Simular latência variável
time.sleep(random.uniform(0.05, 0.15))
2% de chance de erro
if random.random() < 0.02:
return jsonify({'error': 'Database error'}), 500
return jsonify({'id': user_id, 'name': 'John Doe'}), 200
@app.route('/api/health', methods=['GET'])
def health_check():
"""Healthcheck simples"""
database_connections.set(random.randint(5, 20))
return jsonify({'status': 'healthy'}), 200
@app.route('/metrics', methods=['GET'])
def metrics():
"""Endpoint Prometheus para scraping de métricas"""
return generate_latest()
if __name__ == '__main__':
print("Iniciando aplicação SRE-ready")
print("- Métricas: http://localhost:5000/metrics")
print("- Health: http://localhost:5000/api/health")
print("- API: http://localhost:5000/api/users/<id>")
app.run(debug=False, port=5000)</code></pre>
<h3>Alertas Baseados em SLO</h3>
<p>Alertas tradicionais monitoram componentes. Alertas SRE monitoram SLIs. Quando seu SLI se desvia do SLO, você precisa saber rapidamente. A chave é criar alertas que identificam problemas que afetam o usuário, não problemas em camadas de infraestrutura.</p>
<pre><code class="language-yaml"># Exemplo: Regras de alerta Prometheus para SRE
Arquivo: prometheus-sre-rules.yml
groups:
- name: sre_alerts
interval: 30s
rules:
SLI: Taxa de erro HTTP
- alert: HighErrorRate
expr: |
(
sum(rate(http_requests_total{status=~"5.."}[5m]))
/
sum(rate(http_requests_total[5m]))
) > 0.001
for: 2m
annotations:
summary: "Taxa de erro acima de 0.1% (SLO violado)"
description: "{{ $value | humanizePercentage }} de erro nos últimos 5 minutos"
SLI: Latência P95
- alert: HighLatencyP95
expr: |
histogram_quantile(0.95,
sum(rate(http_request_duration_seconds_bucket[5m])) by (le)
) > 0.2
for: 5m
annotations:
summary: "P95 de latência acima de 200ms"
description: "P95: {{ $value }}s"
Error Budget: Taxa de consumo
- alert: ErrorBudgetBurnRateTooHigh
expr: |
Queimando mais de 10% do budget mensal por dia
(sum(rate(http_requests_total{status=~"5.."}[1h]))
/ sum(rate(http_requests_total[1h]))) > 0.001
for: 1h
annotations:
summary: "Taxa de consumo de error budget muito alta"
description: "Em 30 dias, error budget será esgotado"
Alerta crítico: Error budget quase esgotado
- alert: ErrorBudgetCritical
expr: |
Se mantiver esse burn rate, error budget acaba em 3 dias
(ALERTS{severity="critical"}) > 0
annotations:
summary: "Error budget será esgotado em menos de 3 dias"
description: "CONGELE deployments, focue em confiabilidade"</code></pre>
<h2>Cultura e Tomada de Decisão com SRE</h2>
<h3>Alinhando Incentivos</h3>
<p>SRE funciona porque cria um contrato claro. Desenvolvimento sabe que tem um budget para "quebrar coisas" (error budget), operações sabe exatamente quanto pode tolerar, e produto entende o trade-off entre features e confiabilidade. Quando o error budget está saudável, todos ganham: produto entrega features, desenvolvimento itera rapidamente, operações opera de forma sustentável.</p>
<p>O erro mais comum é tentar alcançar 100% de uptime. Isso é impossível e desperdiça recursos enormes. Um SLO de 99.95% (52 minutos de downtime por ano) é completamente razoável para a maioria dos serviços. Invista os recursos economizados em experiência do usuário, ao invés de redundância infinita.</p>
<pre><code class="language-python"># Exemplo: Framework de decisão SRE
class SREDecisionFramework:
def __init__(self, slo_tracker, incident_count_week):
self.tracker = slo_tracker
self.incidents_week = incident_count_week
def should_prioritize_reliability_work(self):
"""Decide se é hora de parar de adicionar features e focar em confiabilidade"""
Critério 1: Error budget crítico
budget_health = (self.tracker.remaining_budget / self.tracker.budget_minutes)
Critério 2: Muitos incidents
too_many_incidents = self.incidents_week > 3
return budget_health < 0.3 or too_many_incidents
def post_incident_decision(self, incident_severity):
"""Decide ações após um incidente"""
if incident_severity == 'critical' and self.tracker.remaining_budget < (self.tracker.budget_minutes * 0.1):
return {
'action': 'IMPLEMENT_FIX',
'timeline': 'IMMEDIATE',
'freeze_features': True,
'reason': 'Restaurar confiabilidade do sistema'
}
elif incident_severity == 'minor':
return {
'action': 'POSTMORTEM',
'timeline': '48_HOURS',
'freeze_features': False,
'reason': 'Aprender e melhorar processos'
}
else:
return {
'action': 'INVESTIGATE',
'timeline': '24_HOURS',
'freeze_features': False,
'reason': 'Entender causa raiz'
}
Usar o framework
framework = SREDecisionFramework(tracker, incident_count_week=2)
print(f"Priorizar confiabilidade: {framework.should_prioritize_reliability_work()}")
print(f"Ação pós-incidente: {framework.post_incident_decision('critical')}")</code></pre>
<h2>Conclusão</h2>
<p>Os três pontos-chave que você deve internalizar sobre SRE são: (1) <strong>SLI, SLO e SLA são contratos diferentes com propósitos diferentes</strong> — SLI mede realidade, SLO define meta operacional, SLA é contrato legal. Confundir os termos cria ambiguidade perigosa; (2) <strong>Error budget transforma como você toma decisões</strong> — não se trata de "quanto mais uptime, melhor", mas sim "qual é o nível de confiabilidade necessário e como operamos eficientemente dentro dessa margem?", eliminando conflitos invisíveis entre produto e operações; (3) <strong>SRE requer observabilidade obsessiva</strong> — você não consegue operar SRE sem métricas estruturadas, logs e traces distribuídos que permitam medir SLIs em tempo real e tomar decisões baseadas em dados, não em intuição.</p>
<h2>Referências</h2>
<ul>
<li><a href="https://cloud.google.com/blog/products/devops-sre" target="_blank" rel="noopener noreferrer">Google Cloud - SRE Fundamentals</a></li>
<li><a href="https://sre.google/books/" target="_blank" rel="noopener noreferrer">Site Reliability Engineering: How Google Runs Production Systems</a></li>
<li><a href="https://prometheus.io/docs/" target="_blank" rel="noopener noreferrer">The Prometheus Monitoring System Official Documentation</a></li>
<li><a href="https://www.oreilly.com/library/view/the-sre-workbook/9781492029496/" target="_blank" rel="noopener noreferrer">Error Budgets and Burn Rates - O'Reilly</a></li>
<li><a href="https://www.honeycomb.io/learn/" target="_blank" rel="noopener noreferrer">Observability Engineering with Honeycomb</a></li>
</ul>
<p><!-- FIM --></p>