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.ymlsetup_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.

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 Gitea workflow'larıyla deploy edilir:

  • .gitea/workflows/deploy-monitoring-test.ymltest 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.ymlprod-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:

# ö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.00.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):
    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:
    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ı
  • statusup veya down
  • msg — Uptime Kuma'ya iletilen mesaj
  • ping_ms — check süresi
  • sourcehealth-agent veya health-agent/events
  • error — yalnızca hata durumunda; exception detayı