- 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
6.8 KiB
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
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:
curlwgetgitjqunzipca-certificatesfail2banchronypython3python3-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 noMaxAuthTries 3fail2banSSH jail aktif edilir.dnf-automaticile otomatik guvenlik guncellestirmeleri aktif edilir.firewallddefault:- 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-cedocker-ce-clicontainerd.iodocker-buildx-plugindocker-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=servicelabel'i ile isaretlenir:docker node update --label-add type=service iklim-app-01 - Node
AVAILABILITY=Activekalir (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:
/opt/iklimco
/opt/iklimco/ssl
/opt/iklimco/init
/opt/iklimco/init/postgresql
/opt/iklimco/init/mongodb
DB node uzerinde manuel DB kurulumu icin minimum:
/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:
storagebox_account: "u469968"
group_vars/test.yml — test ortamina ozgu; user ve url account'tan turetilir:
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:
# Sifreleme
ansible-vault encrypt group_vars/test-vault.yml
# Duzenleme
ansible-vault edit group_vars/test-vault.yml
test-vault.yml icerigi:
vault_storagebox_password: "SUB_ACCOUNT_PAROLASI"
Adimlar
-
davfs2 kurulumu
- name: Install davfs2 ansible.builtin.dnf: name: davfs2 state: present -
Kimlik bilgileri dosyasi (
/etc/davfs2/secrets)- 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 -
Mount point olustur
- name: Create mount point ansible.builtin.file: path: "{{ storagebox_mount_point }}" state: directory mode: "0755" -
fstab kaydı
- 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 -
Mount et
- 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:
- name: Write mount marker ansible.builtin.copy: content: "mounted by ansible" dest: "{{ storagebox_mount_point }}/.mounted_marker"
Notlar
davfs2paketi EPEL repository'sinde bulunur; base role'dednf install epel-releaseyapilmalidir.- StorageBox sifreleri asla plaintext olarak repository'e eklenmez; Ansible Vault zorunludur.
- Mount noktasi reboot'ta
_netdevflag'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 pingbasarili olur.iklim-app-01uzerindedocker infocalisir.iklim-app-01uzerinde Swarm active olur; nodeAVAILABILITY=Active(drain degil).docker network lsicindeiklimco-netgorulur.docker node inspect iklim-app-01 --format '{{.Spec.Labels}}'ciktisimap[type:service]icerir.iklim-db-01uzerinde public DB portu acik degildir.- Public portlar Hetzner firewall + firewalld seviyesinde
22,80,443ile sinirlidir. - Her iki node'da
mount | grep storageboxStorageBox mount'unu gosterir. ls /mnt/storagebox/.mounted_markerbasarili olur.- Reboot sonrasi mount otomatik olarak geri gelir.