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

187 lines
4.8 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.

# Terraform — iklim.co Hetzner Cloud Altyapısı
Bu dizin, iklim.co test ve prod ortamlarının Hetzner Cloud altyapısını Terraform ile yönetir.
## Dizin Yapısı
```text
terraform/hetzner/
test/ — test ortamı: 1 app + 1 db node, single-node Swarm
prod/ — prod ortamı: 3 app + 3 db node, 3-manager HA Swarm
```
Her ortam kendi bağımsız Terraform state dosyasına sahiptir; birbirini etkilemez.
## Ortam Karşılaştırması
| Özellik | Test | Prod |
| --- | --- | --- |
| App node sayısı | 1 (`iklim-app-01`) | 3 (`iklim-app-01/02/03`) |
| DB node sayısı | 1 (`iklim-db-01`) | 3 (`iklim-db-01/02/03`) |
| App sunucu tipi | `cpx42` | `cpx42` |
| DB sunucu tipi | `cpx42` | `cpx32` |
| Swarm mimarisi | Single-node | 3-manager HA |
| App subnet | `10.10.10.0/24` | `10.20.10.0/24` |
| DB subnet | `10.10.20.0/24` | `10.20.20.0/24` |
| Floating IP | Var | Var |
| Placement group | Yok | Spread (farklı fiziksel host) |
## Ön Koşullar
- Terraform >= 1.5 kurulu olmalı.
- Hetzner Cloud ortama özel proje API token'ı hazır olmalı (test ve prod ayrı proje).
- `terraform.tfvars` dosyası oluşturulmuş olmalı (bkz. `terraform.tfvars.example`).
## terraform.tfvars Kurulumu
```bash
# Test için:
cd terraform/hetzner/test
cp terraform.tfvars.example terraform.tfvars
# Prod için:
cd terraform/hetzner/prod
cp terraform.tfvars.example terraform.tfvars
```
`terraform.tfvars` içindeki değişkenler:
| Değişken | Açıklama |
| --- | --- |
| `hcloud_token` | Hetzner Cloud ortama özel proje API token'ı |
| `location` | Sunucu lokasyonu (örn. `fsn1`) |
| `image` | Sunucu işletim sistemi (örn. `rocky-10`) |
| `server_type_app` | App sunucu tipi |
| `server_type_db` | DB sunucu tipi |
| `admin_ssh_public_key_path` | Admin SSH public key dosya yolu |
| `admin_allowed_cidrs` | SSH erişimine izin verilen CIDR listesi |
> `terraform.tfvars` hassas bilgi içerir; repository'e commit edilmez.
## Terraform Komutları
Tüm komutlar ilgili ortam dizininden çalıştırılmalıdır:
```bash
# Test:
cd terraform/hetzner/test
# Prod:
cd terraform/hetzner/prod
```
### Başlatma
```bash
terraform init
```
### Değişiklik önizleme
```bash
terraform plan
```
### Uygulama
```bash
terraform apply
```
### Kaynakları kaldırma
```bash
terraform destroy
```
## Ansible Inventory Üretimi
`terraform apply` tamamlandıktan sonra Ansible inventory'si şu komutlarla üretilir:
```bash
# Test inventory:
cd terraform/hetzner/test
terraform output -raw ansible_inventory_yaml \
> ../../../ansible/test/inventory/generated/test.yml
# Prod inventory:
cd terraform/hetzner/prod
terraform output -raw ansible_inventory_yaml \
> ../../../ansible/prod/inventory/generated/prod.yml
```
Sunucu ekleme/silme veya IP değişimi sonrası inventory yeniden üretilmelidir.
## Outputs
### Test
| Output | Açıklama |
| --- | --- |
| `ansible_inventory_yaml` | Ansible inventory YAML |
| `test_private_ips` | Node private IP haritası |
| `test_public_ips` | Node public IPv4 haritası |
| `test_floating_ip` | Swarm giriş noktası floating IP |
### Prod
| Output | Açıklama |
| --- | --- |
| `ansible_inventory_yaml` | Ansible inventory YAML |
| `prod_private_ips` | Node private IP haritası (`app` ve `db` alt anahtarlarıyla) |
| `prod_public_ips` | Node public IPv4 haritası |
| `prod_floating_ip` | Swarm giriş noktası floating IP — DNS A kaydı bu IP'ye yönlendirilir |
```bash
# Floating IP'yi görmek için:
terraform output prod_floating_ip # veya test_floating_ip
```
## Güvenlik Duvarı Özeti
### App Firewall (her iki ortam)
| Port | Protokol | Kaynak | Açıklama |
| --- | --- | --- | --- |
| `22` | TCP | `admin_allowed_cidrs` | SSH |
| `80` | TCP | 0.0.0.0/0 | HTTP (SWAG) |
| `443` | TCP | 0.0.0.0/0 | HTTPS (SWAG) |
| `2377` | TCP | DB subnet | Docker Swarm control plane |
| `7946` | TCP/UDP | DB subnet | Docker Swarm node discovery |
| `4789` | UDP | DB subnet | Docker Swarm VXLAN overlay |
### DB Firewall (her iki ortam)
App subnet kaynaklı:
| Port | Açıklama |
| --- | --- |
| `22/tcp` | SSH |
| `5432/tcp` | PostgreSQL |
| `27017/tcp` | MongoDB |
| `2377/tcp` | Docker Swarm control plane |
| `7946/tcp,udp` | Docker Swarm node discovery |
| `4789/udp` | Docker Swarm VXLAN overlay |
Prod'a özgü (app subnet kaynaklı):
| Port | Açıklama |
| --- | --- |
| `2379/tcp` | etcd client (Patroni + APISIX) |
Prod'a özgü (DB subnet içi, karşılıklı):
| Port | Açıklama |
| --- | --- |
| `5432/tcp` | Patroni replikasyon |
| `27017/tcp` | MongoDB replica set internal |
| `2379/tcp` | etcd client |
| `2380/tcp` | etcd peer |
| `8008/tcp` | Patroni REST API |
> IP kısıtlaması (admin paneli, dashboard vb.) Hetzner Firewall'da değil, SWAG nginx konfigürasyonunda yapılır.
## Sonraki Adım
Terraform apply ve inventory üretiminin ardından Ansible bootstrap çalıştırılır. Detaylar için `ansible/README.md` dosyasına bakın.