- This commit introduces the Terraform configuration to provision a production environment on Hetzner Cloud, building on the existing test setup. - Key improvements and new features include: * **Multi-node clusters:** Scaling to 3-node Swarm application and database clusters for improved resilience. * **High availability:** Utilizing a Hetzner Floating IP for the application entry point and `spread` placement groups for fault tolerance across physical hosts. * **Enhanced network security:** Internal management services (RabbitMQ, APISIX, Prometheus, Grafana) are restricted to the application subnet, expected to be accessed via an internal reverse proxy (SWAG). * **Internal database replication:** New firewall rules enable PostgreSQL replication and MongoDB replica set traffic within the database subnet. * **Refined test environment:** Updates to align `test` configuration with the new `prod` structure, including a dedicated floating IP and adjusted firewall rules. * **Configuration standardization:** Environment-specific details moved to `locals.tf` for clarity, with upgraded server types and migration to Rocky Linux as the base image. - Updates were also made to the latest version of Terraform to ensure consistency in the documentation
7.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:
07-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 = "cx42"
server_type_db = "cx52"
admin_ssh_public_key_path = "~/.ssh/id_ed25519.pub"
admin_allowed_cidrs = ["X.X.X.X/32"]
Server type degerleri kapasiteye gore degisebilir. Bu dokuman topoloji ve guvenlik kararini tanimlar; sizing daha sonra revize edilebilir.
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.
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
Private ingress (app subnet 10.20.10.0/24 kaynakli):
| Port | Servis | Erisim yontemi |
|---|---|---|
15672/tcp |
RabbitMQ Management | SWAG arkasinda 443 — IP kisitli |
9090/tcp |
Prometheus | SWAG arkasinda 443 — IP kisitli |
3000/tcp |
Grafana | 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 |
8200/tcp |
Vault | Docker overlay / private network |
2377/tcp |
Docker Swarm control plane | App subnet icinden |
7946/tcp, 7946/udp |
Docker Swarm node discovery | App subnet icinden |
4789/udp |
Docker Swarm VXLAN overlay | App subnet icinden |
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 |
DB firewall ek kurallar (db subnet 10.20.20.0/24 kaynakli):
| Port | Servis | Kural |
|---|---|---|
5432/tcp |
PostgreSQL replication | DB subnet icinden |
27017/tcp |
MongoDB replica set | DB subnet icinden |
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
07-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.