# 09 - 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 | | --- | --- | | `iklim-app-01` | `act_runner` systemd | | `iklim-app-02` | `act_runner` systemd | | `iklim-app-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 iklim-app-01 iklim-app-02 iklim-app-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. ## Ön Koşullar — StorageBox Sırları Deploy pipeline çalışmadan önce aşağıdaki dosyaların StorageBox'ta mevcut olması gerekir. Bu dosyalar otomatik oluşturulmaz; ilk kurulumda elle oluşturulur. ### SWAG / GoDaddy Kimlik Bilgileri ``` prod/secrets/iklim.co/.env.secrets.swag ``` ```bash GODADDY_KEY= GODADDY_SECRET= ``` GoDaddy API anahtarı için: https://developer.godaddy.com/keys — **Production** key oluştur. Mevcut bir anahtarın herhangi bir chat, Slack veya e-postada paylaşıldığı biliniyorsa kullanmadan önce iptal et ve yenisini oluştur. > `.env.secrets.swag` yalnızca SWAG/GoDaddy kimlik bilgilerini içerir. > `.env.secrets.shared` AppRole ID'leri, DB şifreleri ve diğer çalışma zamanı sırlarını içerir — bu iki dosyayı karıştırma. ### Gitea PROD_FLOATING_IP Değişkeni DNS otomasyonu için `PROD_FLOATING_IP` Gitea project variable olarak tanımlanmış olmalıdır. `06-prod-terraform-iaac.md` → "Gitea Değişkeni: PROD_FLOATING_IP" adımına bak. ## 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/.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/.lock` | Ileride servis bazli paralel deploy'a gecmek icin | ## Swarm Servis Dagilimi Prod'da 3 app node da manager + app worker oldugu icin servisler 3 node'a dagitilabilir. ### Mikroservisler Her mikroservisin iki stack dosyasi vardir: | Dosya | Icerik | Ortam | | --- | --- | --- | | `BE-/docker-stack-service.yml` | Base tanimlar, `replicas: 1` | Test + Prod | | `BE-/docker-stack-service.prod.yml` | `replicas: 3`, `max_replicas_per_node: 1` | Yalnizca Prod | Prod deploy komutu: ```bash docker stack deploy \ -c BE-/docker-stack-service.yml \ -c BE-/docker-stack-service.prod.yml \ iklimco ``` `max_replicas_per_node: 1` zorunludur; bu olmadan Swarm node sayisi < replica sayisina dustugunde ayni node'a birden fazla replica yerlestirir. ### Infra Servisleri `docker-stack-infra.yml` (base) ile `docker-stack-infra.prod.yml` (overlay) birlikte deploy edilir. Overlay; Vault, APISIX, RabbitMQ, Redis Sentinel gibi servisleri `replicas: 3` ve `max_replicas_per_node: 1` ile override eder. Detay: `Environment_Infrastructure/roadmap/prod-env/03-infra-stack-changes.md`. ## Gateway ve Public Trafik Public internet sadece `80/tcp` ve `443/tcp` ile SWAG uzerinden girer. SWAG `iklim-app-01`'e sabitlenmistir (Floating IP bu node'da). APISIX admin portlari (`9180`) ve diger servis portlari public acilmaz; SWAG reverse proxy olarak tum public trafigi APISIX'e iletir. Detay: `Environment_Infrastructure/roadmap/prod-env/04-swag-nginx-configs.md`. ## 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. - StorageBox'ta `prod/secrets/iklim.co/.env.secrets.swag` mevcuttur ve geçerli GoDaddy kimlik bilgilerini içerir. - Gitea'da `PROD_FLOATING_IP` project variable tanımlıdır.