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