<h2>Circuit Breaker em Istio: Proteção Contra Falhas em Cascata</h2>
<p>O Circuit Breaker é um padrão de design que atua como um "disjuntor" para suas requisições. Quando um serviço downstream está com problemas, ao invés de continuar enviando requisições que falharão, o Circuit Breaker detecta o padrão de falha e temporariamente impede novas tentativas, evitando desperdício de recursos e degradação em cascata da arquitetura inteira.</p>
<p>Em Istio, o Circuit Breaker é configurado através do recurso <code>DestinationRule</code>. Você define limites como número de conexões simultâneas, requisições pendentes e detecta outliers (hosts que se comportam mal) removendo-os do pool de balanceamento. O comportamento é automático e transparente para a aplicação, funcionando no nível da malha.</p>
<h3>Configurando um Circuit Breaker básico</h3>
<p>Considere um cenário onde você tem um serviço <code>payment-api</code> que frequentemente falha sob carga. Você quer proteger seus consumidores:</p>
<pre><code class="language-yaml">apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
name: payment-api-circuit-breaker
namespace: production
spec:
host: payment-api
trafficPolicy:
connectionPool:
http:
http1MaxPendingRequests: 100
maxRequestsPerConnection: 2
h2UpgradePolicy: UPGRADE
tcp:
maxConnections: 100
outlierDetection:
consecutive5xxErrors: 5
interval: 30s
baseEjectionTime: 30s
maxEjectionPercent: 50
minRequestVolume: 5
splitExternalLocalOriginErrors: true</code></pre>
<p>Nesta configuração, o Circuit Breaker:</p>
<ul>
<li>Limita 100 requisições HTTP pendentes</li>
<li>Detecta 5 erros 5xx consecutivos e remove o host por 30 segundos</li>
<li>Nunca remove mais de 50% dos hosts disponíveis</li>
<li>Requer no mínimo 5 requisições antes de considerar outliers</li>
</ul>
<h3>Entendendo os parâmetros de Outlier Detection</h3>
<p>O <code>outlierDetection</code> é o coração inteligente do Circuit Breaker. A propriedade <code>consecutive5xxErrors: 5</code> significa que após 5 falhas 5xx consecutivas, Istio remove aquele pod do balanceamento por <code>baseEjectionTime</code>. O campo <code>maxEjectionPercent: 50</code> é crítico em produção — garante que você nunca perde mais da metade da sua capacidade, mesmo com falhas em cascata.</p>
<p>A <code>minRequestVolume: 5</code> evita que decisões sejam tomadas com base em tráfego muito baixo, reduzindo falsos positivos. Em ambientes com pouco tráfego, esse valor deve ser ajustado para refletir o volume real esperado.</p>
<p>---</p>
<h2>Fault Injection: Injetando Falhas de Forma Controlada</h2>
<p>Fault Injection é a prática de injetar falhas (delays, aborts) propositalmente em seu sistema para testar resiliência. Istio permite fazer isso sem modificar código algum — é configuração pura na malha. Você pode simular lentidão de rede ou indisponibilidade temporária para validar se seus circuit breakers, retries e timeouts funcionam corretamente.</p>
<p>Este padrão é essencial para Chaos Engineering. Em vez de esperar que falhas aconteçam naturalmente, você as provoca de forma controlada em ambientes de staging ou produção, identificando fragilidades antes que afetem usuários reais.</p>
<h3>Injetando delays e aborts</h3>
<p>Use um <code>VirtualService</code> para configurar injeção de falhas. Aqui está um exemplo prático:</p>
<pre><code class="language-yaml">apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
name: payment-api-fault-injection
namespace: production
spec:
hosts:
- payment-api
http:
- match:
- sourceLabels:
version: canary
fault:
delay:
percentage: 10
fixedDelay: 5s
abort:
percentage: 3
grpcStatus: UNAVAILABLE
route:
- destination:
host: payment-api
port:
number: 8080
- route:
- destination:
host: payment-api
port:
number: 8080</code></pre>
<p>Aqui, requisições originadas de pods com label <code>version: canary</code> receberão:</p>
<ul>
<li>10% de atraso de 5 segundos</li>
<li>3% de respostas imediatas com erro <code>UNAVAILABLE</code></li>
</ul>
<p>Tráfego de outras fontes passa direto para o destino sem injeção. Isso permite testar código novo (canary) com falhas controladas enquanto mantém o tráfego regular estável.</p>
<h3>Diferença entre delay e abort</h3>
<p><code>delay</code> simula rede lenta — a requisição ainda é processada, mas com latência extra. Útil para testar timeouts. <code>abort</code> encerra a conexão imediatamente com um código de erro, simulando indisponibilidade. Combining ambos oferece testes mais realistas: parte falha rápido (abort), parte falha lentamente (delay).</p>
<p>Para Debug, você pode aumentar temporariamente as percentagens em staging:</p>
<pre><code class="language-yaml">fault:
delay:
percentage: 100
fixedDelay: 2s
abort:
percentage: 50
grpcStatus: RESOURCE_EXHAUSTED</code></pre>
<p>Com 100% de delay e 50% de abort, você verá imediatamente se sua aplicação comporta-se corretamente sob essas condições extremas.</p>
<p>---</p>
<h2>Observabilidade: Rastreando Tudo na Malha</h2>
<p>Observabilidade em Istio funciona em três pilares: métricas, logs e traces distribuídos. A malha injeta sidecar Envoy em cada pod, e esses proxies coletam dados detalhados sobre tráfego, latência, erros e dependências. Você obtém visibilidade total sem instrumentar código.</p>
<p>Métricas são números (requisições por segundo, latência p99). Logs são eventos estruturados. Traces mostem o caminho completo de uma requisição através de múltiplos serviços, essencial para debugging de problemas em arquiteturas distribuídas.</p>
<h3>Coletando métricas com Prometheus</h3>
<p>Istio expõe métricas em formato Prometheus nos sidecars. Configure um <code>ServiceMonitor</code> (se usar Prometheus Operator) ou um scrape_config manual:</p>
<pre><code class="language-yaml">apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
name: istio-mesh
namespace: istio-system
spec:
selector:
matchLabels:
release: istio
endpoints:
- port: http-monitoring
interval: 30s
path: /stats/prometheus</code></pre>
<p>Com isso configurado, você terá métricas como:</p>
<pre><code># Requisições bem-sucedidas
istio_requests_total{destination_service="payment-api", response_code="200"} 15234
Latência em percentis
istio_request_duration_milliseconds_bucket{le="100", destination_service="payment-api"} 5000
istio_request_duration_milliseconds_bucket{le="500", destination_service="payment-api"} 14500
Taxa de erro
istio_requests_total{destination_service="payment-api", response_code="500"} 42</code></pre>
<p>Você pode criar alertas baseados nessas métricas. Por exemplo, alertar quando a taxa de erro 5xx de um serviço ultrapassa 5%:</p>
<pre><code class="language-yaml">groups:
- name: istio_alerts
rules:
- alert: HighErrorRate
expr: |
sum(rate(istio_requests_total{response_code=~"5.."}[5m])) by (destination_service) /
sum(rate(istio_requests_total[5m])) by (destination_service) > 0.05
for: 5m
annotations:
summary: "High error rate for {{ $labels.destination_service }}"</code></pre>
<h3>Distributed Tracing com Jaeger</h3>
<p>Istio integra-se nativamente com Jaeger. Cada sidecar propaga headers de trace (<code>x-trace-id</code>, <code>x-parent-span-id</code>) automaticamente:</p>
<pre><code class="language-yaml">apiVersion: telemetry.istio.io/v1alpha1
kind: Telemetry
metadata:
name: tracing-sampling
namespace: istio-system
spec:
tracing:
- providers:
- name: jaeger
randomSamplingPercentage: 10</code></pre>
<p>Com 10% de sampling, 10% das requisições são traçadas. Em produção, ajuste conforme volume — muita amostragem consome recursos, pouca perde contexto.</p>
<p>Uma vez configurado, você verá traces como este em Jaeger:</p>
<pre><code>Request ID: a1b2c3d4e5f6g7h8
├─ payment-service (5ms)
│ ├─ database query (3ms)
│ └─ cache lookup (0.5ms)
├─ fraud-service (8ms)
│ └─ external ML model (7ms)
└─ notification-service (1ms)
Total: 14ms</code></pre>
<p>Isso permite identificar exatamente qual serviço é lento em uma cadeia de chamadas.</p>
<h3>Logs Estruturados com Fluentd</h3>
<p>Configure coleta de logs dos sidecars:</p>
<pre><code class="language-yaml">apiVersion: v1
kind: ConfigMap
metadata:
name: fluent-bit-config
namespace: istio-system
data:
parsers.conf: |
[PARSER]
Name docker
Format json
Time_Key time
Time_Format %Y-%m-%dT%H:%M:%S.%L%z
fluent-bit.conf: |
[SERVICE]
Flush 5
Log_Level info
[INPUT]
Name tail
Path /var/log/containers/_istio-proxy_.log
Parser docker
Tag istio.*
[OUTPUT]
Name stackdriver
Match *
resource k8s_pod</code></pre>
<p>Cada requisição processada por Envoy gera um log JSON estruturado, facilitando buscas e agregações em ferramentas como Stackdriver ou ELK.</p>
<p>---</p>
<h2>Integrando Tudo: Um Exemplo Completo de Produção</h2>
<p>Agora vamos integrar Circuit Breaker, Fault Injection e observabilidade em um cenário real. Suponha você tem dois serviços: <code>order-service</code> (frontend) e <code>inventory-service</code> (backend).</p>
<pre><code class="language-yaml"># Namespace
apiVersion: v1
kind: Namespace
metadata:
name: ecommerce
labels:
istio-injection: enabled
---
DestinationRule com Circuit Breaker
apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
name: inventory-circuit-breaker
namespace: ecommerce
spec:
host: inventory-service
trafficPolicy:
connectionPool:
http:
http1MaxPendingRequests: 50
maxRequestsPerConnection: 1
tcp:
maxConnections: 50
outlierDetection:
consecutive5xxErrors: 3
interval: 15s
baseEjectionTime: 30s
maxEjectionPercent: 100
minRequestVolume: 3
---
VirtualService com Fault Injection para teste
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
name: inventory-fault-injection
namespace: ecommerce
spec:
hosts:
- inventory-service
http:
- match:
- sourceLabels:
app: order-service
test: true
fault:
delay:
percentage: 20
fixedDelay: 2s
timeout: 5s
retries:
attempts: 3
perTryTimeout: 2s
route:
- destination:
host: inventory-service
port:
number: 8080
- route:
- destination:
host: inventory-service
port:
number: 8080
---
Telemetria para observabilidade
apiVersion: telemetry.istio.io/v1alpha1
kind: Telemetry
metadata:
name: production-tracing
namespace: ecommerce
spec:
tracing:
- providers:
- name: jaeger
randomSamplingPercentage: 5
useRequestIdForTraceSampling: true</code></pre>
<p>Deploy seu order-service com labels para testes:</p>
<pre><code class="language-yaml">apiVersion: apps/v1
kind: Deployment
metadata:
name: order-service
namespace: ecommerce
spec:
replicas: 2
selector:
matchLabels:
app: order-service
template:
metadata:
labels:
app: order-service
version: v1
test: "true"
spec:
containers:
- name: order-api
image: order-service:1.2.0
ports:
- containerPort: 8080
env:
- name: INVENTORY_SERVICE_URL
value: "http://inventory-service:8080"
livenessProbe:
httpGet:
path: /health
port: 8080
initialDelaySeconds: 10
periodSeconds: 10
readinessProbe:
httpGet:
path: /ready
port: 8080
initialDelaySeconds: 5
periodSeconds: 5</code></pre>
<p>Com esta configuração:</p>
<ol>
<li><strong>Circuit Breaker</strong> atuará quando inventory-service falhar 3x consecutivamente</li>
<li><strong>Fault Injection</strong> adicionará delay de 2s em 20% das requisições do order-service (test=true)</li>
<li><strong>Observabilidade</strong> traçará 5% das requisições em Jaeger, permitindo investigar latências</li>
</ol>
<p>Você pode validar com um teste simples:</p>
<pre><code class="language-bash"># Terminal 1: Monitorar traces em Jaeger
kubectl port-forward -n istio-system svc/jaeger 16686:16686
Terminal 2: Gerar tráfego
kubectl run -it --rm -n ecommerce \
--image=curlimages/curl:latest \
--restart=Never \
test-curl -- \
bash -c 'for i in {1..100}; do curl http://order-service:8080/api/orders; sleep 0.1; done'</code></pre>
<p>Em Jaeger, você verá traces como:</p>
<ul>
<li>Requisições normais (~2ms)</li>
<li>Requisições com delay injetado (~2000ms)</li>
<li>Requisições rejeitadas pelo Circuit Breaker (após falhas)</li>
</ul>
<p>---</p>
<h2>Conclusão</h2>
<p>Istio oferece três capacidades transformadoras para resiliência e observabilidade em Kubernetes:</p>
<ol>
<li><strong>Circuit Breaker</strong> automatiza proteção contra falhas em cascata através de <code>DestinationRule</code> e outlier detection, eliminando necessidade de instrumentação em código. A chave é dimensionar corretamente <code>maxEjectionPercent</code> e <code>consecutive5xxErrors</code> para sua carga de trabalho.</li>
</ol>
<ol>
<li><strong>Fault Injection</strong> via <code>VirtualService</code> permite testar resiliência de forma controlada sem esperar por falhas reais, transformando Chaos Engineering em prática segura e previsível. Combine com retries e timeouts para cenários realistas.</li>
</ol>
<ol>
<li><strong>Observabilidade</strong> através de métricas Prometheus, logs estruturados e traces distribuídos fornece visibilidade completa sem alterar aplicações, sendo essencial para debugging em microsserviços. Ajuste sampling de traces conforme volume para balancear fidelidade vs. custo.</li>
</ol>
<p>A combinação desses três pilares transforma sua arquitetura de microsserviços de frágil para robusto, permitindo confiança em produção.</p>
<p>---</p>
<h2>Referências</h2>
<ol>
<li><a href="https://istio.io/latest/docs/reference/config/networking/destination-rule/#OutlierDetection" target="_blank" rel="noopener noreferrer">Istio Documentation - Circuit Breaker</a></li>
</ol>
<ol>
<li><a href="https://istio.io/latest/docs/reference/config/networking/virtual-service/#HTTPFaultInjection" target="_blank" rel="noopener noreferrer">Istio Documentation - Fault Injection</a></li>
</ol>
<ol>
<li><a href="https://www.envoyproxy.io/docs/envoy/latest/api-v3/cluster/outlier_detection.proto" target="_blank" rel="noopener noreferrer">Envoy Proxy - Outlier Detection</a></li>
</ol>
<ol>
<li><a href="https://www.jaegertracing.io/docs/" target="_blank" rel="noopener noreferrer">Jaeger Distributed Tracing Documentation</a></li>
</ol>
<ol>
<li><a href="https://prometheus.io/docs/practices/naming/" target="_blank" rel="noopener noreferrer">Prometheus Metrics Best Practices</a></li>
</ol>
<p><!-- FIM --></p>