Murat ÖZDEMİR 27f4f83f73 docs(prod): resolve cross-layer inconsistencies and complete prod env implementation
Ansible roles:
- act_runner/defaults: set act_runner_name to inventory_hostname (was
  hardcoded to iklim-test-app); added vault_gitea_runner_token to vault.yml
- prod/group_vars/all: restructured from flat files to all/ directory;
  added act_runner_labels override (prod-runner,ubuntu-24.04,hostname);
  added storagebox_managed_directories; added swarm_manager_ip and other
  prod-specific vars
- prod/roles/db_stack: prod-specific db_node tasks using StorageBox paths
  (/mnt/storagebox/db/...) instead of local paths
- docker/tasks: split firewalld loop into all-nodes (Swarm ports) and
  app-only (80/443) tasks
- swarm/tasks: added --advertise-addr private_ip to join commands for
  correct multi-homed node advertisement
- hardening/tasks: corrected firewalld drop zone configuration
- node_dirs/tasks: added /opt/iklimco/vault/data for Vault Raft volume
- db_stack/tasks/app_node: updated stale comment (removed pg-proxy reference)
- db_stack/templates: removed pg-proxy and mongo-proxy service blocks
- test/host_vars/iklim-app-01: added act_runner_name override to preserve
  existing test runner registration

Roadmap and setup docs:
- roadmap/03-infra-stack-changes: added replicas:0 for etcd/postgresql/
  mongodb/pg-proxy/mongo-proxy in prod overlay; updated placement table;
  fixed grafana/data mkdir (auto-created by Ansible); translated Turkish
  note to English
- roadmap/08-deploy-pipeline-update: updated stale "remains idle" note
  for standalone etcd (now disabled with replicas:0)
- roadmap/01-swarm-init-multinode: consistency fixes
- setup/06: added Outputs section and etcd firewall port documentation
- setup/07: removed prometheus/data from StorageBox acceptance criteria;
  replaced manual StorageBox mkdir section with Ansible auto-creation note;
  updated prod README section with full bootstrap instructions and vault docs;
  added act_runner_labels prod policy
- setup/08: extensive rewrite — aligned with Patroni etcd overlay DNS,
  corrected hcloud_firewall.app reference, updated all StorageBox paths
  from /prod/db/ to /db/
- setup/09: removed prometheus/data from acceptance criteria; updated
  runner label policy (removed docker/swarm-manager labels); added
  acceptance criterion for disabled services absent from docker service ls

Terraform:
- prod/firewall.tf: added missing DB subnet mutual rules (etcd, Patroni)
- prod/outputs.tf: added prod_floating_ip and prod_private_ips outputs
- prod/servers.tf: aligned placement group and naming
- prod/variables.tf: corrected variable descriptions
- prod/terraform.tfvars.example: updated defaults
- terraform/hetzner/README.md: new comprehensive README covering both
  test and prod environments with firewall tables and inventory instructions

ansible/README.md: expanded prod section with inventory groups, bootstrap
  run order, runner label policy, and vault variable documentation
2026-05-18 19:17:56 +03:00

447 lines
13 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.

# 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, overlay ağ, 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 \
--ask-vault-pass
# 2. Swarm kurulumu (app node'lar önce, ardından db node'lar)
ansible-playbook prod-bootstrap.yml \
--tags swarm \
--ask-vault-pass
# 3. DB node label'ları (Patroni koordinasyonu için)
ansible-playbook prod-bootstrap.yml \
--tags db_labels \
--ask-vault-pass
# 4. DB node konfigürasyonu (StorageBox dizin ve config dosyaları)
ansible-playbook prod-bootstrap.yml \
--tags db_stack \
--ask-vault-pass
# 5. App node runner kurulumu
ansible-playbook prod-bootstrap.yml \
--tags act_runner \
--ask-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 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.