251 lines
15 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# iklim.co Health Agent
Docker Swarm cluster içinde çalışan, push modeli üzerinden Uptime Kuma'ya sağlık durumu ileten ve Docker olaylarını Slack'e doğrudan bildiren hafif bir Python servisidir. Gelen bağlantı gerekmez — tüm trafik dışa yönelik HTTPS'tir.
---
## Mimari
Agent, Swarm manager node üzerinde tek replica olarak çalışır ve şu kaynaklara erişir:
- `/var/run/docker.sock` (salt okunur) — Swarm servislerini, node'ları ve event stream'ini dinler
- `iklimco-net` overlay ağı — tüm iç servislere DNS adıyla erişir
- StorageBox bind mount (salt okunur) — sertifika dosyaları ve yapılandırma varlığını kontrol eder
- `config/generated/uk_tokens.yml``setup_uptime_kuma.py` tarafından üretilir, agent bu dosyayı okur
Her check bağımsız çalışır ve kendi Uptime Kuma monitörüne push yapar. Bir check'in başarısız olması diğerlerini etkilemez.
Slack bildirimleri iki kanaldan gelir:
- **`[Uptime Kuma]`** — Uptime Kuma'nın kendi HTTP/DNS/Ping monitörleri tarafından üretilir
- **`[Health Agent]`** — health-agent'ın push check'lerinden; Uptime Kuma'nın group monitor mekanizması üzerinden iletilir
- **`[Health Agent / Events]`** — Docker events stream'den gelen anlık restart/OOM bildirimleri; doğrudan Slack webhook'una gönderilir, Uptime Kuma'dan geçmez
---
## Dizin Yapısı
```
Environment_Monitoring/health-agent/
├── config/
│ ├── monitors.yml # tüm monitor/group/tag/status-page tanımları; node IP'leri buraya yazılır
│ └── generated/
│ └── uk_tokens.yml # setup_uptime_kuma.py tarafından üretilir; health-agent okur
├── src/
│ └── health_agent/
│ ├── main.py # giriş noktası; scheduler loop
│ ├── config.py # .env + uk_tokens.yml yükler; ortam ayarlarını expose eder
│ ├── uptime_kuma.py # push(token, status, msg, ping_ms) yardımcısı
│ ├── slack.py # notify(webhook, source, priority, title, detail, uk_group_url) — kaynak etiketli + UK grup linki
│ ├── checks/
│ │ ├── swarm.py # Docker API: node listesi (sadece Swarm node kontrolü)
│ │ ├── swarm_services.py # Docker API: iklimco stack servislerinin replica kontrolü
│ │ ├── actuator.py # Mikroservisler için HTTP actuator health (IP/replica bazlı) check
│ │ ├── http.py # genel HTTP check + uygulama bazlı parser'lar (Patroni, Vault, RabbitMQ...)
│ │ ├── tcp.py # TCP port erişilebilirliği
│ │ ├── tls.py # TLS sertifika son kullanma tarihi (dosyadan veya handshake'den)
│ │ ├── redis_sentinel.py # Redis Sentinel — redis-py ile quorum ve master kontrolü
│ │ ├── mongodb.py # MongoDB rs.status() — pymongo ile PRIMARY ve lag kontrolü
│ │ └── filesystem.py # StorageBox mount varlığı ve SSL cert sync durumu
│ └── events/
│ └── docker_events.py # arka plan thread'i; Docker /events stream'ini dinler, restart/OOM bildirir
├── scripts/
│ └── setup_uptime_kuma.py # monitors.yml'i okur, UK'da oluşturur, uk_tokens.yml'e yazar
├── Dockerfile
├── pyproject.toml
├── .env.example # health-agent runtime değişkenleri (credentials, ENV, CLUSTER_SIZE_*)
└── .env.setup.example # setup script değişkenleri (UK_URL, UK_USER, UK_PASS, Slack webhook'ları)
```
---
## Yapılandırma
**`config/monitors.yml`** — Tüm monitor, group, tag ve status page tanımları bu dosyadadır. Yeni bir monitor eklemek için kod değişikliği gerekmez; `monitors.yml`'e yeni bir blok eklenir ve `setup_uptime_kuma.py` çalıştırılır.
**Mikroservis Ekleme:** `microservice_monitors` bölümü, BE servislerinin Uptime Kuma'ya (actuator ve swarm replica bazında) eklenmesini otomatikleştirir. Yeni bir BE servisi eklendiğinde kod değişikliği gerekmez; sadece bu bölüme servis tanımı ve opsiyonel `replicas.<env>` beklentisi yazılıp setup script çalıştırılır. `replicas.<env>`, ortam bazlı beklenen replica sayısıdır; Docker "desired" değerinden bağımsız çalışır (yanlış scale-down veya deploy edilmeme durumlarını alarm olarak yakalar). Servisin replica değerini kalıcı olarak değiştiriyorsanız, `monitors.yml` dosyasını da güncelleyip imajı rebuild etmelisiniz (çünkü bu dosya imaja gömülüdür).
**`.env`** — Runtime değişkenler:
| Variable | Description |
|----------|-------------|
| `UK_PUSH_URL_BASE` | Uptime Kuma push base URL (e.g. `https://status.iklim.co/api/push`) |
| `ENV` | `prod` or `test` |
| `CLUSTER_SIZE_ETCD` | etcd node count (prod: 3, test: 1) |
| `CLUSTER_SIZE_PATRONI` | Patroni node count |
| `CLUSTER_SIZE_MONGODB` | MongoDB node count |
| `CLUSTER_SIZE_RABBITMQ` | Expected RabbitMQ cluster member count (RabbitMQ runs as a single Swarm service — this only sets the expected total, not per-node hostnames) |
| `CLUSTER_SIZE_VAULT` | Vault node count |
| `REDIS_MODE` | `sentinel` or `standalone` |
| `EXTERNAL_DOMAIN` | Base domain — `iklim.co` in both environments |
| `EXTERNAL_SUBDOMAIN_SUFFIX` | Subdomain suffix — empty for prod, `-test` for test → `api-test.iklim.co` |
| `SLACK_WEBHOOK_IKLIM_{ENV}_OPS` | Direct Slack webhook for container crash/OOM events — e.g. `SLACK_WEBHOOK_IKLIM_PROD_OPS` |
| `ETCD_HOSTS` | etcd node list (comma-separated `host:port`) — e.g. `etcd-01:2379,etcd-02:2379`; falls back to `etcd-01..0N` derived from `CLUSTER_SIZE_ETCD` |
| `PATRONI_HOSTS` | Patroni node list (comma-separated `host:port`) — e.g. `patroni-01:8008,patroni-02:8008` |
| `VAULT_HOSTS` | Vault node subdomain list (comma-separated) — e.g. `vault-1,vault-2,vault-3` |
| `RABBITMQ_HOSTS` | Optional RabbitMQ endpoint override (comma-separated `host:port`); defaults to the single `rabbitmq` Swarm service — normally leave unset |
| `RABBITMQ_USER` / `RABBITMQ_PASS` | RabbitMQ management credentials |
| `MONGO_URI` | MongoDB connection URI |
| `REDIS_PASSWORD` | Redis / Sentinel password |
| `REDIS_MASTER_NAME` | Redis Sentinel master name |
| `REDIS_SENTINEL_HOSTS` | Sentinel host list (comma-separated `host:port`) |
| `STORAGEBOX_PATH` | StorageBox mount path for filesystem check |
| `APISIX_ADMIN_KEY` | APISIX admin API key for health check |
**Altyapı Beklentileri (CLUSTER_SIZE_*)**: Altyapı check'leri, `*_HOSTS` listesi `.env` içinde tanımlıysa onu kullanır, tanımsız/boş ise `CLUSTER_SIZE_*` sayısına göre (ör. `etcd-01`, `etcd-02`...) beklenen host listesini otomatik türetir. Bu sayede cluster node sayısını artırıp azaltmak kod veya imaj rebuild gerektirmez.
**Monitör Adlandırma Konvansiyonu**: Test ve prod aynı Uptime Kuma'yı paylaştığı için monitörler UK arayüzünde `iklim [<env>] <Ad>` formatıyla oluşturulur. Ancak `uk_tokens.yml` dosyası ve kod içi `push()` fonksiyonu, prefix'siz ham ad (ör. "Stack Services") ile çalışmaya devam eder.
Check periyotları `monitors.yml`'de her monitor için tanımlanır; `.env`'e eklenmez.
Push token'ları `config/generated/uk_tokens.yml`'den otomatik okunur — bu dosya `setup_uptime_kuma.py` tarafından üretilir ve `.env`'e elle kopyalanmaz.
---
## Yeni Check Ekleme
1. `src/health_agent/checks/` altına yeni bir dosya ekle veya uygun mevcut dosyaya yeni bir fonksiyon ekle.
2. Fonksiyon `(ok: bool, msg: str, ping_ms: int)` tuple'ı döndürmeli.
3. `config/monitors.yml`'e yeni monitor bloğu ekle (isim, grup, öncelik, bildirim kanalı, check periyodu).
4. `setup_uptime_kuma.py`'yi çalıştır — yeni monitor UK'da oluşturulur ve token `uk_tokens.yml`'e yazılır.
5. `main.py`'de check fonksiyonunu token ve yapılandırmayla kaydet.
---
## İlk Kurulum (Uptime Kuma)
Health-agent deploy edilmeden önce kurulum script'i çalıştırılır. Script, `monitors.yml`'i okuyarak tüm monitor, tag, group ve status page'leri Uptime Kuma'da oluşturur; push token'larını `config/generated/uk_tokens.yml`'e yazar.
Script `uptime-kuma-api-v2` kütüphanesini kullanır; Socket.IO üzerinden username/password ile bağlanır.
```bash
cd Environment_Monitoring/health-agent
# Python 3.12 venv oluştur ve aktive et
python3.12 -m venv .venv
source .venv/bin/activate
pip install -e ".[dev]"
# runtime ve setup değişkenlerini doldur
cp .env.example .env # ENV, EXTERNAL_DOMAIN vb.
cp .env.setup.example .env.setup # UK_URL, UK_USER, UK_PASS, Slack webhook'ları
# önce dry-run ile ne yapılacağını gör
python scripts/setup_uptime_kuma.py --dry-run
# tüm kaynakları oluştur
python scripts/setup_uptime_kuma.py
# sadece belirli bir monitörü işle (monitor adıyla)
python scripts/setup_uptime_kuma.py --only SWARM-CLUSTER
```
Script idempotent çalışır — CI/CD pipeline'ında her deploy'da güvenle tetiklenebilir.
---
## Notification Flood Önleme
Uptime Kuma group monitor mekanizması kullanılır: Slack bildirimi child monitor'lere değil, **yalnızca group monitor'e** bağlanır. Bir grup içinde birden fazla monitor aynı anda çökse dahi tek bildirim üretilir.
Planlı bakım/deploy sırasında etkilenecek group için Uptime Kuma'da Maintenance penceresi açılır (API üzerinden otomatik yapılabilir). Bu süre zarfında alarm üretilmez.
---
## Yerel Geliştirme
```bash
cd Environment_Monitoring/health-agent
# Python 3.12 venv oluştur ve aktive et
python3.12 -m venv .venv
source .venv/bin/activate
# bağımlılıkları kur
pip install -e ".[dev]"
# .env dosyasını hazırla
cp .env.example .env
# check'leri bir kez çalıştır, Uptime Kuma'ya push etme
python -m health_agent.main --once --dry-run
# check'leri bir kez çalıştır, Uptime Kuma'ya gerçekten push et
python -m health_agent.main --once
# tam scheduler'ı başlat
python -m health_agent.main
```
`--once`: her check'i bir kez çalıştırıp çıkar. `--dry-run`: Uptime Kuma push'larını atlar, sadece loglar. İkisi birlikte credential ve bağlantı doğrulaması için kullanılır.
---
## Deployment
Monitoring stack ve health-agent Gitea workflow'larıyla deploy edilir:
- `.gitea/workflows/deploy-monitoring-test.yml``test` branch'ine push ile tetiklenir. Sırası: (1) imajı **build edip** Harbor'a `health-agent:<version>-rc` olarak push'lar ve log'a "Promotion Manifest" (digest + tag) yazdırır, (2) `uk_tokens.yml` yoksa `setup_uptime_kuma.py`'yi çalıştırır, (3) monitoring stack'ini deploy eder.
- `.gitea/workflows/deploy-monitoring-prod.yml``prod-env` branch'ine push ile tetiklenir. **İmaj build etmez**; `health-agent/deploy/prod.env` dosyasındaki `SOURCE_IMAGE_DIGEST`'i çekip `PROD_IMAGE_TAG` ile yeniden etiketleyerek promote eder. Sonrası test ile aynıdır: `uk_tokens.yml` yoksa setup, ardından stack deploy.
> ⚠️ **İki kritik davranış:**
>
> 1. **Setup adımı `uk_tokens.yml` varken hiç çalışmaz.** Workflow'daki `if [ ! -s uk_tokens.yml ]` koşulu nedeniyle dosya host'ta durduğu sürece `setup_uptime_kuma.py` atlanır. `monitors.yml`'e yeni monitor/group eklediyseniz, deploy öncesinde host'taki `${HEALTH_AGENT_CONFIG_GENERATED_DIR}/uk_tokens.yml` dosyasını silmelisiniz — yoksa yeni monitörler Uptime Kuma'da asla oluşmaz. Script idempotent olduğu için mevcut monitörler güncellenir, yenileri eklenir, token'lar yeniden yazılır.
> 2. **Aynı tag ile deploy servisi güncellemez.** Stack deploy `--resolve-image changed` kullanır: servis tanımındaki imaj referansı (repo/tag string'i) değişmediyse Swarm digest'i yeniden çözmez ve çalışan container **eski imajla devam eder** — Harbor'da tag'in üzerine yeni imaj yazılmış olsa bile. Bu yüzden her kod değişikliğinde versiyon yükseltmek zorunludur (aşağıdaki release prosedürüne bakın).
Ayrıca `config/monitors.yml` ve `scripts/setup_uptime_kuma.py` **imaja gömülüdür** — setup adımı `docker run` ile yalnızca `config/generated/` dizinini mount eder. Repo'da `monitors.yml`'i değiştirip merge etmek tek başına hiçbir şeyi değiştirmez; değişikliğin etkili olması için imajın yeniden build edilmesi gerekir.
Manuel deploy için:
```bash
# önce setup_uptime_kuma.py çalıştır
python scripts/setup_uptime_kuma.py
# tek stack: portainer + loki + promtail + health-agent
docker stack deploy \
--with-registry-auth \
-c docker-stack-monitoring.yml \
monitoring
```
Health-agent `iklimco-net` overlay ağına bağlı olmalı ve Docker socket'a salt okunur erişimi olmalıdır.
---
## Güncelleme / Release Prosedürü
Health-agent'ta herhangi bir değişiklik (kod, `monitors.yml`, bağımlılık) prod'a şu adımlarla çıkar. Adımların hiçbiri atlanamaz — özellikle versiyon yükseltme (bkz. yukarıdaki ⚠️ notları):
1. **Versiyonu yükselt:** `health-agent/pyproject.toml` içindeki `version` alanını artır (ör. `0.2.0``0.3.0`). Build script tag'i buradan okur; tag değişmezse Swarm çalışan servisi güncellemez.
2. **İmajı build et ve push'la** (`main` branch'inde, `Environment_Monitoring/` kökünden):
```bash
HARBOR_CI_TOKEN=<token> ./ops/build-and-push-health-agent.sh
```
Alternatif: `test` branch'ine push'lamak test workflow'unda aynı build'i yapar. Her iki yol da çıktının sonunda "Promotion Manifest" basar:
```
SOURCE_IMAGE_DIGEST=registry.tarla.io/iklimco/health-agent@sha256:<digest>
PROD_IMAGE_TAG=<version>
```
3. **Manifest'i prod'a yaz:** `prod-env` branch'inde `health-agent/deploy/prod.env` dosyasına yukarıdaki iki satırı aynen yaz (`PROD_IMAGE_TAG` `-rc` içeremez). Bu dosyanın kaynak doğrusu `prod-env` branch'idir; `main`'deki kopyası kullanılmaz.
4. **Gerekliyse `uk_tokens.yml`'i sil:** Yalnızca `monitors.yml`'e yeni monitor/group/status-page eklediyseniz, prod host'taki `${HEALTH_AGENT_CONFIG_GENERATED_DIR}/uk_tokens.yml` dosyasını silin ki setup adımı yeniden çalışsın. Salt kod değişikliğinde dosyaya ve Uptime Kuma'daki monitörlere dokunmayın.
5. **`prod-env`'i push'la:** `main`'i `prod-env`'e merge edip `prod.env` değişikliğiyle birlikte push'layın — push, prod workflow'unu tetikler.
6. **Doğrula:**
```bash
docker service inspect monitoring_health-agent --format '{{.Spec.TaskTemplate.ContainerSpec.Image}}'
```
Çıktı `health-agent:<yeni-version>@sha256:<yeni-digest>` olmalı. Ardından `docker service logs monitoring_health-agent` ile check'lerin push'landığını ve Uptime Kuma'da monitörlerin yeşile döndüğünü kontrol edin. Deploy `stop-first` olduğu için heartbeat'lerde 1-2 dakikalık boşluk normaldir.
**Sıfırdan kurulum / monitörleri yeniden yaratma:** Uptime Kuma'daki monitörler silinip baştan oluşturulacaksa, hem UK'daki eski monitör/grupları hem de host'taki `uk_tokens.yml`'i silin; aksi halde eski push monitörlerine heartbeat gelmeyeceği için sahte "down" alarmları üretilir.
---
## Log Formatı
Agent JSON formatında log üretir. Grafana Explore (Loki datasource, `{service="monitoring_health-agent"}`) veya `docker service logs monitoring_health-agent` ile izlenebilir. Her log girdisi şu alanları içerir:
- `check` — monitor adı
- `status` — `up` veya `down`
- `msg` — Uptime Kuma'ya iletilen mesaj
- `ping_ms` — check süresi
- `source` — `health-agent` veya `health-agent/events`
- `error` — yalnızca hata durumunda; exception detayı