- 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
263 lines
6.8 KiB
Markdown
263 lines
6.8 KiB
Markdown
# 02 - Test Ansible Bootstrap
|
||
|
||
Bu asamanin amaci Terraform ile olusturulan test makinelerini Linux, hardening, Docker ve Swarm acisindan hazir hale getirmektir. DB yazilimi kurulumu bu asamanin disindadir.
|
||
|
||
## Hedef Makineler
|
||
|
||
| Host | Rol |
|
||
| --- | --- |
|
||
| `iklim-app-01` | Swarm manager + app worker |
|
||
| `iklim-db-01` | Manuel DB kurulumu icin OS-hardening uygulanmis DB node |
|
||
|
||
## Onerilen Dosya Yapisi
|
||
|
||
```text
|
||
ansible/
|
||
ansible.cfg
|
||
inventory/
|
||
generated/
|
||
test.yml
|
||
group_vars/
|
||
all.yml
|
||
test.yml
|
||
playbooks/
|
||
test-bootstrap.yml
|
||
roles/
|
||
base/
|
||
hardening/
|
||
docker/
|
||
swarm/
|
||
node_dirs/
|
||
storagebox/
|
||
```
|
||
|
||
## Base Role
|
||
|
||
Tum test node'larina uygulanir:
|
||
|
||
- `dnf update`
|
||
- temel paketler:
|
||
- `curl`
|
||
- `wget`
|
||
- `git`
|
||
- `jq`
|
||
- `unzip`
|
||
- `ca-certificates`
|
||
- `fail2ban`
|
||
- `chrony`
|
||
- `python3`
|
||
- `python3-pip`
|
||
- timezone: `Europe/Istanbul`
|
||
- hostname ayari
|
||
- sistem reboot gerekiyorsa kontrollu reboot
|
||
|
||
## Security Hardening Role
|
||
|
||
Tum test node'larina uygulanir:
|
||
|
||
- SSH password login kapatilir.
|
||
- Root SSH login kapatilir.
|
||
- Sadece SSH key ile login kalir.
|
||
- `PermitEmptyPasswords no`
|
||
- `MaxAuthTries 3`
|
||
- `fail2ban` SSH jail aktif edilir.
|
||
- `dnf-automatic` ile otomatik guvenlik guncellestirmeleri aktif edilir.
|
||
- `firewalld` default:
|
||
- incoming: deny (drop zone)
|
||
- outgoing: allow
|
||
- Public SSH sadece admin CIDR'dan acilir.
|
||
|
||
Not: Docker iptables kurallari firewalld ile etkilesebilir. Hetzner Cloud firewall asil dis perimeter kabul edilir; firewalld host icinde ikinci katman olarak kullanilir.
|
||
|
||
## Docker Role
|
||
|
||
Sadece `iklim-app-01` uzerinde zorunludur. `iklim-db-01` uzerinde DB manual kurulum stratejisine gore opsiyonel tutulabilir.
|
||
|
||
Docker kurulumu resmi Docker dnf repository uzerinden yapilir:
|
||
|
||
- Docker GPG key + dnf repository (`https://download.docker.com/linux/rhel/docker-ce.repo`)
|
||
- paketler:
|
||
- `docker-ce`
|
||
- `docker-ce-cli`
|
||
- `containerd.io`
|
||
- `docker-buildx-plugin`
|
||
- `docker-compose-plugin`
|
||
- Docker servisi enabled + started
|
||
|
||
Docker convenience script kullanilmayacak. Production benzeri test ortami icin paket repository yolu tercih edilir.
|
||
|
||
## Swarm Role
|
||
|
||
`iklim-app-01` uzerinde:
|
||
|
||
- `docker swarm init`
|
||
- advertise addr: `10.10.10.11`
|
||
- data path addr: `10.10.10.11`
|
||
- overlay network:
|
||
- `iklimco-net`
|
||
- driver: `overlay`
|
||
- attachable: `true`
|
||
- Node `type=service` label'i ile isaretlenir:
|
||
```bash
|
||
docker node update --label-add type=service iklim-app-01
|
||
```
|
||
- Node `AVAILABILITY=Active` kalir (drain edilmez); tek node hem manager hem worker'dir.
|
||
|
||
Test tek node Swarm oldugu icin join token kullanimi yoktur.
|
||
|
||
## Node Directory Role
|
||
|
||
`iklim-app-01` uzerinde deploy on kosullari:
|
||
|
||
```text
|
||
/opt/iklimco
|
||
/opt/iklimco/ssl
|
||
/opt/iklimco/init
|
||
/opt/iklimco/init/postgresql
|
||
/opt/iklimco/init/mongodb
|
||
```
|
||
|
||
DB node uzerinde manuel DB kurulumu icin minimum:
|
||
|
||
```text
|
||
/opt/iklimco
|
||
/opt/iklimco/db
|
||
/opt/iklimco/backup
|
||
```
|
||
|
||
## StorageBox DAVFS Mount Role
|
||
|
||
Her iki node'a uygulanir (`iklim-app-01` ve `iklim-db-01`).
|
||
|
||
### Amac
|
||
|
||
Hetzner StorageBox'u WebDAV (DAVFS) protokolü üzerinden `/mnt/storagebox` olarak mount eder. Docker volume'lari bu dizine baglanarak veri kaliciligini ve yedeklemeyi saglar.
|
||
|
||
### Test Ortami Sub-Account
|
||
|
||
| Parametre | Degisken | Deger |
|
||
| --- | --- | --- |
|
||
| Ana hesap | `storagebox_account` | `u469968` |
|
||
| Sub-account | `storagebox_user` | `u469968-sub1` |
|
||
| WebDAV URL | `storagebox_url` | `https://u469968-sub1.your-storagebox.de/` |
|
||
| Mount point | `storagebox_mount_point` | `/mnt/storagebox` |
|
||
|
||
### Role Degiskenleri
|
||
|
||
`group_vars/all.yml` — tum ortamlar icin ortak:
|
||
|
||
```yaml
|
||
storagebox_account: "u469968"
|
||
```
|
||
|
||
`group_vars/test.yml` — test ortamina ozgu; user ve url account'tan turetilir:
|
||
|
||
```yaml
|
||
storagebox_user: "{{ storagebox_account }}-sub1"
|
||
storagebox_url: "https://{{ storagebox_user }}.your-storagebox.de/"
|
||
storagebox_password: "{{ vault_storagebox_password }}" # Ansible Vault ile saklanir
|
||
storagebox_mount_point: "/mnt/storagebox"
|
||
```
|
||
|
||
Prod ortaminda yalnizca suffix degisir (`sub1` → `sub2`), geri kalan her sey turetilir.
|
||
|
||
`vault_storagebox_password` degeri Ansible Vault ile sifreli `group_vars/test-vault.yml` icinde tutulur:
|
||
|
||
```bash
|
||
# Sifreleme
|
||
ansible-vault encrypt group_vars/test-vault.yml
|
||
|
||
# Duzenleme
|
||
ansible-vault edit group_vars/test-vault.yml
|
||
```
|
||
|
||
`test-vault.yml` icerigi:
|
||
|
||
```yaml
|
||
vault_storagebox_password: "SUB_ACCOUNT_PAROLASI"
|
||
```
|
||
|
||
### Adimlar
|
||
|
||
1. **davfs2 kurulumu**
|
||
|
||
```yaml
|
||
- name: Install davfs2
|
||
ansible.builtin.dnf:
|
||
name: davfs2
|
||
state: present
|
||
```
|
||
|
||
2. **Kimlik bilgileri dosyasi** (`/etc/davfs2/secrets`)
|
||
|
||
```yaml
|
||
- name: Configure davfs2 secrets
|
||
ansible.builtin.lineinfile:
|
||
path: /etc/davfs2/secrets
|
||
line: "{{ storagebox_url }} {{ storagebox_user }} {{ storagebox_password }}"
|
||
create: yes
|
||
mode: "0600"
|
||
owner: root
|
||
group: root
|
||
```
|
||
|
||
3. **Mount point olustur**
|
||
|
||
```yaml
|
||
- name: Create mount point
|
||
ansible.builtin.file:
|
||
path: "{{ storagebox_mount_point }}"
|
||
state: directory
|
||
mode: "0755"
|
||
```
|
||
|
||
4. **fstab kaydı**
|
||
|
||
```yaml
|
||
- name: Add fstab entry
|
||
ansible.builtin.lineinfile:
|
||
path: /etc/fstab
|
||
line: >-
|
||
{{ storagebox_url }} {{ storagebox_mount_point }} davfs
|
||
_netdev,auto,user,rw,uid=root,gid=root 0 0
|
||
state: present
|
||
```
|
||
|
||
5. **Mount et**
|
||
|
||
```yaml
|
||
- name: Mount StorageBox
|
||
ansible.builtin.command: mount {{ storagebox_mount_point }}
|
||
args:
|
||
creates: "{{ storagebox_mount_point }}/.mounted_marker"
|
||
```
|
||
|
||
Mount basarisi icin dizine bir marker dosyasi yazilabilir:
|
||
|
||
```yaml
|
||
- name: Write mount marker
|
||
ansible.builtin.copy:
|
||
content: "mounted by ansible"
|
||
dest: "{{ storagebox_mount_point }}/.mounted_marker"
|
||
```
|
||
|
||
### Notlar
|
||
|
||
- `davfs2` paketi EPEL repository'sinde bulunur; base role'de `dnf install epel-release` yapilmalidir.
|
||
- StorageBox sifreleri asla plaintext olarak repository'e eklenmez; Ansible Vault zorunludur.
|
||
- Mount noktasi reboot'ta `_netdev` flag'i sayesinde network hazir olduktan sonra otomatik mount edilir.
|
||
- Docker volume'lari bu dizin altindaki bir alt klasore yonlendirilir, ornegin `/mnt/storagebox/volumes/`.
|
||
|
||
## Kabul Kriterleri
|
||
|
||
- `ansible -i inventory/generated/test.yml all -m ping` basarili olur.
|
||
- `iklim-app-01` uzerinde `docker info` calisir.
|
||
- `iklim-app-01` uzerinde Swarm active olur; node `AVAILABILITY=Active` (drain degil).
|
||
- `docker network ls` icinde `iklimco-net` gorulur.
|
||
- `docker node inspect iklim-app-01 --format '{{.Spec.Labels}}'` ciktisi `map[type:service]` icerir.
|
||
- `iklim-db-01` uzerinde public DB portu acik degildir.
|
||
- Public portlar Hetzner firewall + firewalld seviyesinde `22`, `80`, `443` ile sinirlidir.
|
||
- Her iki node'da `mount | grep storagebox` StorageBox mount'unu gosterir.
|
||
- `ls /mnt/storagebox/.mounted_marker` basarili olur.
|
||
- Reboot sonrasi mount otomatik olarak geri gelir.
|