- 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.
216 lines
7.9 KiB
Markdown
216 lines
7.9 KiB
Markdown
# 01 - Test Terraform IaC
|
|
|
|
Bu asamanin amaci test Hetzner Cloud Project icinde minimum IaaS kaynaklarini Terraform ile olusturmaktir. Bu dokuman tek basina uygulanabilir olacak sekilde yazilmistir.
|
|
|
|
## Kapsam
|
|
|
|
Terraform test ortaminda sunlari olusturur:
|
|
|
|
- Private network: `iklim-test-net`
|
|
- Subnetler:
|
|
- App/Swarm subnet: `10.10.10.0/24`
|
|
- DB subnet: `10.10.20.0/24`
|
|
- Firewall:
|
|
- Public ingress: sadece `22/tcp`, `80/tcp`, `443/tcp`
|
|
- Private ingress: `01-private-network-port-matrisi.md` dosyasindaki test kurallari
|
|
- SSH key
|
|
- Placement group: `iklim-test-spread`
|
|
- Floating IP: swarm entry point icin sabit IPv4
|
|
- Server:
|
|
- `iklim-app-01`
|
|
- `iklim-db-01`
|
|
- Ansible inventory output
|
|
|
|
Terraform DB yazilimini kurmaz. DB node sadece makine, network ve firewall seviyesinde hazirlanir.
|
|
|
|
## Onerilen Dosya Yapisi
|
|
|
|
```text
|
|
terraform/
|
|
hetzner/
|
|
test/
|
|
versions.tf
|
|
providers.tf
|
|
variables.tf
|
|
locals.tf
|
|
network.tf
|
|
firewall.tf
|
|
placement.tf
|
|
servers.tf
|
|
outputs.tf
|
|
terraform.tfvars.example
|
|
```
|
|
|
|
`terraform.tfvars` commit edilmeyecek. `.gitignore` icinde ignore edilmelidir.
|
|
|
|
## Degiskenler
|
|
|
|
Minimum degiskenler:
|
|
|
|
```hcl
|
|
hcloud_token = "secret"
|
|
location = "fsn1"
|
|
image = "rocky-10"
|
|
server_type_swarm = "cpx42"
|
|
server_type_db = "cpx42"
|
|
admin_ssh_public_key_path = "~/.ssh/id_ed25519.pub"
|
|
admin_allowed_cidrs = ["X.X.X.X/32"]
|
|
```
|
|
|
|
`environment` sabiti `locals.tf` icindedir; `tfvars` ile override edilmez.
|
|
|
|
`location` icin tek lokasyonla baslanir. Farkli region/lokasyon felaket kurtarma bu asamada konu disidir; ileride dokumana eklenmelidir.
|
|
|
|
Server type karari `../hetzner-sizing-report.md` dokumanindaki mevcut test
|
|
ortami metriklerine dayanir. Test app node uzerinde 10 mikroservis ve altyapi
|
|
servisleri birlikte calistigi icin `cpx32` RAM acisindan riskli bulunmustur.
|
|
Test DB node icin de tek node CPU spike riski nedeniyle `cpx42` onerilir.
|
|
|
|
## Server Rolleri
|
|
|
|
| Server | Private IP | Rol |
|
|
| --- | --- | --- |
|
|
| `iklim-app-01` | `10.10.10.11` | Swarm manager + app worker + Gitea runner |
|
|
| `iklim-db-01` | `10.10.20.11` | Manuel DB kurulumu icin hazir DB node |
|
|
|
|
Private IP'ler Terraform icinde sabit tanimlanmalidir. Ansible inventory ve firewall kurallari deterministik kalir.
|
|
|
|
## Onerilen Kaynaklar ve Maliyet
|
|
|
|
| Server | Rol | Server Type | CPU | RAM | SSD | Aylik |
|
|
| --- | --- | --- | ---: | ---: | ---: | ---: |
|
|
| `iklim-app-01` | Swarm manager + app worker + Gitea runner | `cpx42` | 8 AMD | 16 GB | 320 GB | $29.99 |
|
|
| `iklim-db-01` | PostgreSQL/PostGIS + MongoDB node | `cpx42` | 8 AMD | 16 GB | 320 GB | $29.99 |
|
|
| **Toplam** | 2 server | | **16 vCPU** | **32 GB** | **640 GB** | **$59.98** |
|
|
|
|
## Firewall Kurallari
|
|
|
|
Public ingress:
|
|
|
|
| Port | Kaynak | Hedef |
|
|
| --- | --- | --- |
|
|
| `22/tcp` | `admin_allowed_cidrs` | Tum test node'lari |
|
|
| `80/tcp` | `0.0.0.0/0`, `::/0` | `iklim-app-01` |
|
|
| `443/tcp` | `0.0.0.0/0`, `::/0` | `iklim-app-01` |
|
|
|
|
Public ingress icin `8200/tcp`, `5432/tcp`, `27017/tcp`, `5672/tcp`, `15672/tcp`, `6379/tcp`, `2379/tcp`, `9000/tcp`, `9180/tcp`, `9090/tcp`, `3000/tcp` acilmayacak.
|
|
|
|
### App (swarm) Firewall — Private Ingress
|
|
|
|
App subnet kaynakli (iklim-app-01):
|
|
|
|
| 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-01` Swarm'a worker olarak katildigi icin):
|
|
|
|
| Port | Servis | Kaynak |
|
|
| --- | --- | --- |
|
|
| `2377/tcp` | Docker Swarm control plane | `10.10.20.0/24` |
|
|
| `7946/tcp,udp` | Docker Swarm node discovery | `10.10.20.0/24` |
|
|
| `4789/udp` | Docker Swarm VXLAN overlay | `10.10.20.0/24` |
|
|
|
|
### DB Firewall — Private Ingress
|
|
|
|
| Port | Servis | Kaynak |
|
|
| --- | --- | --- |
|
|
| `22/tcp` | SSH | `admin_allowed_cidrs` |
|
|
| `5432/tcp` | PostgreSQL | `10.10.10.0/24` (app subnet) |
|
|
| `27017/tcp` | MongoDB | `10.10.10.0/24` (app subnet) |
|
|
| `2377/tcp` | Docker Swarm control plane | `10.10.10.0/24` (app subnet) |
|
|
| `7946/tcp,udp` | Docker Swarm node discovery | `10.10.10.0/24` (app subnet) |
|
|
| `4789/udp` | Docker Swarm VXLAN overlay | `10.10.10.0/24` (app subnet) |
|
|
|
|
IP kisitlamasi Hetzner firewall'da degil, SWAG nginx konfigurasyonunda yapilir.
|
|
Bu portlarin hicbiri `admin_allowed_cidrs` kaynagiyla public'ten acilmaz.
|
|
|
|
Diger private ingress kurallari icin `01-private-network-port-matrisi.md` kaynak alinacak.
|
|
|
|
## Placement Group
|
|
|
|
`iklim-test-spread` placement group `type = "spread"` olacak. Testte iki server oldugu icin bu grup `iklim-app-01` ve `iklim-db-01` makinelerinin farkli fiziksel host'lara dagitilmasini hedefler.
|
|
|
|
Not: Spread placement group farkli kabinet veya lokasyon garantisi degildir; tek fiziksel host arizasinin etkisini azaltir.
|
|
|
|
## Terraform Cikti Beklentisi
|
|
|
|
`outputs.tf` minimum su bilgileri uretmelidir:
|
|
|
|
```hcl
|
|
output "ansible_inventory_yaml" {
|
|
sensitive = false
|
|
}
|
|
|
|
output "test_private_ips" {
|
|
sensitive = false
|
|
}
|
|
|
|
output "test_public_ips" {
|
|
sensitive = false
|
|
}
|
|
```
|
|
|
|
Inventory output'u daha sonra `ansible/inventory/generated/test.yml` dosyasina yazilabilir. Inventory dosyasinda secret bulunmayacaksa commit edilebilir; secret veya token icerirse commit edilmeyecek.
|
|
|
|
## 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
|
|
- `hcloud_firewall_attachment` — firewall iliskisi
|
|
|
|
Gomulu tanimlamada bazi provider versiyonlari bu alanlardaki degisiklikleri
|
|
sunucu recreation olarak yorumlar. Ayri resource kullanildiginda sadece
|
|
attachment guncellenir, sunucu dokunulmaz.
|
|
|
|
### prevent_destroy Korumasi
|
|
|
|
Her sunucuya `lifecycle { prevent_destroy = true }` eklenir. Bu blok varken
|
|
Terraform hicbir kosulda sunucuyu silemez, plan asamasinda hata verir.
|
|
Kasitli silmek icin once lifecycle blogunu gecici olarak kaldir.
|
|
|
|
## Kabul Kriterleri
|
|
|
|
- `terraform plan` sadece test Hetzner Project token'i ile calisir.
|
|
- `terraform apply` sonrasinda 2 server olusur.
|
|
- Iki server private network uzerinden birbirine erisebilir.
|
|
- Public internetten sadece `22`, `80`, `443` firewall seviyesinde aciktir.
|
|
- Vault `8200` public'ten kapali kalir.
|
|
- Terraform state repo'ya commit edilmez.
|