feat(aula-14): adicionar Istio Traffic Splitting com canary deployment

- Instala Istio (base + istiod + ingressgateway)
- Configura Kiali e Jaeger para observabilidade
- Deploy de app-backend v1 e v2 com traffic splitting 90/10
- Integra com Victoria Metrics da aula-12
- Inclui teste-stress.sh para validar distribuição de tráfego
- Tráfego externo passa pelo Istio Gateway via NGINX Ingress
This commit is contained in:
ArgoCD Setup
2026-01-24 07:40:51 -03:00
parent 3e53328214
commit 3860809e5c
22 changed files with 1545 additions and 0 deletions

198
aula-14/teste-stress.sh Executable file
View File

@@ -0,0 +1,198 @@
#!/bin/bash
# ============================================================================
# Teste de Stress - Demonstração de Traffic Splitting do Istio
# ============================================================================
# Script interativo para visualizar a distribuição de tráfego entre v1 e v2.
#
# Uso:
# ./teste-stress.sh [URL] [NUM_REQUESTS]
#
# Exemplos:
# ./teste-stress.sh # Usa APP_HOST do .env, 100 requests
# ./teste-stress.sh https://app.kube.quest # URL específica, 100 requests
# ./teste-stress.sh https://app.kube.quest 50 # 50 requests
# ============================================================================
set -e
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
CYAN='\033[0;36m'
MAGENTA='\033[0;35m'
NC='\033[0m'
BOLD='\033[1m'
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
ENV_FILE="${SCRIPT_DIR}/.env"
# ============================================================================
# Configuração
# ============================================================================
# Carregar .env se existir
if [[ -f "$ENV_FILE" ]]; then
source "$ENV_FILE"
fi
# Parâmetros
URL="${1:-}"
NUM_REQUESTS="${2:-100}"
# Se URL não foi passada, tentar construir do .env
if [[ -z "$URL" ]]; then
if [[ -n "$APP_HOST" ]]; then
if [[ "$USE_LETSENCRYPT" == "true" ]]; then
URL="https://${APP_HOST}"
else
URL="http://${APP_HOST}"
fi
else
echo -e "${RED}[ERRO]${NC} URL não especificada e APP_HOST não encontrado no .env"
echo ""
echo "Uso: $0 [URL] [NUM_REQUESTS]"
echo ""
echo "Exemplos:"
echo " $0 https://app.kube.quest"
echo " $0 https://app.kube.quest 50"
echo ""
echo "Ou configure APP_HOST no .env executando setup.sh novamente."
exit 1
fi
fi
# ============================================================================
# Funções
# ============================================================================
get_current_weights() {
local weights
weights=$(kubectl get virtualservice app-backend -n istio -o jsonpath='{.spec.http[0].route[*].weight}' 2>/dev/null || echo "90 10")
echo "$weights"
}
draw_bar() {
local value=$1
local max=$2
local width=40
local filled=$((value * width / max))
local empty=$((width - filled))
printf "["
for ((i=0; i<filled; i++)); do printf "${GREEN}#${NC}"; done
for ((i=0; i<empty; i++)); do printf "."; done
printf "]"
}
show_header() {
local weights
weights=$(get_current_weights)
local v1_weight=$(echo "$weights" | awk '{print $1}')
local v2_weight=$(echo "$weights" | awk '{print $2}')
echo ""
echo -e "${CYAN}${BOLD}╔═══════════════════════════════════════════════════════════╗${NC}"
echo -e "${CYAN}${BOLD}║ Teste de Traffic Splitting - Istio ║${NC}"
echo -e "${CYAN}${BOLD}╚═══════════════════════════════════════════════════════════╝${NC}"
echo ""
echo -e "${YELLOW}Distribuição configurada:${NC} v1=${v1_weight}% v2=${v2_weight}%"
echo -e "${YELLOW}URL:${NC} ${URL}"
echo -e "${YELLOW}Requests:${NC} ${NUM_REQUESTS}"
echo ""
echo -e "${CYAN}───────────────────────────────────────────────────────────${NC}"
}
run_test() {
local count_v1=0
local count_v2=0
local count_other=0
for ((i=1; i<=NUM_REQUESTS; i++)); do
# Fazer request e capturar resposta
local response
response=$(curl -sk --connect-timeout 5 --max-time 10 "$URL" 2>/dev/null || echo "ERROR")
# Identificar versão baseado na resposta
if echo "$response" | grep -q "v1\|node-bugado v1"; then
((count_v1++))
elif echo "$response" | grep -q "v2\|stable\|node-bugado v2"; then
((count_v2++))
else
((count_other++))
fi
# Exibir progresso
printf "\r${NC}[%3d/%d] ${BLUE}v1:%-3d${NC} ${GREEN}v2:%-3d${NC}" "$i" "$NUM_REQUESTS" "$count_v1" "$count_v2"
# Pequena pausa para não sobrecarregar
sleep 0.05
done
echo ""
echo ""
# Exibir resultados
show_results "$count_v1" "$count_v2" "$count_other"
}
show_results() {
local count_v1=$1
local count_v2=$2
local count_other=$3
local total=$((count_v1 + count_v2 + count_other))
local pct_v1=0
local pct_v2=0
[[ $total -gt 0 ]] && pct_v1=$((count_v1 * 100 / total))
[[ $total -gt 0 ]] && pct_v2=$((count_v2 * 100 / total))
echo -e "${CYAN}═══════════════════════════════════════════════════════════${NC}"
echo -e "${BOLD}Resultados:${NC}"
echo ""
printf " ${BLUE}v1${NC}: %3d (%2d%%) " "$count_v1" "$pct_v1"
draw_bar "$count_v1" "$total"
echo ""
printf " ${GREEN}v2${NC}: %3d (%2d%%) " "$count_v2" "$pct_v2"
draw_bar "$count_v2" "$total"
echo ""
if [[ $count_other -gt 0 ]]; then
echo -e " ${RED}Erros${NC}: $count_other"
fi
echo -e "${CYAN}═══════════════════════════════════════════════════════════${NC}"
echo ""
# Comandos para alterar distribuição
show_commands
}
show_commands() {
echo -e "${BOLD}Comandos para alterar distribuição:${NC}"
echo ""
echo -e "${YELLOW}# Aumentar tráfego para v2 (50/50)${NC}"
echo "kubectl patch virtualservice app-backend -n istio --type='json' \\"
echo " -p='[{\"op\":\"replace\",\"path\":\"/spec/http/0/route/0/weight\",\"value\":50},"
echo " {\"op\":\"replace\",\"path\":\"/spec/http/0/route/1/weight\",\"value\":50}]'"
echo ""
echo -e "${YELLOW}# Virada completa para v2 (0/100)${NC}"
echo "kubectl patch virtualservice app-backend -n istio --type='json' \\"
echo " -p='[{\"op\":\"replace\",\"path\":\"/spec/http/0/route/0/weight\",\"value\":0},"
echo " {\"op\":\"replace\",\"path\":\"/spec/http/0/route/1/weight\",\"value\":100}]'"
echo ""
echo -e "${YELLOW}# Rollback para v1 se necessário (100/0)${NC}"
echo "kubectl patch virtualservice app-backend -n istio --type='json' \\"
echo " -p='[{\"op\":\"replace\",\"path\":\"/spec/http/0/route/0/weight\",\"value\":100},"
echo " {\"op\":\"replace\",\"path\":\"/spec/http/0/route/1/weight\",\"value\":0}]'"
echo ""
echo -e "${CYAN}Após alterar, re-execute: ${NC}${BOLD}./teste-stress.sh${NC}"
echo ""
}
# ============================================================================
# Execução
# ============================================================================
show_header
run_test