This commit introduces a reordered and renumbered set of setup documentation files to better reflect the deployment stages for both test and production environments. Key changes include: * A new `setup-vs-roadmap-map.md` file to provide a clear mapping between roadmap tasks and their corresponding setup phases. * Significantly expanded Ansible bootstrap documentation for both test and production, detailing Docker, Swarm, security hardening, and StorageBox SSH key management roles. * Formalized database Docker and Swarm cluster setup instructions for test and production, including explicit steps for Swarm worker integration of DB nodes. * Updated roadmap documentation (`roadmap/prod-env/*`) to align with the refined setup, incorporating correct private IP addresses for Swarm joins, new node labels, and floating IP usage for GoDaddy DNS records.
221 lines
8.0 KiB
Markdown
221 lines
8.0 KiB
Markdown
# 02 - 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
|
|
floating_ip.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_app = "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
|
|
}
|
|
|
|
output "test_floating_ip" {
|
|
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.
|