diff --git a/aula-12/README.md b/aula-12/README.md index b61c1e2..6fde89e 100644 --- a/aula-12/README.md +++ b/aula-12/README.md @@ -1,209 +1,166 @@ -# Aula 12 - Victoria Metrics (Observabilidade) +# Aula 12 - Observabilidade (Victoria Metrics + Grafana) -Stack completo de monitoramento com Victoria Metrics, Grafana e alertas, instalado via **GitOps com ArgoCD**. +Instale monitoramento no cluster e aprenda a **ver o que está acontecendo** — CPU, memória, disco, pods crashando, PVCs enchendo. -## Por que Victoria Metrics? +## Por que esta aula existe -### Alternativa ao Prometheus +Nas aulas anteriores construímos um cluster completo: Kubernetes, Gitea, ArgoCD, auto-scaling. Mas se um pod estiver em CrashLoop, um PVC estiver 95% cheio, ou um node estiver com CPU saturada — **como você sabe?** -Victoria Metrics oferece **compatibilidade total** com Prometheus, mas com vantagens: +Sem observabilidade, você descobre problemas quando o **usuário reclama**. Com observabilidade, você descobre **antes do usuário**. -| Feature | Prometheus | Victoria Metrics | -|---------|------------|------------------| -| Consumo de RAM | Alto | ~7x menor | -| Compressão | Básica | ~10x melhor | -| Velocidade | Normal | ~2-3x mais rápido | -| Setup HA | Complexo (Thanos) | Simples | -| API | PromQL | PromQL + extensões | +## O que instalamos -### Diferença da Aula-05 +``` +helm install monitoring vm/victoria-metrics-k8s-stack +``` -| Aula-05 (KEDA) | Aula-12 (Observabilidade) | -|----------------|---------------------------| -| Foco: Auto-scaling | Foco: Monitoramento | -| VM básico (sem Grafana) | VM + Grafana completo | -| Queries para KEDA | Queries para operações | -| Ambiente local | Cluster Hetzner + GitOps | +Um único comando. Sem GitOps intermediário, sem repositório extra, sem pipeline de CI. O foco desta aula é **usar** o monitoramento, não instalar infraestrutura. -## Arquitetura +### Componentes ``` ┌─────────────────────────────────────────────────────────────────┐ │ Victoria Metrics Stack │ ├─────────────────────────────────────────────────────────────────┤ -│ ┌─────────────┐ ┌─────────────┐ ┌─────────────────────────┐ │ -│ │ vmagent │ │ vmsingle │ │ Grafana │ │ -│ │ (coleta) │──│ (storage) │──│ (visualização) │ │ -│ └─────────────┘ └─────────────┘ └─────────────────────────┘ │ -│ │ │ │ │ -│ ┌──────┴──────┐ ┌─────┴─────┐ ┌─────┴─────┐ │ -│ │ node-export │ │ vmalert │ │ Dashboards│ │ -│ │ kube-state │ │ (alertas) │ │ pré-config│ │ -│ └─────────────┘ └───────────┘ └───────────┘ │ +│ ┌─────────────┐ ┌─────────────┐ ┌─────────────────────────┐ │ +│ │ vmagent │ │ vmsingle │ │ Grafana │ │ +│ │ (coleta) │─►│ (storage) │◄─│ (visualização) │ │ +│ └─────────────┘ └─────────────┘ └─────────────────────────┘ │ +│ │ │ │ │ +│ ┌──────┴──────┐ ┌─────┴─────┐ ┌─────┴─────┐ │ +│ │ node-export │ │ vmalert │ │ 20+ dash- │ │ +│ │ kube-state │ │ (alertas) │ │ boards │ │ +│ └─────────────┘ └───────────┘ └───────────┘ │ └─────────────────────────────────────────────────────────────────┘ ``` -### Componentes +| Componente | O que faz | +|------------|-----------| +| **vmagent** | Scrapes métricas de todos os pods, nodes, services a cada 30s | +| **vmsingle** | Armazena métricas (14 dias de retenção, 10Gi PVC) | +| **vmalert** | Avalia regras de alerta (PVC cheio, pod crashando, CPU alta) | +| **Grafana** | UI com 20+ dashboards pré-configurados | +| **kube-state-metrics** | Expõe estado dos objetos K8s (pods, deployments, PVCs) | +| **node-exporter** | Expõe métricas do SO (CPU, RAM, disco, rede) | -| Componente | Função | -|------------|--------| -| **vmsingle** | Armazena métricas (modo single-node) | -| **vmagent** | Coleta métricas via scrape | -| **vmalert** | Avalia regras e dispara alertas | -| **Grafana** | Interface de visualização | -| **kube-state-metrics** | Métricas de objetos K8s (pods, deployments) | -| **node-exporter** | Métricas de nodes (CPU, RAM, disco) | +### Por que Victoria Metrics e não Prometheus? -## Pré-requisitos +Compatível com PromQL, mas mais leve: -- Cluster Kubernetes Hetzner (aula-08) -- ArgoCD instalado (aula-11) -- Gitea com org `factory` (aula-11) +| | Prometheus | Victoria Metrics | +|---|---|---| +| RAM | Alto | ~7x menor | +| Compressão em disco | Básica | ~10x melhor | +| Velocidade de query | Normal | ~2-3x mais rápido | +| HA | Complexo (Thanos) | Simples | -## Estrutura +Para um cluster pequeno na Hetzner, Victoria Metrics é a escolha pragmática. -``` -aula-12/ -├── README.md # Este arquivo -├── setup.sh # Instalação automatizada -├── cleanup.sh # Remoção via ArgoCD -│ -├── gitops/ # Conteúdo para Gitea -│ └── apps/ -│ └── victoria-metrics/ -│ ├── Chart.yaml # Helm chart wrapper -│ ├── values.yaml # Configurações do stack -│ └── templates/ -│ └── alerts.yaml # VMRule customizado -│ -├── argocd/ -│ └── application.yaml # ArgoCD Application CRD -│ -├── alerts/ -│ └── vmalert-rules.yaml # Referência (aplicada via gitops/) -│ -└── queries/ - └── useful-queries.md # Queries PromQL úteis -``` - -## Instalação (GitOps) - -### 1. Executar Setup +## Instalação ```bash cd aula-12 +export KUBECONFIG=$(pwd)/../aula-08/kubeconfig ./setup.sh ``` -O script: -1. Cria repositório `factory/monitoring` no Gitea -2. Faz push dos manifests GitOps -3. Cria namespace `monitoring` -4. Aplica ArgoCD Application -5. Aguarda sincronização +O script pergunta: +1. Domínio base (herda da aula-10) +2. Hostname do Grafana (ex: `grafana.kube.quest`) +3. TLS (Let's Encrypt / CloudFlare / HTTP) -### 2. Fluxo GitOps +Depois faz `helm install` direto — sem GitOps, sem repos intermediários. + +## Acesso ao Grafana + +### Via Ingress ``` -┌──────────────────┐ push ┌──────────────────┐ -│ aula-12/ │ ──────────► │factory/monitoring │ -│ gitops/ │ │ (Gitea) │ -└──────────────────┘ └────────┬─────────┘ - │ - sync │ - ▼ - ┌──────────────────┐ - │ ArgoCD │ - └────────┬─────────┘ - │ - apply │ - ▼ - ┌──────────────────┐ - │ Kubernetes │ - │ ns: monitoring │ - └──────────────────┘ +URL: https://grafana.kube.quest +Username: admin +Password: (exibida no setup.sh) ``` -### 3. Verificar Instalação +### Via Port-Forward ```bash -# Status do ArgoCD Application -kubectl get application monitoring -n argocd - -# Pods rodando -kubectl get pods -n monitoring - -# Serviços -kubectl get svc -n monitoring -``` - -## Configuração de DNS - -Antes de acessar o Grafana, configure o DNS: - -```bash -# Obter IP do Load Balancer -kubectl get svc -n ingress-nginx ingress-nginx-controller -o jsonpath='{.status.loadBalancer.ingress[0].ip}' -``` - -Configure o registro DNS: -- **grafana.kube.quest** → IP do Load Balancer (ex: 49.13.44.102) - -## Acessar Grafana - -### Via Ingress (Recomendado) - -Após configurar o DNS: -- **URL**: https://grafana.kube.quest -- Certificado TLS via Let's Encrypt (automático) - -### Credenciais - -- **Usuário**: admin -- **Senha**: (gerada automaticamente) - -```bash -# Obter senha do Grafana -kubectl get secret monitoring-grafana -n monitoring \ - -o jsonpath='{.data.admin-password}' | base64 -d; echo -``` - -### Via Port-Forward (Alternativa) - -Se não tiver DNS configurado: - -```bash -# Port-forward Grafana kubectl port-forward -n monitoring svc/monitoring-grafana 3000:80 - -# Acessar open http://localhost:3000 ``` -## Dashboards Incluídos +### Obter senha -O chart `victoria-metrics-k8s-stack` já inclui **20+ dashboards** via Grafana sidecar: +```bash +kubectl get secret -n monitoring -l app.kubernetes.io/name=grafana \ + -o jsonpath='{.items[0].data.admin-password}' | base64 -d; echo +``` -### Dashboards Principais +## O que monitorar (casos reais) -| Dashboard | Descrição | -|-----------|-----------| +### 1. PVC enchendo + +O problema mais comum em clusters pequenos. Um volume Hetzner de 10Gi enche silenciosamente. + +```promql +# PVCs acima de 80% +(kubelet_volume_stats_used_bytes / kubelet_volume_stats_capacity_bytes) > 0.8 +``` + +Dashboard: **Kubernetes / Views / Persistent Volumes** + +### 2. Pod em CrashLoop + +Quando um pod reinicia repetidamente sem ficar Ready. + +```promql +# Pods que restartaram mais de 5x na última hora +sum(increase(kube_pod_container_status_restarts_total[1h])) by (pod, namespace) > 5 +``` + +Dashboard: **Kubernetes / Views / Pods** + +### 3. Node com CPU saturada + +```promql +# CPU por node (%) +100 - (avg by(instance) (rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100) +``` + +Dashboard: **Node Exporter / Nodes** + +### 4. Memória por namespace + +Quem está consumindo mais memória no cluster? + +```promql +sum(container_memory_working_set_bytes{container!=""}) by (namespace) +``` + +Dashboard: **Kubernetes / Views / Namespaces** + +### 5. Network throughput + +```promql +# Bytes recebidos por pod (rate 5min) +sum(rate(container_network_receive_bytes_total[5m])) by (pod) +``` + +## Dashboards incluídos + +O chart já vem com **20+ dashboards** configurados: + +| Dashboard | Uso | +|-----------|-----| | **Kubernetes / Views / Global** | Visão geral do cluster | | **Kubernetes / Views / Namespaces** | Recursos por namespace | | **Kubernetes / Views / Nodes** | CPU, memória, disco por node | | **Kubernetes / Views / Pods** | Métricas detalhadas de pods | -| **Node Exporter / Nodes** | Métricas de sistema operacional | -| **Node Exporter / USE Method / Node** | Utilização, Saturação, Erros | -| **VictoriaMetrics / vmagent** | Status da coleta de métricas | -| **VictoriaMetrics / vmsingle** | Status do storage de métricas | +| **Node Exporter / Nodes** | Métricas do SO | +| **Node Exporter / USE Method** | Utilização, Saturação, Erros | +| **VictoriaMetrics / vmagent** | Status da coleta | +| **VictoriaMetrics / vmsingle** | Status do storage | -### Ver Todos os Dashboards - -No Grafana: -1. Menu lateral → **Dashboards** -2. Ou acesse: https://grafana.kube.quest/dashboards - -## Alertas Configurados +## Alertas configurados | Alerta | Condição | Severidade | |--------|----------|------------| @@ -215,274 +172,56 @@ No Grafana: | NodeLowMemory | RAM livre < 10% | warning | | NodeDiskFull | Disco > 85% | critical | -### Verificar Alertas - ```bash -# Ver alertas ativos -kubectl get vmrule -n monitoring - -# Ver status no VMAlert +# Ver alertas kubectl port-forward -n monitoring svc/vmalert 8880:8880 open http://localhost:8880/alerts ``` -## Queries PromQL Úteis +## Integração com KEDA (Aula-05) -### Uso de Storage - -```promql -# Uso de PVC em porcentagem -kubelet_volume_stats_used_bytes / kubelet_volume_stats_capacity_bytes * 100 - -# PVCs acima de 80% -(kubelet_volume_stats_used_bytes / kubelet_volume_stats_capacity_bytes) > 0.8 - -# Espaço disponível por PVC -kubelet_volume_stats_available_bytes -``` - -### CPU e Memória - -```promql -# CPU por pod (cores) -sum(rate(container_cpu_usage_seconds_total{container!=""}[5m])) by (pod, namespace) - -# Memória por namespace -sum(container_memory_working_set_bytes{container!=""}) by (namespace) - -# CPU por node (%) -100 - (avg by(instance) (rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100) -``` - -### Pods e Containers - -```promql -# Pods restartando na última hora -sum(increase(kube_pod_container_status_restarts_total[1h])) by (pod, namespace) > 0 - -# Pods não Ready -kube_pod_status_ready{condition="false"} - -# Pods em CrashLoopBackOff -kube_pod_container_status_waiting_reason{reason="CrashLoopBackOff"} -``` - -### Network - -```promql -# Bytes recebidos por pod -sum(rate(container_network_receive_bytes_total[5m])) by (pod) - -# Bytes enviados por pod -sum(rate(container_network_transmit_bytes_total[5m])) by (pod) -``` - -## Integrações - -### Com KEDA (Aula-05) - -Victoria Metrics pode alimentar KEDA para auto-scaling: +Victoria Metrics pode alimentar KEDA para auto-scaling baseado em métricas: ```yaml triggers: - type: prometheus metadata: - serverAddress: http://vmsingle-vm.monitoring:8429 + serverAddress: http://vmsingle-monitoring-victoria-metrics-k8s-stack.monitoring:8429 query: sum(kube_deployment_status_replicas_unavailable{deployment="myapp"}) threshold: '1' ``` -### Com Alertmanager +## Auto-Resize de PVC (Opcional) -Para notificações (Slack, Email, PagerDuty): +Expansão automática de volumes quando atingirem 80%. -```yaml -# values.yaml -vmalert: - alertmanager: - url: http://alertmanager.monitoring:9093 +```bash +helm repo add pvc-autoresizer https://topolvm.github.io/pvc-autoresizer/ +helm install pvc-autoresizer pvc-autoresizer/pvc-autoresizer \ + --namespace pvc-autoresizer \ + --create-namespace \ + --set controller.args.prometheusURL=http://vmsingle-monitoring-victoria-metrics-k8s-stack.monitoring:8429 \ + --set controller.args.noAnnotationCheck=true + +# Habilitar no StorageClass +kubectl annotate storageclass hcloud-volumes resize.topolvm.io/enabled="true" ``` +Com isso, **todos os PVCs** no cluster são monitorados e expandidos automaticamente. + ## Troubleshooting ### Grafana não carrega dashboards ```bash -# Verificar configmap de dashboards -kubectl get configmap -n monitoring | grep dashboard - -# Verificar logs do sidecar kubectl logs -n monitoring -l app.kubernetes.io/name=grafana -c sc-dashboard ``` ### Métricas não aparecem ```bash -# Verificar targets do vmagent kubectl port-forward -n monitoring svc/vmagent 8429:8429 open http://localhost:8429/targets - -# Verificar scrape configs -kubectl get configmap -n monitoring vmagent-config -o yaml -``` - -### VMAlert não dispara alertas - -```bash -# Verificar regras carregadas -kubectl port-forward -n monitoring svc/vmalert 8880:8880 -open http://localhost:8880/rules - -# Verificar logs -kubectl logs -n monitoring -l app=vmalert -``` - -### ArgoCD mostra OutOfSync - -```bash -# Ver diff -argocd app diff monitoring - -# Forçar sync -argocd app sync monitoring --prune -``` - -## Auto-Resize de PVC (Opcional) - -Expansão automática de volumes quando atingirem 80% da capacidade. - -### Arquitetura - -``` -┌─────────────────────────────────────────────────────────────────────┐ -│ FLUXO DE MÉTRICAS │ -├─────────────────────────────────────────────────────────────────────┤ -│ │ -│ kubelet ──────────► vmagent ──────────► vmsingle │ -│ (expõe stats (scrape (armazena │ -│ do volume) 30s) métricas) │ -│ │ -│ Métrica: kubelet_volume_stats_used_bytes │ -│ Métrica: kubelet_volume_stats_capacity_bytes │ -│ │ -└─────────────────────────────────────────────────────────────────────┘ - -┌─────────────────────────────────────────────────────────────────────┐ -│ FLUXO DE RESIZE │ -├─────────────────────────────────────────────────────────────────────┤ -│ │ -│ pvc-autoresizer ───── query ────► vmsingle │ -│ │ (consulta % usado) │ -│ │ │ -│ │ Se usado > 80% (free < 20%): │ -│ │ │ -│ ▼ │ -│ kubectl patch PVC ──────► Kubernetes ──────► Hetzner CSI │ -│ (spec.resources. (detecta mudança (expande volume │ -│ requests.storage no request) online, sem │ -│ += 10Gi) downtime) │ -│ │ │ -│ ▼ │ -│ Pod restart ──────► Filesystem resize ──────► Capacidade OK │ -│ │ -└─────────────────────────────────────────────────────────────────────┘ -``` - -### Componentes e Responsabilidades - -| Componente | Função | Faz resize? | -|------------|--------|-------------| -| **kubelet** | Expõe métricas de volume | ❌ | -| **vmagent** | Coleta métricas (scrape) | ❌ | -| **vmsingle** | Armazena métricas | ❌ | -| **pvc-autoresizer** | Monitora + patch PVC | ✅ | -| **Hetzner CSI** | Expande volume físico | ✅ | - -### Pré-requisitos - -- StorageClass com `allowVolumeExpansion: true` (já configurado) -- Hetzner CSI Driver (suporta online resize) -- Victoria Metrics coletando métricas do kubelet - -### Instalar pvc-autoresizer - -```bash -# Adicionar repo Helm -helm repo add pvc-autoresizer https://topolvm.github.io/pvc-autoresizer/ - -# Instalar com Victoria Metrics + modo automático (sem annotations) -helm install pvc-autoresizer pvc-autoresizer/pvc-autoresizer \ - --namespace pvc-autoresizer \ - --create-namespace \ - --set controller.args.prometheusURL=http://vmsingle-monitoring-victoria-metrics-k8s-stack.monitoring:8429 \ - --set controller.args.noAnnotationCheck=true \ - --set controller.args.initialResizeGroupByPvc=true - -# Habilitar auto-resize no StorageClass -kubectl annotate storageclass hcloud-volumes resize.topolvm.io/enabled="true" -``` - -### Comportamento Automático - -Com `--no-annotation-check`, **todos os PVCs** em StorageClasses com a annotation `resize.topolvm.io/enabled: "true"` são automaticamente monitorados. - -**Defaults aplicados:** -- Threshold: 10% livre (expande quando usado > 90%) -- Increase: 10% do tamanho atual - -**PVCs futuros** não precisam de annotations - funcionam automaticamente! - -### Annotations para Override (Opcional) - -Para customizar o comportamento de um PVC específico: - -```bash -kubectl annotate pvc -n \ - resize.topolvm.io/storage_limit="10Ti" \ - resize.topolvm.io/threshold="20%" \ - resize.topolvm.io/increase="10Gi" -``` - -### Configuração das Annotations (Override) - -| Annotation | Valor | Descrição | -|------------|-------|-----------| -| `storage_limit` | `10Ti` | Limite máximo (10TB = max Hetzner) | -| `threshold` | `20%` | Expandir quando free < 20% (usado > 80%) | -| `increase` | `10Gi` | Quanto aumentar por vez | - -**Nota:** Sem `storage_limit`, o PVC pode expandir até o máximo do Hetzner (10TB). - -### Alerta de Notificação - -Quando um PVC é redimensionado, o alerta **PVCAutoResized** é disparado automaticamente (severity: info). - -### Verificar Funcionamento - -```bash -# Logs do controller -kubectl logs -n pvc-autoresizer deployment/pvc-autoresizer-controller - -# Ver PVCs com auto-resize habilitado -kubectl get pvc -A -o jsonpath='{range .items[*]}{.metadata.namespace}/{.metadata.name}: {.metadata.annotations.resize\.topolvm\.io/storage_limit}{"\n"}{end}' -``` - -### Referência - -- [pvc-autoresizer GitHub](https://github.com/topolvm/pvc-autoresizer) - ---- - -## Retenção de Dados - -Configuração padrão: **14 dias** - -Para alterar: - -```yaml -# gitops/apps/victoria-metrics/values.yaml -vmsingle: - retentionPeriod: "30d" ``` ## Cleanup @@ -491,17 +230,11 @@ vmsingle: ./cleanup.sh ``` -O script remove: -1. ArgoCD Application -2. Namespace `monitoring` -3. Repositório Gitea (opcional) - -**Nota**: Dados de métricas serão perdidos! +Remove o Helm release e o namespace `monitoring`. Dados de métricas serão perdidos. ## Referências - [Victoria Metrics Docs](https://docs.victoriametrics.com/) - [victoria-metrics-k8s-stack Chart](https://github.com/VictoriaMetrics/helm-charts/tree/master/charts/victoria-metrics-k8s-stack) -- [Grafana Dashboards](https://grafana.com/grafana/dashboards/) - [PromQL Cheat Sheet](https://promlabs.com/promql-cheat-sheet/) -- [pvc-autoresizer](https://github.com/topolvm/pvc-autoresizer) - Auto-resize de volumes +- [pvc-autoresizer](https://github.com/topolvm/pvc-autoresizer) diff --git a/aula-12/cleanup.sh b/aula-12/cleanup.sh index ce3b3f0..0844a8e 100755 --- a/aula-12/cleanup.sh +++ b/aula-12/cleanup.sh @@ -1,163 +1,66 @@ #!/bin/bash # ============================================================================= -# Aula 12 - Cleanup Victoria Metrics -# ============================================================================= -# -# Remove Victoria Metrics stack via ArgoCD -# +# Aula 12 - Cleanup (Remove Victoria Metrics) # ============================================================================= set -e -# Cores para output RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' -NC='\033[0m' # No Color +CYAN='\033[0;36m' +NC='\033[0m' -# Funções de log log_info() { echo -e "${BLUE}[INFO]${NC} $1"; } log_success() { echo -e "${GREEN}[OK]${NC} $1"; } log_warn() { echo -e "${YELLOW}[WARN]${NC} $1"; } -log_error() { echo -e "${RED}[ERROR]${NC} $1"; } - -# Diretório do script -SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -ENV_FILE="${SCRIPT_DIR}/.env" - -# Carregar configuração -if [[ -f "$ENV_FILE" ]]; then - source "$ENV_FILE" -fi echo "" -echo "==========================================" -echo " Cleanup Victoria Metrics" -echo "==========================================" +echo -e "${CYAN}============================================${NC}" +echo -e "${CYAN} Cleanup - Aula 12 (Victoria Metrics)${NC}" +echo -e "${CYAN}============================================${NC}" echo "" -echo "Este script irá remover:" -echo " - ArgoCD Application 'monitoring'" -echo " - Todos os recursos no namespace 'monitoring'" -echo " - Secret do repositório no ArgoCD" -echo "" -echo "ATENÇÃO: Dados de métricas serão PERDIDOS!" -echo "" -read -p "Continuar? [y/N]: " CONFIRM -if [[ "$CONFIRM" != "y" && "$CONFIRM" != "Y" ]]; then - log_info "Cancelado pelo usuário" +log_warn "Isso vai remover:" +echo " - Victoria Metrics Stack (Helm release)" +echo " - Namespace monitoring (dados de métricas serão perdidos)" +echo " - Arquivo .env" +echo "" +read -p "Continuar? (digite 'sim' para confirmar): " confirm + +if [ "$confirm" != "sim" ]; then + log_info "Operação cancelada" exit 0 fi -# ============================================================================= -# REMOVER ARGOCD APPLICATION -# ============================================================================= +echo "" -log_info "Removendo ArgoCD Application..." - -if kubectl get application monitoring -n argocd &> /dev/null; then - # Remover finalizers para permitir deleção - kubectl patch application monitoring -n argocd \ - --type json \ - --patch='[{"op": "remove", "path": "/metadata/finalizers"}]' 2>/dev/null || true - - kubectl delete application monitoring -n argocd --wait=false - log_success "ArgoCD Application removida" +# Remover Helm release +log_info "Removendo Victoria Metrics Stack..." +if helm status monitoring -n monitoring &> /dev/null; then + helm uninstall monitoring -n monitoring --wait 2>/dev/null || true + log_success "Helm release removido" else - log_info "ArgoCD Application já não existe" + log_info "Helm release não encontrado" fi -# Aguardar recursos serem deletados pelo ArgoCD -log_info "Aguardando ArgoCD deletar recursos..." -sleep 5 +# Remover PVCs +log_info "Removendo PVCs..." +kubectl delete pvc --all -n monitoring --wait=false 2>/dev/null || true -# ============================================================================= -# REMOVER NAMESPACE -# ============================================================================= +# Remover namespace +log_info "Removendo namespace..." +kubectl delete namespace monitoring --timeout=60s 2>/dev/null || true +log_success "Namespace removido" -log_info "Removendo namespace 'monitoring'..." - -if kubectl get namespace monitoring &> /dev/null; then - # Forçar remoção de recursos se necessário - kubectl delete all --all -n monitoring --timeout=60s 2>/dev/null || true - kubectl delete pvc --all -n monitoring --timeout=60s 2>/dev/null || true - kubectl delete configmap --all -n monitoring --timeout=60s 2>/dev/null || true - kubectl delete secret --all -n monitoring --timeout=60s 2>/dev/null || true - - kubectl delete namespace monitoring --timeout=120s 2>/dev/null || { - log_warn "Timeout deletando namespace, forçando..." - kubectl get namespace monitoring -o json | \ - jq '.spec.finalizers = []' | \ - kubectl replace --raw "/api/v1/namespaces/monitoring/finalize" -f - 2>/dev/null || true - } - log_success "Namespace 'monitoring' removido" -else - log_info "Namespace 'monitoring' já não existe" +# Remover .env +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +if [[ -f "${SCRIPT_DIR}/.env" ]]; then + rm "${SCRIPT_DIR}/.env" + log_info ".env removido" fi -# ============================================================================= -# REMOVER SECRET DO REPOSITÓRIO -# ============================================================================= - -log_info "Removendo secret do repositório..." - -if kubectl get secret factory-monitoring-repo -n argocd &> /dev/null; then - kubectl delete secret factory-monitoring-repo -n argocd - log_success "Secret do repositório removido" -else - log_info "Secret do repositório já não existe" -fi - -# ============================================================================= -# REMOVER REPOSITÓRIO GITEA (OPCIONAL) -# ============================================================================= - -if [[ -n "$GITEA_HOST" && -n "$GITEA_TOKEN" ]]; then - echo "" - read -p "Remover repositório 'factory/monitoring' do Gitea? [y/N]: " REMOVE_PROJECT - - if [[ "$REMOVE_PROJECT" == "y" || "$REMOVE_PROJECT" == "Y" ]]; then - log_info "Removendo repositório do Gitea..." - - DELETE_RESPONSE=$(curl -s -o /dev/null -w "%{http_code}" --request DELETE \ - -H "Authorization: token ${GITEA_TOKEN}" \ - "https://${GITEA_HOST}/api/v1/repos/factory/monitoring") - - if [[ "$DELETE_RESPONSE" == "204" ]]; then - log_success "Repositório removido do Gitea" - else - log_info "Repositório não encontrado no Gitea (HTTP ${DELETE_RESPONSE})" - fi - fi -fi - -# ============================================================================= -# LIMPAR ARQUIVO .ENV -# ============================================================================= - echo "" -read -p "Remover arquivo de configuração local (.env)? [y/N]: " REMOVE_ENV - -if [[ "$REMOVE_ENV" == "y" || "$REMOVE_ENV" == "Y" ]]; then - rm -f "$ENV_FILE" - log_success "Arquivo .env removido" -fi - -# ============================================================================= -# FINALIZAÇÃO -# ============================================================================= - -echo "" -echo "==========================================" -echo " Cleanup Concluído!" -echo "==========================================" -echo "" -echo "Recursos removidos:" -echo " - ArgoCD Application 'monitoring'" -echo " - Namespace 'monitoring'" -echo " - Secret do repositório no ArgoCD" -echo "" -echo "Para reinstalar:" -echo " ./setup.sh" +log_success "Cleanup concluído!" echo "" diff --git a/aula-12/setup.sh b/aula-12/setup.sh index 50f9843..3d3460b 100755 --- a/aula-12/setup.sh +++ b/aula-12/setup.sh @@ -1,40 +1,35 @@ #!/bin/bash # ============================================================================= -# Aula 12 - Victoria Metrics (Observabilidade via GitOps) +# Aula 12 - Victoria Metrics (Observabilidade) # ============================================================================= # -# Este script instala Victoria Metrics stack usando ArgoCD (GitOps): -# 1. Cria projeto 'factory/monitoring' no Gitea -# 2. Push dos manifests GitOps -# 3. Cria ArgoCD Application -# 4. Victoria Metrics + Grafana são sincronizados automaticamente +# Este script instala o stack de monitoramento via Helm: +# 1. Victoria Metrics (coleta + storage de métricas) +# 2. Grafana (dashboards) +# 3. Alertas pré-configurados # # Pré-requisitos: # - Cluster Kubernetes (aula-08) -# - ArgoCD instalado (aula-11) -# - Gitea com org 'factory' (aula-10/11) +# - kubectl e helm instalados # # ============================================================================= set -e -# Cores para output RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' -NC='\033[0m' # No Color +CYAN='\033[0;36m' +NC='\033[0m' -# Funções de log log_info() { echo -e "${BLUE}[INFO]${NC} $1"; } log_success() { echo -e "${GREEN}[OK]${NC} $1"; } log_warn() { echo -e "${YELLOW}[WARN]${NC} $1"; } log_error() { echo -e "${RED}[ERROR]${NC} $1"; } -# Diretório do script SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" ENV_FILE="${SCRIPT_DIR}/.env" -GITOPS_DIR="${SCRIPT_DIR}/gitops" # ============================================================================= # VERIFICAR PRÉ-REQUISITOS @@ -42,42 +37,18 @@ GITOPS_DIR="${SCRIPT_DIR}/gitops" log_info "Verificando pré-requisitos..." -# Verificar kubectl if ! command -v kubectl &> /dev/null; then - log_error "kubectl não encontrado. Instale com: brew install kubectl" + log_error "kubectl não encontrado" exit 1 fi -# Verificar helm if ! command -v helm &> /dev/null; then - log_error "helm não encontrado. Instale com: brew install helm" + log_error "helm não encontrado" exit 1 fi -# Verificar git -if ! command -v git &> /dev/null; then - log_error "git não encontrado. Instale com: brew install git" - exit 1 -fi - -# Verificar conexão com cluster if ! kubectl cluster-info &> /dev/null; then - log_error "Não foi possível conectar ao cluster Kubernetes" - log_info "Verifique se KUBECONFIG está configurado corretamente" - exit 1 -fi - -# Verificar se ArgoCD está instalado -if ! kubectl get namespace argocd &> /dev/null; then - log_error "Namespace 'argocd' não encontrado" - log_info "Execute primeiro a aula-11 para instalar o ArgoCD" - exit 1 -fi - -# Verificar se ArgoCD está rodando -if ! kubectl get pods -n argocd -l app.kubernetes.io/name=argocd-server --no-headers 2>/dev/null | grep -q Running; then - log_error "ArgoCD server não está rodando" - log_info "Verifique: kubectl get pods -n argocd" + log_error "Não foi possível conectar ao cluster" exit 1 fi @@ -87,48 +58,31 @@ log_success "Pré-requisitos verificados" # CARREGAR CONFIGURAÇÃO # ============================================================================= -# Carregar configuração local (se existir) if [[ -f "$ENV_FILE" ]]; then - log_info "Carregando configuração local..." source "$ENV_FILE" fi -# Herdar configuração da aula-11 -AULA11_ENV="${SCRIPT_DIR}/../aula-11/.env" -if [[ -f "$AULA11_ENV" ]]; then - log_info "Herdando configuração da aula-11..." - source "$AULA11_ENV" -fi - -# Herdar configuração da aula-10 -AULA10_ENV="${SCRIPT_DIR}/../aula-10/.env" -if [[ -f "$AULA10_ENV" ]]; then - log_info "Herdando configuração da aula-10..." - source "$AULA10_ENV" -fi +# Herdar domínio da aula-10 ou aula-11 +for ENV_SRC in "${SCRIPT_DIR}/../aula-11/.env" "${SCRIPT_DIR}/../aula-10/.env"; do + if [[ -f "$ENV_SRC" && -z "$DOMAIN" ]]; then + source "$ENV_SRC" + fi +done # ============================================================================= # COLETAR CONFIGURAÇÃO # ============================================================================= echo "" -echo "==========================================" -echo " Configuração Victoria Metrics (GitOps)" -echo "==========================================" +echo -e "${CYAN}═══════════════════════════════════════════════════${NC}" +echo -e "${CYAN} Victoria Metrics - Observabilidade${NC}" +echo -e "${CYAN}═══════════════════════════════════════════════════${NC}" echo "" -# Gitea Host -if [[ -z "$GITEA_HOST" ]]; then - read -p "Hostname do Gitea (ex: gitea.kube.quest): " GITEA_HOST -fi -log_info "Gitea: https://${GITEA_HOST}" - -# Extrair domínio base if [[ -z "$DOMAIN" ]]; then - DOMAIN=$(echo "$GITEA_HOST" | sed 's/^[^.]*\.//') + read -p "Domínio base (ex: kube.quest): " DOMAIN fi -# Grafana Host if [[ -z "$GRAFANA_HOST" ]]; then DEFAULT_GRAFANA="grafana.${DOMAIN}" read -p "Hostname do Grafana [${DEFAULT_GRAFANA}]: " GRAFANA_HOST @@ -136,334 +90,141 @@ if [[ -z "$GRAFANA_HOST" ]]; then fi log_info "Grafana: https://${GRAFANA_HOST}" -# Gitea Token (para criar projeto via API) -if [[ -z "$GITEA_TOKEN" ]]; then - echo "" - echo "Token de acesso Gitea (para criar repositório via API):" - echo " 1. Acesse https://${GITEA_HOST}/user/settings/applications" - echo " 2. Crie um token com permissões de escrita" - echo "" - read -p "Gitea Token: " GITEA_TOKEN -fi - -# TLS (herdar da aula-11) +# TLS if [[ -z "$USE_CLOUDFLARE" && -z "$USE_LETSENCRYPT" ]]; then echo "" echo "Configuração de TLS:" - echo " 1) CloudFlare (proxy ativo - TLS na borda)" - echo " 2) Let's Encrypt (cert-manager)" - echo " 3) HTTP apenas (desenvolvimento)" + echo " 1) Let's Encrypt (recomendado)" + echo " 2) CloudFlare (proxy)" + echo " 3) HTTP apenas" read -p "Escolha [1-3]: " TLS_CHOICE - case $TLS_CHOICE in - 1) USE_CLOUDFLARE=true; USE_LETSENCRYPT=false ;; - 2) USE_CLOUDFLARE=false; USE_LETSENCRYPT=true ;; + 1) USE_CLOUDFLARE=false; USE_LETSENCRYPT=true ;; + 2) USE_CLOUDFLARE=true; USE_LETSENCRYPT=false ;; *) USE_CLOUDFLARE=false; USE_LETSENCRYPT=false ;; esac fi -# Salvar configuração +# Salvar cat > "$ENV_FILE" << EOF -# Configuração gerada pelo setup.sh -# $(date) -GITEA_HOST=${GITEA_HOST} -GRAFANA_HOST=${GRAFANA_HOST} +# Configuração gerada pelo setup.sh - $(date) DOMAIN=${DOMAIN} +GRAFANA_HOST=${GRAFANA_HOST} USE_CLOUDFLARE=${USE_CLOUDFLARE} USE_LETSENCRYPT=${USE_LETSENCRYPT} -GITEA_TOKEN=${GITEA_TOKEN} EOF -log_success "Configuração salva em ${ENV_FILE}" +log_success "Configuração salva" # ============================================================================= -# CRIAR REPOSITÓRIO NO GITEA (VIA API) +# PREPARAR VALUES COM HOSTNAME DO GRAFANA +# ============================================================================= + +log_info "Preparando configuração..." + +VALUES_FILE="${SCRIPT_DIR}/gitops/apps/victoria-metrics/values.yaml" +TEMP_VALUES=$(mktemp) +sed "s/grafana\.kube\.quest/${GRAFANA_HOST}/g" "$VALUES_FILE" > "$TEMP_VALUES" + +# Ajustar TLS no values +if [[ "$USE_LETSENCRYPT" != "true" ]]; then + # Remover anotação cert-manager se não usa Let's Encrypt + sed -i.bak '/cert-manager.io\/cluster-issuer/d' "$TEMP_VALUES" + rm -f "$TEMP_VALUES.bak" +fi + +if [[ "$USE_CLOUDFLARE" == "true" || "$USE_LETSENCRYPT" != "true" ]]; then + # Remover bloco TLS se não usa Let's Encrypt + sed -i.bak '/tls:/,/- grafana/d' "$TEMP_VALUES" + rm -f "$TEMP_VALUES.bak" +fi + +# ============================================================================= +# INSTALAR VIA HELM # ============================================================================= echo "" -log_info "=== Criando Repositório no Gitea ===" +log_info "=== Instalando Victoria Metrics Stack ===" -# Verificar se org factory existe -log_info "Verificando organização 'factory'..." -ORG_RESPONSE=$(curl -s -o /dev/null -w "%{http_code}" \ - -H "Authorization: token ${GITEA_TOKEN}" \ - "https://${GITEA_HOST}/api/v1/orgs/factory") +helm repo add vm https://victoriametrics.github.io/helm-charts/ 2>/dev/null || true +helm repo update vm -if [[ "$ORG_RESPONSE" != "200" ]]; then - log_info "Criando organização 'factory'..." - ORG_CREATE=$(curl -s --request POST \ - -H "Authorization: token ${GITEA_TOKEN}" \ - -H "Content-Type: application/json" \ - --data '{"username": "factory", "visibility": "limited"}' \ - "https://${GITEA_HOST}/api/v1/orgs") +kubectl create namespace monitoring 2>/dev/null || true - ORG_NAME=$(echo "$ORG_CREATE" | grep -o '"username":"factory"' || true) - - if [[ -z "$ORG_NAME" ]]; then - log_error "Falha ao criar organização 'factory'" - echo "$ORG_CREATE" - exit 1 - fi - log_success "Organização 'factory' criada" +if helm status monitoring -n monitoring &> /dev/null; then + log_warn "Já instalado. Atualizando..." + HELM_CMD="upgrade" else - log_success "Organização 'factory' já existe" + HELM_CMD="install" fi -# Verificar se repositório monitoring existe -log_info "Verificando repositório 'monitoring'..." -REPO_RESPONSE=$(curl -s -o /dev/null -w "%{http_code}" \ - -H "Authorization: token ${GITEA_TOKEN}" \ - "https://${GITEA_HOST}/api/v1/repos/factory/monitoring") +helm ${HELM_CMD} monitoring vm/victoria-metrics-k8s-stack \ + --namespace monitoring \ + -f "$TEMP_VALUES" \ + --wait \ + --timeout 10m -if [[ "$REPO_RESPONSE" != "200" ]]; then - log_info "Criando repositório 'monitoring'..." - REPO_CREATE=$(curl -s --request POST \ - -H "Authorization: token ${GITEA_TOKEN}" \ - -H "Content-Type: application/json" \ - --data '{"name": "monitoring", "private": false, "auto_init": false}' \ - "https://${GITEA_HOST}/api/v1/orgs/factory/repos") +rm -f "$TEMP_VALUES" - REPO_NAME=$(echo "$REPO_CREATE" | grep -o '"name":"monitoring"' || true) +log_success "Victoria Metrics Stack instalado!" - if [[ -z "$REPO_NAME" ]]; then - log_error "Falha ao criar repositório 'monitoring'" - echo "$REPO_CREATE" - exit 1 - fi - log_success "Repositório 'monitoring' criado" -else - log_success "Repositório 'monitoring' já existe" +# ============================================================================= +# APLICAR ALERTAS CUSTOMIZADOS +# ============================================================================= + +if [[ -f "${SCRIPT_DIR}/gitops/apps/victoria-metrics/templates/alerts.yaml" ]]; then + echo "" + log_info "Aplicando alertas customizados..." + kubectl apply -f "${SCRIPT_DIR}/gitops/apps/victoria-metrics/templates/alerts.yaml" -n monitoring 2>/dev/null || true + log_success "Alertas aplicados" fi -# ============================================================================= -# PUSH DOS MANIFESTS GITOPS -# ============================================================================= - -echo "" -log_info "=== Push dos Manifests GitOps ===" - -# Criar diretório temporário para clone -TEMP_DIR=$(mktemp -d) -trap "rm -rf ${TEMP_DIR}" EXIT - -cd "${TEMP_DIR}" - -# Configurar git -git config --global user.email "argocd@${DOMAIN}" 2>/dev/null || true -git config --global user.name "ArgoCD Setup" 2>/dev/null || true - -# Clone do repositório (usando token) -log_info "Clonando repositório..." -GITEA_USER=$(curl -s -H "Authorization: token ${GITEA_TOKEN}" "https://${GITEA_HOST}/api/v1/user" | grep -o '"login":"[^"]*"' | cut -d'"' -f4) -GIT_URL="https://${GITEA_USER}:${GITEA_TOKEN}@${GITEA_HOST}/factory/monitoring.git" - -if ! git clone "${GIT_URL}" monitoring 2>/dev/null; then - # Repositório vazio, inicializar - mkdir monitoring - cd monitoring - git init - git remote add origin "${GIT_URL}" -else - cd monitoring -fi - -# Copiar arquivos GitOps -log_info "Copiando manifests GitOps..." -cp -r "${GITOPS_DIR}/apps" . - -# Configurar values.yaml com hostname do Grafana -log_info "Configurando Grafana hostname..." -if [[ -f "apps/victoria-metrics/values.yaml" ]]; then - sed -i.bak "s/GRAFANA_HOST_PLACEHOLDER/${GRAFANA_HOST}/g" apps/victoria-metrics/values.yaml - rm -f apps/victoria-metrics/values.yaml.bak -fi - -# Commit e push -git add -A -if git diff --cached --quiet; then - log_info "Nenhuma mudança para commit" -else - git commit -m "feat: Victoria Metrics stack configuration" - log_info "Pushing para Gitea..." - git push -u origin main 2>/dev/null || git push -u origin master 2>/dev/null || { - # Primeiro push em repo vazio - git push --set-upstream origin main 2>/dev/null || git push --set-upstream origin master - } - log_success "Manifests enviados para Gitea" -fi - -cd "${SCRIPT_DIR}" - -# ============================================================================= -# CRIAR NAMESPACE MONITORING -# ============================================================================= - -echo "" -log_info "=== Criando Namespace ===" - -kubectl create namespace monitoring 2>/dev/null || log_info "Namespace 'monitoring' já existe" -log_success "Namespace 'monitoring' pronto" - -# ============================================================================= -# CONFIGURAR REPOSITÓRIO NO ARGOCD -# ============================================================================= - -echo "" -log_info "=== Configurando Repositório no ArgoCD ===" - -# Criar secret para o repositório -log_info "Criando secret de acesso ao repositório..." -kubectl apply -f - << EOF -apiVersion: v1 -kind: Secret -metadata: - name: factory-monitoring-repo - namespace: argocd - labels: - argocd.argoproj.io/secret-type: repository -stringData: - type: git - url: https://${GITEA_HOST}/factory/monitoring.git - username: ${GITEA_USER} - password: ${GITEA_TOKEN} -EOF - -log_success "Repositório configurado no ArgoCD" - -# ============================================================================= -# CRIAR ARGOCD APPLICATION -# ============================================================================= - -echo "" -log_info "=== Criando ArgoCD Application ===" - -# Construir anotações de Ingress -INGRESS_ANNOTATIONS="" -if [[ "$USE_LETSENCRYPT" == "true" ]]; then - INGRESS_ANNOTATIONS='cert-manager.io/cluster-issuer: letsencrypt-prod' -fi - -# Aplicar ArgoCD Application -kubectl apply -f - << EOF -apiVersion: argoproj.io/v1alpha1 -kind: Application -metadata: - name: monitoring - namespace: argocd - finalizers: - - resources-finalizer.argocd.argoproj.io -spec: - project: default - source: - repoURL: https://${GITEA_HOST}/factory/monitoring.git - targetRevision: HEAD - path: apps/victoria-metrics - helm: - valueFiles: - - values.yaml - destination: - server: https://kubernetes.default.svc - namespace: monitoring - syncPolicy: - automated: - prune: true - selfHeal: true - syncOptions: - - CreateNamespace=true - - ServerSideApply=true -EOF - -log_success "ArgoCD Application criada" - -# ============================================================================= -# AGUARDAR SINCRONIZAÇÃO -# ============================================================================= - -echo "" -log_info "=== Aguardando Sincronização ===" - -log_info "ArgoCD está sincronizando Victoria Metrics stack..." -log_info "Isso pode levar alguns minutos na primeira vez..." - -# Aguardar até 5 minutos -for i in {1..60}; do - STATUS=$(kubectl get application monitoring -n argocd -o jsonpath='{.status.sync.status}' 2>/dev/null || echo "Unknown") - HEALTH=$(kubectl get application monitoring -n argocd -o jsonpath='{.status.health.status}' 2>/dev/null || echo "Unknown") - - echo -ne "\r Status: ${STATUS} | Health: ${HEALTH} " - - if [[ "$STATUS" == "Synced" && "$HEALTH" == "Healthy" ]]; then - echo "" - log_success "Victoria Metrics stack sincronizado e saudável!" - break - fi - - if [[ $i -eq 60 ]]; then - echo "" - log_warn "Timeout aguardando sincronização" - log_info "Verifique o status no ArgoCD UI" - fi - - sleep 5 -done - # ============================================================================= # OBTER SENHA DO GRAFANA # ============================================================================= echo "" -log_info "=== Credenciais do Grafana ===" +log_info "Obtendo credenciais do Grafana..." -# Aguardar secret ser criado +GRAFANA_PASSWORD="" for i in {1..30}; do - if kubectl get secret vm-grafana -n monitoring &> /dev/null; then - break - fi + GRAFANA_PASSWORD=$(kubectl get secret -n monitoring -l app.kubernetes.io/name=grafana \ + -o jsonpath='{.items[0].data.admin-password}' 2>/dev/null | base64 -d 2>/dev/null) + if [[ -n "$GRAFANA_PASSWORD" ]]; then break; fi sleep 2 done -GRAFANA_PASSWORD=$(kubectl get secret vm-grafana -n monitoring -o jsonpath='{.data.admin-password}' 2>/dev/null | base64 -d 2>/dev/null || echo "") +# ============================================================================= +# RESUMO FINAL +# ============================================================================= -if [[ -z "$GRAFANA_PASSWORD" ]]; then - # Tentar nome alternativo do secret - GRAFANA_PASSWORD=$(kubectl get secret -n monitoring -l app.kubernetes.io/name=grafana -o jsonpath='{.items[0].data.admin-password}' 2>/dev/null | base64 -d 2>/dev/null || echo "admin") +PROTOCOL="https" +if [[ "$USE_CLOUDFLARE" == "false" && "$USE_LETSENCRYPT" == "false" ]]; then + PROTOCOL="http" fi -# ============================================================================= -# INSTRUÇÕES FINAIS -# ============================================================================= - echo "" -echo "==========================================" -echo " Instalação Concluída!" -echo "==========================================" -echo "" -echo "Victoria Metrics Stack instalado via GitOps" +echo -e "${CYAN}═══════════════════════════════════════════════════${NC}" +echo -e "${GREEN} Victoria Metrics Instalado!${NC}" +echo -e "${CYAN}═══════════════════════════════════════════════════${NC}" echo "" echo "Grafana:" -if [[ "$USE_CLOUDFLARE" == "true" || "$USE_LETSENCRYPT" == "true" ]]; then - echo " URL: https://${GRAFANA_HOST}" -else - echo " URL: http://${GRAFANA_HOST}" -fi +echo " URL: ${PROTOCOL}://${GRAFANA_HOST}" echo " Username: admin" -echo " Password: ${GRAFANA_PASSWORD:-'(ver secret vm-grafana)'}" +echo " Password: ${GRAFANA_PASSWORD:-'(kubectl get secret -n monitoring -l app.kubernetes.io/name=grafana -o jsonpath=\"{.items[0].data.admin-password}\" | base64 -d)'}" echo "" -echo "Acesso via port-forward:" -echo " kubectl port-forward -n monitoring svc/vm-grafana 3000:80" +echo "Acesso alternativo (port-forward):" +echo " kubectl port-forward -n monitoring svc/monitoring-grafana 3000:80" echo " open http://localhost:3000" echo "" -echo "ArgoCD Application:" -echo " kubectl get application monitoring -n argocd" -echo "" -echo "Pods:" +echo "Verificar:" echo " kubectl get pods -n monitoring" echo "" -echo "GitOps Repository:" -echo " https://${GITEA_HOST}/factory/monitoring" +echo "Desinstalar:" +echo " ./cleanup.sh" echo "" -echo "Verificar métricas:" -echo " kubectl port-forward -n monitoring svc/vmsingle-vm 8429:8429" -echo " curl http://localhost:8429/api/v1/query?query=up" +echo -e "${CYAN}═══════════════════════════════════════════════════${NC}" echo "" -echo "==========================================" + +log_info "Status dos pods:" +kubectl get pods -n monitoring