Murat ÖZDEMİR 51933afea6 feat(infra): Refactor Swarm networking for reliable DNS and stack ownership
Moves `iklimco-net` overlay network creation to be managed by the Docker Swarm stack, ensuring reliable embedded DNS resolution for inter-service communication. This resolves issues where services on external overlay networks failed to discover each other via Docker DNS.

This refactoring includes:
*   Removing the manual `iklimco-net` creation from the Ansible `swarm` role.
*   Adjusting `act_runner` configuration to connect job containers to `iklimco-net` only after the stack has deployed and created the network.
*   Setting `storagebox_file_mode` to `0600` for DB nodes to prevent "too open" errors with MongoDB keyfiles.
*   Provisioning dedicated bind mount directories for MongoDB and PostgreSQL on DB nodes with correct ownership and permissions.
*   Updating documentation to reflect the consolidated stack and network changes.
2026-05-26 01:08:12 +03:00

447 lines
13 KiB
Markdown
Raw Permalink 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.

# iklim.co Ansible Kullanım Rehberi
Bu dizin, iklim.co test ve prod sunucu ortamlarının Ansible ile hazırlanması için kullanılan playbook, role, inventory ve değişken dosyalarını içerir.
Mevcut kapsam:
- Test ortamı bootstrap ve post-stack hazırlıkları.
- Ortak Ansible rollerinin yönetimi.
- Terraform tarafından üretilen inventory dosyalarının kullanımı.
- Ansible Vault ile şifreli değişken yönetimi.
- Prod ortamı için başlangıç playbook yapısı.
Prod ortamı tamamlandıkça bu README içindeki prod başlıkları genişletilecektir.
## Dizin Yapısı
```text
Environment_Infrastructure/ansible/
README.md
requirements.yml
roles/
test/
ansible.cfg
inventory/generated/test.yml
group_vars/
host_vars/
test-bootstrap.yml
test-app-post-stack.yml
test-db-post-stack.yml
prod/
ansible.cfg
inventory/generated/prod.yml
group_vars/
prod-bootstrap.yml
```
## Temel Kavramlar
| Kavram | Açıklama |
| --- | --- |
| Playbook | Çalıştırılacak Ansible iş akışını tanımlar. Örn. `test-bootstrap.yml`. |
| Role | Tekrarlanabilir kurulum birimidir. Örn. `docker`, `swarm`, `db_stack`. |
| Inventory | Ansible'ın bağlanacağı hostları ve host gruplarını tanımlar. |
| Tag | Playbook içindeki belirli role/task'ları seçerek çalıştırmayı sağlar. |
| Vault | Şifreli değişkenlerin güvenli tutulması için Ansible Vault kullanımıdır. |
| `ansible.cfg` | Inventory, role path, remote user ve privilege escalation gibi varsayılanları belirler. |
## Inventory Kaynağı
Inventory dosyaları elle yazılan ana kaynak değildir. Terraform tarafından üretilen `ansible_inventory_yaml` output'u dosyaya aktarılır.
Test inventory üretimi:
```bash
cd Environment_Infrastructure/terraform/hetzner/test
terraform output -raw ansible_inventory_yaml > ../../../ansible/test/inventory/generated/test.yml
```
Prod inventory üretimi:
```bash
cd Environment_Infrastructure/terraform/hetzner/prod
terraform output -raw ansible_inventory_yaml > ../../../ansible/prod/inventory/generated/prod.yml
```
Inventory içeriği Terraform'un oluşturduğu Hetzner kaynaklarından gelir:
- Host adı
- Public IP: `ansible_host`
- SSH kullanıcısı: `ansible_user`
- Private network IP: `private_ip`
Sunucu ekleme/silme, public IP değişimi veya private IP değişimi Terraform tarafında yapıldıktan sonra inventory yeniden üretilmelidir. Aksi halde Ansible eski host bilgileriyle çalışır.
## Ortak Komut Parametreleri
| Parametre | Açıklama |
| --- | --- |
| `ansible-playbook` | Bir playbook dosyasını çalıştırır. |
| `-i <inventory>` | Kullanılacak inventory dosyasını belirtir. |
| `--tags <tag>` | Sadece belirtilen tag'e sahip role/task'ları çalıştırır. |
| `--limit <host-or-group>` | Çalışmayı belirli host veya host grubuyla sınırlar. |
| `--vault-password-file=<file>` | Ansible Vault ile şifrelenmiş değişkenleri açmak için parola dosyasını kullanır. |
| `--check` | Değişiklikleri uygulamadan deneme çalıştırması yapar. |
| `--list-tasks` | Çalışacak task listesini gösterir. |
## Test Ortamı
Test komutları `Environment_Infrastructure/ansible/test` dizini altından çalıştırılmalıdır:
```bash
cd Environment_Infrastructure/ansible/test
```
Bu dizindeki `ansible.cfg` şu varsayılanları tanımlar:
- `inventory = inventory/generated/test.yml`
- `remote_user = root`
- `roles_path = ../roles`
- `become = True`
Bu nedenle `-i inventory/generated/test.yml` parametresi teknik olarak zorunlu değildir; komutlarda görünürlük için kullanılabilir.
### Test Inventory Grupları
| Grup | Host | Amaç |
| --- | --- | --- |
| `app` | `iklim-app-01` | Uygulama node'u, runner ve deploy işleri |
| `db` | `iklim-db-01` | Veritabanı node'u, DB stack ve WireGuard |
`--limit` örnekleri:
```bash
--limit iklim-app-01
--limit app
--limit db
```
### Test Playbook'ları
| Playbook | Host kapsamı | Amaç |
| --- | --- | --- |
| `test-bootstrap.yml` | `all`, `app`, `db` | Base, hardening, Docker, node dizinleri, StorageBox ve Swarm hazırlıkları |
| `test-app-post-stack.yml` | `app` | Gitea runner ve app node deploy ön koşulları |
| `test-db-post-stack.yml` | `db` | DB stack ve WireGuard hazırlıkları |
### Test Bootstrap
Sadece `base` tag'ini `iklim-app-01` üzerinde çalıştırmak için:
```bash
ansible-playbook test-bootstrap.yml \
-i inventory/generated/test.yml \
--tags base \
--limit iklim-app-01 \
--vault-password-file=../.vault_pass
```
`test-bootstrap.yml` içindeki başlıca tag'ler:
| Tag | Rol | Amaç |
| --- | --- | --- |
| `base` | `base` | Temel paketler, sistem ayarları ve genel hazırlıklar |
| `hardening` | `hardening` | SSH ve güvenlik sıkılaştırmaları |
| `docker` | `docker` | Docker kurulumu ve ayarları |
| `node_dirs` | `node_dirs` | Ortak node dizinlerinin hazırlanması |
| `storagebox` | `storagebox` | StorageBox mount/dizin hazırlıkları |
| `storagebox_ssh_key` | `storagebox_ssh_key` | StorageBox SSH key hazırlığı |
| `swarm` | `swarm` | Docker Swarm kurulumu |
Örnekler:
```bash
# Tüm hostlarda Docker rolünü çalıştır
ansible-playbook test-bootstrap.yml \
--tags docker \
--vault-password-file=../.vault_pass
# Sadece app grubunda hardening rolünü çalıştır
ansible-playbook test-bootstrap.yml \
--tags hardening \
--limit app \
--vault-password-file=../.vault_pass
# Swarm kurulumunu çalıştır
ansible-playbook test-bootstrap.yml \
--tags swarm \
--vault-password-file=../.vault_pass
```
### Test App Node Hazırlıkları
```bash
ansible-playbook test-app-post-stack.yml \
-i inventory/generated/test.yml \
--tags act_runner \
--vault-password-file=../.vault_pass
```
Bu komut `app` grubundaki hostlarda `act_runner` rolünü çalıştırır.
Amaç:
- Gitea Actions runner kurulumu.
- Runner servis/dizin hazırlığı.
- Deploy ön koşullarının hazırlanması.
Ön koşul:
- Gitea arayüzünden `Organization -> Settings -> Actions -> Runners` altında registration token alınır.
- Token, Vault ile şifreli değişkenlerde `vault_gitea_runner_token` olarak tanımlanır.
Not:
- Token tanımlı değilse kurulum tamamlanabilir ama runner kayıt adımı atlanır.
- `.runner` dosyası varsa kayıt tekrar yapılmaz; rol idempotent çalışacak şekilde tasarlanmıştır.
### Test DB Node Hazırlıkları
```bash
ansible-playbook test-db-post-stack.yml \
-i inventory/generated/test.yml \
--tags db_stack \
--vault-password-file=../.vault_pass
```
Bu komut `db` grubundaki hostlarda `db_stack` rolünü çalıştırır.
Amaç:
- PostgreSQL/PostGIS ve MongoDB için host hazırlıkları.
- DB ile ilgili dizin, config ve secret bağımlılıklarının hazırlanması.
- Test ortamındaki DB node'un stack sonrası operasyonel hale getirilmesi.
`test-db-post-stack.yml` içindeki tag'ler:
| Tag | Rol | Amaç |
| --- | --- | --- |
| `db_stack` | `db_stack` | PostgreSQL/MongoDB stack hazırlıkları |
| `wireguard` | `wireguard` | WireGuard VPN client/server ayarları |
Sadece WireGuard güncellemek için:
```bash
ansible-playbook test-db-post-stack.yml \
--tags wireguard \
--vault-password-file=../.vault_pass
```
WireGuard client eklemek için `group_vars/all/vars.yml` içindeki `wireguard_clients` listesine client public key'i eklenir.
### Test İçin Önerilen Çalıştırma Sırası
```bash
# 1. Temel sunucu hazırlıkları
ansible-playbook test-bootstrap.yml \
--tags base,hardening,docker,node_dirs,storagebox,storagebox_ssh_key \
--vault-password-file=../.vault_pass
# 2. Swarm kurulumu
ansible-playbook test-bootstrap.yml \
--tags swarm \
--vault-password-file=../.vault_pass
# 3. App node runner/deploy hazırlıkları
ansible-playbook test-app-post-stack.yml \
--tags act_runner \
--vault-password-file=../.vault_pass
# 4. DB node hazırlıkları
ansible-playbook test-db-post-stack.yml \
--tags db_stack,wireguard \
--vault-password-file=../.vault_pass
```
Rolleri tek tek çalıştırmak, hata durumunda hangi adımın problem çıkardığını daha net görmeyi sağlar.
## Prod Ortamı
Prod ortamı için mevcut başlangıç dosyaları:
```text
prod/ansible.cfg
prod/prod-bootstrap.yml
prod/group_vars/
```
Prod komutları `Environment_Infrastructure/ansible/prod` dizini altından çalıştırılmalıdır:
```bash
cd Environment_Infrastructure/ansible/prod
```
Bu dizindeki `ansible.cfg` şu varsayılanları tanımlar:
- `inventory = inventory/generated/prod.yml`
- `remote_user = root`
- `roles_path = ../roles`
- `become = True`
Prod inventory, prod Terraform çıktısından üretilir:
```bash
cd Environment_Infrastructure/terraform/hetzner/prod
terraform output -raw ansible_inventory_yaml > ../../../ansible/prod/inventory/generated/prod.yml
```
### Prod Inventory Grupları
| Grup | Host'lar | Rol |
| --- | --- | --- |
| `app` | `iklim-app-01`, `iklim-app-02`, `iklim-app-03` | Swarm manager + uygulama worker |
| `db` | `iklim-db-01`, `iklim-db-02`, `iklim-db-03` | Swarm worker + DB cluster node'u |
`--limit` örnekleri:
```bash
--limit iklim-app-01
--limit app
--limit db
```
### Prod Playbook ve Tag'ler
Ana playbook: `prod-bootstrap.yml`
| Tag | Rol | Host kapsamı | Amaç |
| --- | --- | --- | --- |
| `base` | `base` | `all` | Temel paketler, timezone, hostname, NTP |
| `hardening` | `hardening` | `all` | SSH, fail2ban, firewalld drop zone, dnf-automatic, iklim kullanıcısı |
| `docker` | `docker` | `all` | Docker Engine kurulumu ve Swarm portları |
| `node_dirs` | `node_dirs` | `all` | Node dizinleri (`/opt/iklimco/...`) |
| `storagebox` | `storagebox` | `all` | WebDAV mount ve yönetilen dizinlerin oluşturulması |
| `storagebox_ssh_key` | `storagebox_ssh_key` | `all` | StorageBox SSH key üretimi |
| `swarm` | `swarm` | `app`, `db` | Swarm init/join, `iklimco-net` overlay ağı (MTU=1400), node label'ları |
| `db_labels` | inline task | `iklim-app-01` | DB node'larına `role=db` ve `db-index=01/02/03` label'ı ekler |
| `db_stack` | `db_stack` | `db` | StorageBox'ta MongoDB ve PostgreSQL config dizinleri |
| `act_runner` | `act_runner` | `app` | Gitea Actions runner kurulumu ve kaydı |
### Prod Bootstrap Çalıştırma Sırası
```bash
# 1. Temel sunucu hazırlıkları (tüm node'lar)
ansible-playbook prod-bootstrap.yml \
--tags base,hardening,docker,node_dirs,storagebox,storagebox_ssh_key \
--vault-password-file=../.vault_pass
# 2. Swarm kurulumu (app node'lar önce, ardından db node'lar)
ansible-playbook prod-bootstrap.yml \
--tags swarm \
--vault-password-file=../.vault_pass
# 3. DB node label'ları (Patroni koordinasyonu için)
ansible-playbook prod-bootstrap.yml \
--tags db_labels \
--vault-password-file=../.vault_pass
# 4. DB node konfigürasyonu (StorageBox dizin ve config dosyaları)
ansible-playbook prod-bootstrap.yml \
--tags db_stack \
--vault-password-file=../.vault_pass
# 5. App node runner kurulumu
ansible-playbook prod-bootstrap.yml \
--tags act_runner \
--vault-password-file=../.vault_pass
```
### Prod Act Runner
Runner'lar tüm app node'larında (`iklim-app-01/02/03`) systemd servisi olarak kurulur.
Label'lar `prod/group_vars/all/vars.yml` içinde tanımlıdır:
```
prod-runner
ubuntu-24.04
iklim-app-01 (veya iklim-app-02, iklim-app-03 — node'a göre değişir)
```
Kayıt token'ı `prod/group_vars/all/vault.yml` içinde `vault_gitea_runner_token` olarak tutulur. Token tanımlı değilse kayıt adımı atlanır; `.runner` dosyası varsa kayıt tekrar yapılmaz.
Gitea üzerinden token almak için: **Organization → Settings → Actions → Runners → Add Runner**
### Prod Vault Dosyası
`prod/group_vars/all/vault.yml` şifreli olarak tutulur ve şu değişkenleri içerir:
| Değişken | Açıklama |
| --- | --- |
| `vault_storagebox_password` | StorageBox WebDAV şifresi |
| `vault_iklim_password` | `iklim` sistem kullanıcısı şifresi |
| `vault_gitea_runner_token` | Gitea runner kayıt token'ı |
Şifreleme:
```bash
cd Environment_Infrastructure/ansible/prod
ansible-vault encrypt group_vars/all/vault.yml
```
Şifre çözme (düzenleme için):
```bash
ansible-vault edit group_vars/all/vault.yml --vault-password-file=../.vault_pass
```
## Vault Kullanımı
Bu Ansible yapısı şifreli değerler için Ansible Vault kullanır.
Örnek şifreli dosyalar:
```text
test/group_vars/all/vault.yml
test/host_vars/iklim-app-01/vault.yml
test/host_vars/iklim-db-01/vault.yml
```
Komutlarda kullanılan parametre:
```bash
--vault-password-file=../.vault_pass
```
Bu parametre, Ansible'ın Vault ile şifrelenmiş değişkenleri açabilmesini sağlar. `.vault_pass` dosyası repository dışına sızdırılmamalı ve CI/CD ortamında güvenli secret olarak yönetilmelidir.
## Kontrol Komutları
Komutu gerçekten çalıştırmadan hangi host ve task'ların etkileneceğini görmek için:
```bash
ansible-playbook test-bootstrap.yml \
--tags base \
--limit iklim-app-01 \
--vault-password-file=../.vault_pass \
--check
```
Hangi task'ların çalışacağını listelemek için:
```bash
ansible-playbook test-bootstrap.yml \
--tags base \
--list-tasks \
--vault-password-file=../.vault_pass
```
Inventory'deki hostları görmek için:
```bash
ansible-inventory \
-i inventory/generated/test.yml \
--list
```
Belirli host'a ping atmak için:
```bash
ansible iklim-app-01 \
-i inventory/generated/test.yml \
-m ping \
--vault-password-file=../.vault_pass
```
Prod için aynı komutlar `ansible/prod` dizininden ve `inventory/generated/prod.yml` inventory'siyle çalıştırılmalıdır.