# 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.` beklentisi yazılıp setup script çalıştırılır. `replicas.`, 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 [] ` 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:-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= ./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: PROD_IMAGE_TAG= ``` 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:@sha256:` 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ı