Adds two-layer BE-* microservice monitoring: an aggregate Stack Services replica check across the iklimco and monitoring Swarm stacks (checks/swarm_services.py), and per-service actuator/DNS health checks driven by a new microservice_monitors section in monitors.yml (checks/actuator.py). BE-* services are excluded from the Stack Services aggregate so a single service incident produces exactly one Slack alert instead of two. Fixes found during QA of the initial implementation: RabbitMQ host derivation generated nonexistent numbered DNS names instead of using the real single-service topology, RabbitMQ and Patroni cluster checks did not push down status on node/member shortfall, and the etcd cluster check still used a hardcoded node list and quorum threshold instead of deriving them from CLUSTER_SIZE_ETCD. Also hardens Docker event crash alerting: excludes ephemeral Gitea Actions runner containers from crash notifications, skips alerts for containers Swarm intentionally stopped (rolling update/scale-down, detected via task DesiredState) instead of alerting on every deploy, and adds human-readable exit code descriptions to the Slack message. Uptime Kuma monitor names are now prefixed with "iklim [env]" since test and prod share one Kuma instance and unprefixed names collided. setup_uptime_kuma.py gained an ensure_push_monitor helper and a microservice push-monitor creation pass. Removed state.py and the unused restart_threshold config field (dead code, no longer referenced anywhere). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
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 dinleriklimco-netoverlay 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.pytarafı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
src/health_agent/checks/altına yeni bir dosya ekle veya uygun mevcut dosyaya yeni bir fonksiyon ekle.- Fonksiyon
(ok: bool, msg: str, ping_ms: int)tuple'ı döndürmeli. config/monitors.yml'e yeni monitor bloğu ekle (isim, grup, öncelik, bildirim kanalı, check periyodu).setup_uptime_kuma.py'yi çalıştır — yeni monitor UK'da oluşturulur ve tokenuk_tokens.yml'e yazılır.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.
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
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 ayrı Gitea workflow'larıyla deploy edilir:
.gitea/workflows/deploy-monitoring-prod.yml— prod ortamı.gitea/workflows/deploy-monitoring-test.yml— test ortamı
Her iki workflow da şu sırayı izler: (1) setup_uptime_kuma.py çalıştır → uk_tokens.yml üret, (2) monitoring stack'i deploy et, (3) health-agent stack'ini deploy et.
Manuel deploy için:
# ö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.
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—upveyadownmsg— Uptime Kuma'ya iletilen mesajping_ms— check süresisource—health-agentveyahealth-agent/eventserror— yalnızca hata durumunda; exception detayı