Environment_Infrastructure/setup/06-prod-runner-ha-ve-swarm.md
2026-05-09 16:26:06 +03:00

159 lines
5.7 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.

# 06 - Prod Runner HA ve Swarm Deploy Modeli
Bu asamanin amaci prod ortaminda Gitea Actions runner'lari HA calisacak sekilde kurmak ve Swarm uzerinde servislerin 3 node'a dagitilmasina uygun on kosullari tanimlamaktir.
## Runner Sayisi
Tek runner fonksiyonel olarak yeterlidir, ancak HA degildir. Prod hedefi HA oldugu icin `act_runner` 3 Swarm manager node'unun tamamına systemd servisi olarak kurulacak:
| Host | Runner |
| --- | --- |
| `prod-swarm-01` | `act_runner` systemd |
| `prod-swarm-02` | `act_runner` systemd |
| `prod-swarm-03` | `act_runner` systemd |
Bu modelde herhangi bir manager/runner kaybedilirse diger runner'lar pipeline job'larini alabilir.
## Runner Kurulum Modeli
Runner Docker container olarak calismayacak. Docker socket mount yok.
Kurulum:
- `gitea-runner` sistem kullanicisi
- `/usr/local/bin/act_runner`
- `/etc/gitea-act-runner/config.yaml`
- `/var/lib/gitea-runner`
- `gitea-act-runner.service`
Runner job'lari deploy icin Docker CLI kullanacaksa `gitea-runner` kullanicisinin Docker daemon erisimi gerekir. Docker group uyeligi root seviyesine yakin yetki kabul edilir; sadece guvenilir repo/job'lar bu runner label'larini kullanmalidir.
## Runner Label PolitikasI
Tum prod runner'larda ortak label:
```text
prod-runner
docker
swarm-manager
ubuntu-24.04
```
Node-spesifik label'lar:
```text
prod-swarm-01
prod-swarm-02
prod-swarm-03
```
Mevcut prod workflow'lari `runs-on: prod-runner` kullaniyorsa 3 runner'dan herhangi biri job'u alabilir. Belirli bir node'a sabitlemek gerekirse node-spesifik label kullanilir.
## Deploy Yarismasi Riski
Birden fazla runner oldugunda ayni anda birden fazla deploy job'u calisabilir. Bu HA icin iyidir ama ortak kaynaklarda yarisma riski yaratabilir.
Riskli alanlar:
- Ayni stack uzerinde es zamanli `docker stack deploy`
- Ayni servis icin es zamanli `docker service update`
- StorageBox'ta ayni `.env` veya manifest dosyasinin es zamanli guncellenmesi
- Root altyapi pipeline'i ile mikroservis deploy pipeline'inin ayni anda calismasi
Gerekli onlem:
- Prod root altyapi deploy'u manuel/onayli calismali.
- Ayni servis icin prod deploy ayni anda birden fazla kez tetiklenmemeli.
- Prod deploy workflow'lari StorageBox uzerinde otomatik deploy lock kullanmalidir.
## StorageBox Deploy Lock Modeli
Prod'da 3 runner oldugu icin deploy lock zorunlu kabul edilir. Lock lokal dosya
sisteminde tutulmayacak; cunku runner'lar farkli makinelerde calisir ve birbirlerinin
`/tmp` veya `/var/lock` dizinlerini gormez.
Lock konumu StorageBox olacaktir:
```text
prod/locks/prod-deploy.lock
prod/locks/prod-infra.lock
prod/locks/services/<service-name>.lock
```
Baslangic modeli:
```text
prod/locks/prod-deploy.lock
```
Bu tek global lock tum prod deploy'lari siraya sokar ve en az karmasik modeldir.
Ileride deploy sureleri uzarsa servis bazli lock'a gecilebilir.
Lock dosyasi/klasoru manuel olusturulmaz. Workflow basinda atomik `mkdir` ile lock
alinir, workflow sonunda `rmdir` ile lock birakilir.
Ornek:
```bash
LOCK_DIR="prod/locks/prod-deploy.lock"
LOCK_META="owner.txt"
ssh "$STORAGEBOX_SSH" "mkdir -p prod/locks && mkdir '$LOCK_DIR'"
ssh "$STORAGEBOX_SSH" "printf '%s\n' 'runner=${GITEA_RUNNER_NAME:-unknown}' 'run=${GITHUB_RUN_ID:-unknown}' 'created_at=$(date -u +%FT%TZ)' > '$LOCK_DIR/$LOCK_META'"
# deploy islemleri
ssh "$STORAGEBOX_SSH" "rm -f '$LOCK_DIR/$LOCK_META' && rmdir '$LOCK_DIR'"
```
Davranis:
- `mkdir '$LOCK_DIR'` basariliysa lock alinmistir.
- `mkdir '$LOCK_DIR'` fail olursa baska deploy calisiyor kabul edilir.
- Job fail olsa bile cleanup adimi `rm/rmdir` calistirmalidir.
- Stale lock temizligi manuel/onayli olmalidir; otomatik zorla silme ilk asamada uygulanmamalidir.
Lock seviyesi:
| Lock | Ne icin |
| --- | --- |
| `prod/locks/prod-deploy.lock` | Ilk asama: tum prod deploy'lar icin global lock |
| `prod/locks/prod-infra.lock` | Ileride root infra deploy'u mikroservis deploy'larindan ayirmak icin |
| `prod/locks/services/<service-name>.lock` | Ileride servis bazli paralel deploy'a gecmek icin |
## Swarm Servis Dagilimi
Prod'da 3 node da manager + app worker oldugu icin servisler 3 node'a dagitilabilir.
Uygulama servisleri icin ileride `docker-stack-service.yml` deploy ayarlari su prensiplere gore revize edilebilir:
- Stateless servislerde `replicas: 3`
- `placement` ile sadece app-capable node'lar secilir
- `update_config` rolling update olacak sekilde ayarlanir
- `restart_policy` aktif kalir
- State tutan servisler app worker uzerinde cogaltilmaz; stateful katman DB node'larinda ayridir
Mevcut repo durumunda mikroservis stack dosyalari servis bazli deploy ediliyor. Bu dokuman, prod HA hedefi icin runner ve Swarm on kosullarini tanimlar; her mikroservisin replica sayisi ayri uygulama deploy refaktoru olarak ele alinmalidir.
## Gateway ve Public Trafik
Public internet sadece `80/tcp` ve `443/tcp` ile gateway katmanina girmelidir.
Mevcut stack dosyalarinda APISIX `8080/8443` publish ediyor olabilir. Prod hedef mimaride public firewall sadece `80/443` acik oldugu icin iki secenekten biri secilmelidir:
1. APISIX/SWAG host publish portlari `80/443` ile uyumlu hale getirilir.
2. Hetzner Load Balancer veya reverse proxy `80/443` alip Swarm gateway portlarina private network uzerinden aktarir.
Bu karar Terraform/Ansible bootstrap'tan ayridir; uygulama altyapi manifest revizyonu gerektirir.
## Kabul Kriterleri
- 3 prod runner Gitea UI'da online gorunur.
- Her runner `prod-runner` label'ina sahiptir.
- Runner'lardan herhangi biri basit Docker komutu calistirabilir.
- `docker node ls` 3 manager gosterir.
- Bir runner/node kapatildiginda diger runner yeni job alabilir.
- Prod workflow'lari StorageBox uzerindeki `prod/locks/prod-deploy.lock` global lock'unu kullanir.
- Lock manuel degil, workflow tarafindan `mkdir/rmdir` ile otomatik yonetilir.
- Public ingress sadece `22`, `80`, `443` ile sinirlidir.