- Add `hetzner-sizing-report.md` defining data-driven server type recommendations for test and prod environments.
- Update Terraform configurations to align with the recommended `CPX` server types and refine firewall rules for Docker Swarm and database interactions.
- Introduce comprehensive documentation and stack files for:
- Single-node PostgreSQL/MongoDB deployment on a test DB worker node.
- High-availability 3-node MongoDB replica set and Patroni+etcd PostgreSQL cluster for production.
- Enhance Ansible bootstrap roles with SELinux disabling, fail2ban configuration, and StorageBox SSH key management for CI/CD.
- Reorganize and rename setup documentation files for improved structure and clarity.
9.2 KiB
04 - Prod Terraform IaC
Bu asamanin amaci prod Hetzner Cloud Project icinde HA odakli IaaS kaynaklarini Terraform ile olusturmaktir. Bu dokuman prod Terraform ajanina tek basina verilebilir.
Kapsam
Terraform prod ortaminda sunlari olusturur:
- Private network:
iklim-prod-net - Subnetler:
- App/Swarm subnet:
10.20.10.0/24 - DB subnet:
10.20.20.0/24
- App/Swarm subnet:
- Firewall:
- Public ingress: sadece
22/tcp,80/tcp,443/tcp - Private ingress:
01-private-network-port-matrisi.mddosyasindaki prod kurallari
- Public ingress: sadece
- SSH key
- Placement groups:
iklim-prod-app-spreadiklim-prod-db-spread
- Floating IP: app entry point icin sabit IPv4 (
iklim-app-01'e atanir) - Servers:
iklim-app-01iklim-app-02iklim-app-03iklim-db-01iklim-db-02iklim-db-03
- Ansible inventory output
DB cluster yazilimi Terraform ile kurulmayacak. DB node'lari sadece makine, network ve firewall seviyesinde hazirlanacak.
Onerilen Dosya Yapisi
terraform/
hetzner/
prod/
versions.tf
providers.tf
variables.tf
locals.tf
network.tf
firewall.tf
placement.tf
servers.tf
floating_ip.tf
outputs.tf
terraform.tfvars.example
terraform.tfvars, state dosyalari ve token repo'ya commit edilmeyecek.
Degiskenler
environment sabiti locals.tf icindedir; tfvars ile override edilmez.
Minimum degiskenler:
hcloud_token = "secret"
location = "fsn1"
image = "rocky-10"
server_type_swarm = "cpx42"
server_type_db = "cpx32"
admin_ssh_public_key_path = "~/.ssh/id_ed25519.pub"
admin_allowed_cidrs = ["X.X.X.X/32"]
Server type karari ../hetzner-sizing-report.md dokumanindaki mevcut test
ortami metrikleri ve prod cluster topolojisi dikkate alinarak belirlenmistir.
Prod app node'lar icin Java mikroservis bellek baskisi nedeniyle cpx42,
prod DB node'lar icin ise 3 node cluster baslangici nedeniyle ekonomik
cpx32 onerilir. Kapasite ihtiyaci metriklerle dogrulandiginda node ekleme
veya in-place rescale yapilabilir.
Server Rolleri ve Private IP Plani
| Server | Private IP | Rol |
|---|---|---|
iklim-app-01 |
10.20.10.11 |
Swarm manager + app worker + runner (primary, FIP alir) |
iklim-app-02 |
10.20.10.12 |
Swarm manager + app worker + runner |
iklim-app-03 |
10.20.10.13 |
Swarm manager + app worker + runner |
iklim-db-01 |
10.20.20.11 |
Manuel DB cluster node |
iklim-db-02 |
10.20.20.12 |
Manuel DB cluster node |
iklim-db-03 |
10.20.20.13 |
Manuel DB cluster node |
Private IP'ler locals.tf icinde swarm_private_ips ve db_private_ips map'leri olarak sabit tanimlanir. Sunucu listesi for_each ile bu map'lerden turetilir.
Onerilen Kaynaklar ve Maliyet
| Server | Rol | Server Type | CPU | RAM | SSD | Aylik |
|---|---|---|---|---|---|---|
iklim-app-01 |
Swarm manager + app worker + runner | cpx42 |
8 AMD | 16 GB | 320 GB | $29.99 |
iklim-app-02 |
Swarm manager + app worker + runner | cpx42 |
8 AMD | 16 GB | 320 GB | $29.99 |
iklim-app-03 |
Swarm manager + app worker + runner | cpx42 |
8 AMD | 16 GB | 320 GB | $29.99 |
iklim-db-01 |
DB cluster node | cpx32 |
4 AMD | 8 GB | 160 GB | $16.49 |
iklim-db-02 |
DB cluster node | cpx32 |
4 AMD | 8 GB | 160 GB | $16.49 |
iklim-db-03 |
DB cluster node | cpx32 |
4 AMD | 8 GB | 160 GB | $16.49 |
| Toplam | 6 server | 36 vCPU | 72 GB | 1,440 GB | $139.44 |
Placement Group Karari
Prod icin iki ayri spread placement group:
iklim-prod-app-spread: iklim-app-01/02/03
iklim-prod-db-spread: iklim-db-01/02/03
Bu sayede Swarm quorum node'lari kendi aralarinda farkli fiziksel host'lara, DB node'lari da kendi aralarinda farkli fiziksel host'lara yerlestirilmeye calisilir.
Notlar:
- Hetzner kabinet secimi dogrudan sunmaz.
- Spread placement group farkli fiziksel host hedefler.
- Farkli lokasyon/region felaket kurtarma bu asamada konu disidir.
- Ileride scale buyudugunde multi-location DR ayri tasarlanmalidir.
Floating IP
iklim-prod-app-fip adli IPv4 floating IP olusturulur ve iklim-app-01'e atanir. DNS A kaydi bu IP'ye yonlendirilir. Failover gerekirse floating IP baska bir app node'una tasinabilir.
Public Firewall
Public ingress:
| Port | Kaynak | Hedef |
|---|---|---|
22/tcp |
admin_allowed_cidrs |
Tum prod node'lari |
80/tcp |
0.0.0.0/0, ::/0 |
iklim-app-* (Floating IP uzerinden) |
443/tcp |
0.0.0.0/0, ::/0 |
iklim-app-* (Floating IP uzerinden) |
Prod'da su portlar public acilmayacak:
8200/tcpVault5432/tcpPostgreSQL27017/tcpMongoDB6379/tcpRedis5672/tcp,15672/tcp,61613/tcp,15674/tcpRabbitMQ2377/tcp,7946/tcp,7946/udp,4789/udpDocker Swarm9180/tcpAPISIX Admin API9090/tcpPrometheus3000/tcpGrafana
Private Firewall
App (swarm) Firewall — Private Ingress
App subnet kaynakli (10.20.10.0/24):
| Port | Servis | Erisim yontemi |
|---|---|---|
2377/tcp |
Docker Swarm control plane | App subnet icinden |
7946/tcp,udp |
Docker Swarm node discovery | App subnet icinden |
4789/udp |
Docker Swarm VXLAN overlay | App subnet icinden |
8200/tcp |
Vault | Docker overlay / private network |
6379/tcp |
Redis | App subnet icinden |
5672/tcp |
RabbitMQ AMQP | App subnet icinden |
61613/tcp |
RabbitMQ STOMP | App subnet icinden |
15674/tcp |
RabbitMQ Web STOMP | App subnet icinden |
15672/tcp |
RabbitMQ Management | SWAG arkasinda 443 — IP kisitli |
9000/tcp |
APISIX Dashboard | SWAG arkasinda 443 — IP kisitli |
9180/tcp |
APISIX Admin API | Docker overlay icinden sadece Dashboard erisir |
9090/tcp |
Prometheus | SWAG arkasinda 443 — IP kisitli |
3000/tcp |
Grafana | SWAG arkasinda 443 — IP kisitli |
DB subnet kaynakli (iklim-db-* node'lari Swarm'a worker olarak katildigi icin):
| Port | Servis | Kaynak |
|---|---|---|
2377/tcp |
Docker Swarm control plane | 10.20.20.0/24 |
7946/tcp,udp |
Docker Swarm node discovery | 10.20.20.0/24 |
4789/udp |
Docker Swarm VXLAN overlay | 10.20.20.0/24 |
DB Firewall — Private Ingress
App subnet kaynakli (10.20.10.0/24):
| Port | Servis | Not |
|---|---|---|
22/tcp |
SSH | admin_allowed_cidrs |
5432/tcp |
PostgreSQL (Patroni primary) | App subnet erisimi |
27017/tcp |
MongoDB replica set endpoint | App subnet erisimi |
2377/tcp |
Docker Swarm control plane | App subnet icinden |
7946/tcp,udp |
Docker Swarm node discovery | App subnet icinden |
4789/udp |
Docker Swarm VXLAN overlay | App subnet icinden |
DB subnet icindeki karsilikli erisim (10.20.20.0/24):
| Port | Servis | Not |
|---|---|---|
5432/tcp |
PostgreSQL Patroni replication | DB node'lari arasi |
27017/tcp |
MongoDB replica set internal | DB node'lari arasi |
2379/tcp |
etcd client | Patroni → etcd erisimi |
2380/tcp |
etcd peer | etcd cluster internal |
8008/tcp |
Patroni REST API | Patroni leader election ve saglik kontrolu |
IP kisitlamasi Hetzner firewall'da degil, SWAG nginx konfigurasyonunda yapilir.
Lifecycle ve Resize Politikasi
server_type Degisikligi (Yeniden Boyutlandirma)
server_type degistirmek Terraform destroy+create tetiklemez. hcloud provider
bunu natively destekler: sunucuyu durdurur, Hetzner Resize API'sini cagirir,
yeniden baslatir. terraform.tfvars icinde degeri guncelle, terraform apply calistir.
Downtime olur (sunucu durur ve baslar) ancak disk, kurulu yazilim ve Docker volumes
korunur. ignore_changes veya manuel adim gerekmez.
Hangi Degisiklikler Sunucuyu Zorla Yeniden Olusturur?
| Degisen alan | Davranis | Not |
|---|---|---|
server_type |
In-place resize (provider native) | terraform apply yeterli |
hcloud_server_network |
Sadece attachment guncellenir | Ayri resource kullanildigi icin |
hcloud_firewall_attachment |
Sadece attachment guncellenir | Ayri resource kullanildigi icin |
placement_group_id |
Hetzner API degisime izin vermiyor → destroy+create | Degistirme |
image |
Disk imaji degisir → destroy+create | Degistirme |
location |
Baska datacenter'a tasinamaz → destroy+create | Degistirme |
Network ve Firewall Attachment Ayrimi
network blogu ve firewall_ids hcloud_server icine gomulmez. Bunun yerine
ayri resource tanimlanir:
hcloud_server_network— private IP atamasi (for_eachile her node icin)hcloud_firewall_attachment— firewall iliskisi (for_eachile turetilen server listesi)
prevent_destroy Korumasi
Her sunucuya lifecycle { prevent_destroy = true } eklenir. Kasitli silmek icin
once lifecycle blogunu gecici olarak kaldir.
Kabul Kriterleri
terraform plansadece prod Hetzner Project token'i ile calisir.- 6 server olusur (
iklim-app-01/02/03,iklim-db-01/02/03). - Swarm node'lari
iklim-prod-app-spreadplacement group icindedir. - DB node'lari
iklim-prod-db-spreadplacement group icindedir. - Public firewall sadece
22,80,443ingress'e izin verir. - Private firewall
01-private-network-port-matrisi.mdile uyumludur. - DB replication portlari yalnizca DB subnet'ten erisilebilir.
- Floating IP olusur ve
iklim-app-01'e atanir. - Terraform state ve secret tfvars commit edilmez.