Restructure setup documentation and refine environment bootstrapping
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.
This commit is contained in:
parent
42dfe76487
commit
bf8f011e43
@ -46,7 +46,7 @@ Save this token — needed on iklim-app-02 and iklim-app-03.
|
||||
|
||||
SSH into iklim-app-02 and iklim-app-03, run:
|
||||
```bash
|
||||
docker swarm join --token <MANAGER_TOKEN> 10.10.10.11:2377
|
||||
docker swarm join --token <MANAGER_TOKEN> 10.20.10.11:2377
|
||||
```
|
||||
|
||||
## Step 4 — Label app nodes
|
||||
@ -70,7 +70,7 @@ docker swarm join-token worker
|
||||
SSH into each DB node and join:
|
||||
|
||||
```bash
|
||||
docker swarm join --token <WORKER_TOKEN> 10.10.10.11:2377
|
||||
docker swarm join --token <WORKER_TOKEN> 10.20.10.11:2377
|
||||
```
|
||||
|
||||
Then label them on iklim-app-01:
|
||||
@ -98,7 +98,7 @@ docker node inspect iklim-app-01 --format '{{.Spec.Labels}}'
|
||||
docker node inspect iklim-db-01 --format '{{.Spec.Labels}}'
|
||||
```
|
||||
|
||||
Expected: `map[role:service]` for app nodes, `map[role:db]` for DB nodes.
|
||||
Expected: `map[type:service]` for app nodes, `map[role:db]` for DB nodes.
|
||||
|
||||
## Step 7 — Confirm `init/swarm-init.sh` multi-node awareness
|
||||
|
||||
|
||||
@ -42,20 +42,18 @@ chmod 600 /opt/iklimco/swag/dns-conf/godaddy.ini
|
||||
|
||||
## Step 4 — GoDaddy A records for prod subdomains
|
||||
|
||||
In GoDaddy DNS panel for `iklim.co`, add/update A records pointing to iklim-app-01's public IP:
|
||||
In GoDaddy DNS panel for `iklim.co`, add/update A records pointing to the **Floating IP** (`iklim-prod-app-fip`).
|
||||
Floating IP değerini almak için: `terraform output prod_floating_ip`
|
||||
|
||||
| Record | Value |
|
||||
|--------|-------|
|
||||
| `api` | `<iklim-app-01-public-ip>` |
|
||||
| `apigw` | `<iklim-app-01-public-ip>` |
|
||||
| `rabbitmq` | `<iklim-app-01-public-ip>` |
|
||||
| `grafana` | `<iklim-app-01-public-ip>` |
|
||||
| `api` | `<iklim-prod-app-fip>` |
|
||||
| `apigw` | `<iklim-prod-app-fip>` |
|
||||
| `rabbitmq` | `<iklim-prod-app-fip>` |
|
||||
| `grafana` | `<iklim-prod-app-fip>` |
|
||||
|
||||
> Swarm's routing mesh means any node IP would work, but iklim-app-01 is the designated
|
||||
> entry point (runs SWAG). Using a single IP keeps DNS simple.
|
||||
>
|
||||
> For HA: add a load balancer or use Hetzner's floating IP in front of the 3 service nodes.
|
||||
> DNS then points to the floating IP. This is a future improvement.
|
||||
> Floating IP `iklim-app-01`'e atanmıştır (`06-prod-terraform-iaac.md` — `floating_ip.tf`).
|
||||
> Failover gerekirse Floating IP başka bir app node'una taşınabilir; DNS değişmez.
|
||||
|
||||
## Notes
|
||||
- Test and prod SWAG instances both obtain `*.iklim.co` independently from Let's Encrypt.
|
||||
|
||||
@ -93,11 +93,13 @@ docker service ps iklim-patroni_patroni-02
|
||||
docker service ps iklim-patroni_patroni-03
|
||||
|
||||
# etcd cluster (for Patroni)
|
||||
docker stack services iklim-db-etcd
|
||||
docker stack services iklim-etcd
|
||||
|
||||
# MongoDB replica set
|
||||
docker stack services iklim-db
|
||||
docker service ps iklim-db_mongodb
|
||||
docker service ps iklim-db_mongodb-01
|
||||
docker service ps iklim-db_mongodb-02
|
||||
docker service ps iklim-db_mongodb-03
|
||||
```
|
||||
|
||||
All tasks should show node names matching `iklim-db-01`, `iklim-db-02`, or `iklim-db-03` with placement constraint `role=db`.
|
||||
|
||||
@ -5,55 +5,61 @@ Terraform/Ansible setup aşamalarından hangisinde ele alındığını gösterir
|
||||
|
||||
## TEST ortamı
|
||||
|
||||
| Roadmap adımı | Hangi aşamada ele alınmalı |
|
||||
| ---------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------- |
|
||||
| Hetzner firewall (sadece 22/80/443) | **Terraform `01-test-terraform-iaac.md`** — `firewall.tf` |
|
||||
| Sunucu oluşturma (`iklim-app-01`, `iklim-db-01`) | **Terraform `01-test-terraform-iaac.md`** — `servers.tf` |
|
||||
| Private network + placement group (`iklim-test-spread`) | **Terraform `01-test-terraform-iaac.md`** — `network.tf`, `placement.tf` |
|
||||
| Floating IP (`iklim-test-app-fip`) | **Terraform `01-test-terraform-iaac.md`** — `floating_ip.tf` |
|
||||
| Docker Engine kurulumu | **Ansible `02-test-ansible-bootstrap.md`** — `docker` role |
|
||||
| Security hardening (SSH, firewalld, fail2ban) | **Ansible `02-test-ansible-bootstrap.md`** — `hardening` role |
|
||||
| Docker Swarm init (`init/swarm-init.sh`) | **Ansible `02-test-ansible-bootstrap.md`** — `swarm` role (pipeline script idempotent çalışmaya devam eder) |
|
||||
| `type=service` node label | **Ansible `02-test-ansible-bootstrap.md`** — `swarm` role |
|
||||
| `/opt/iklimco/...` dizinleri | **Ansible `02-test-ansible-bootstrap.md`** — `node_dirs` role |
|
||||
| StorageBox DAVFS mount (`u469968-sub1`) | **Ansible `02-test-ansible-bootstrap.md`** — `storagebox` role |
|
||||
| `act_runner` systemd kurulumu | **Ansible `03-test-runner-ve-deploy-onkosullari.md`** — `gitea_runner` role |
|
||||
| GoDaddy credentials storagebox'a yükleme | **Manuel kalır** — secret yönetimi, Terraform/Ansible dışı |
|
||||
| Roadmap adımı | Hangi aşamada ele alınmalı |
|
||||
| --- | --- |
|
||||
| Hetzner firewall (sadece 22/80/443) | **Terraform `02-test-terraform-iaac.md`** — `firewall.tf` |
|
||||
| Sunucu oluşturma (`iklim-app-01`, `iklim-db-01`) | **Terraform `02-test-terraform-iaac.md`** — `servers.tf` |
|
||||
| Private network + placement group (`iklim-test-spread`) | **Terraform `02-test-terraform-iaac.md`** — `network.tf`, `placement.tf` |
|
||||
| Floating IP (`iklim-test-app-fip`) | **Terraform `02-test-terraform-iaac.md`** — `floating_ip.tf` |
|
||||
| Docker Engine kurulumu (app + db node) | **Ansible `03-test-ansible-bootstrap.md`** — `docker` role |
|
||||
| Security hardening (SSH, firewalld, fail2ban) | **Ansible `03-test-ansible-bootstrap.md`** — `hardening` role |
|
||||
| Docker Swarm init + `iklim-db-01` worker join | **Ansible `03-test-ansible-bootstrap.md`** — `swarm` role |
|
||||
| `type=service` ve `role=db` node label'ları | **Ansible `03-test-ansible-bootstrap.md`** — `swarm` role |
|
||||
| `/opt/iklimco/...` dizinleri | **Ansible `03-test-ansible-bootstrap.md`** — `node_dirs` role |
|
||||
| StorageBox DAVFS mount (`u469968-sub4`) | **Ansible `03-test-ansible-bootstrap.md`** — `storagebox` role |
|
||||
| DB stack deploy (PostgreSQL + MongoDB on `iklim-db-01`) | **Manuel `04-test-db-docker-kurulum.md`** |
|
||||
| `act_runner` systemd kurulumu | **Ansible `05-test-runner-ve-deploy-onkosullari.md`** — `gitea_runner` role |
|
||||
| GoDaddy credentials storagebox'a yükleme | **Manuel kalır** — secret yönetimi, Terraform/Ansible dışı |
|
||||
|
||||
## PROD ortamı
|
||||
|
||||
| Roadmap adımı | Hangi aşamada ele alınmalı |
|
||||
| -------------------------------------------------------------------- | ------------------------------------------------------------------------ |
|
||||
| 6 sunucu oluşturma (`iklim-app-01/02/03`, `iklim-db-01/02/03`) | **Terraform `04-prod-terraform-iaac.md`** — `servers.tf` |
|
||||
| Private network + 2 placement group | **Terraform `04-prod-terraform-iaac.md`** — `network.tf`, `placement.tf` |
|
||||
| Firewall (sadece 22/80/443 public) | **Terraform `04-prod-terraform-iaac.md`** — `firewall.tf` |
|
||||
| Floating IP (`iklim-prod-app-fip`, `iklim-app-01`'e atanır) | **Terraform `04-prod-terraform-iaac.md`** — `floating_ip.tf` |
|
||||
| Docker Engine kurulumu (`iklim-app-*`) | **Ansible `05-prod-ansible-bootstrap.md`** — `docker` role |
|
||||
| Security hardening (tüm node'lar) | **Ansible `05-prod-ansible-bootstrap.md`** — `hardening` role |
|
||||
| Swarm init (`iklim-app-01`) | **Ansible `05-prod-ansible-bootstrap.md`** — `swarm` role |
|
||||
| Manager join (`iklim-app-02`, `iklim-app-03`) | **Ansible `05-prod-ansible-bootstrap.md`** — `swarm` role |
|
||||
| `type=service` node label (3 swarm node) | **Ansible `05-prod-ansible-bootstrap.md`** — `swarm` role |
|
||||
| `/opt/iklimco/...` dizinleri | **Ansible `05-prod-ansible-bootstrap.md`** — `node_dirs` role |
|
||||
| StorageBox DAVFS mount (`u469968-sub2`) | **Ansible `05-prod-ansible-bootstrap.md`** — `storagebox` role |
|
||||
| 3× `act_runner` systemd (HA runner) | **Ansible `06-prod-runner-ha-ve-swarm.md`** — `gitea_runner` role |
|
||||
| GoDaddy credentials storagebox'a yükleme | **Manuel kalır** — secret yönetimi, Terraform/Ansible dışı |
|
||||
| DB node'ları Swarm'a join | **Kapsam dışı** — DB cluster ayrı yönetilir |
|
||||
| Roadmap adımı | Hangi aşamada ele alınmalı |
|
||||
| --- | --- |
|
||||
| 6 sunucu oluşturma (`iklim-app-01/02/03`, `iklim-db-01/02/03`) | **Terraform `06-prod-terraform-iaac.md`** — `servers.tf` |
|
||||
| Private network + 2 placement group | **Terraform `06-prod-terraform-iaac.md`** — `network.tf`, `placement.tf` |
|
||||
| Firewall (sadece 22/80/443 public; private port matrisi) | **Terraform `06-prod-terraform-iaac.md`** — `firewall.tf` |
|
||||
| Floating IP (`iklim-prod-app-fip`, `iklim-app-01`'e atanır) | **Terraform `06-prod-terraform-iaac.md`** — `floating_ip.tf` |
|
||||
| Docker Engine kurulumu (tüm node'lar — app ve db) | **Ansible `07-prod-ansible-bootstrap.md`** — `docker` role |
|
||||
| Security hardening (tüm node'lar) | **Ansible `07-prod-ansible-bootstrap.md`** — `hardening` role |
|
||||
| Swarm init (`iklim-app-01`) + manager join (`iklim-app-02/03`) | **Ansible `07-prod-ansible-bootstrap.md`** — `swarm` role |
|
||||
| `type=service` node label (3 app node) | **Ansible `07-prod-ansible-bootstrap.md`** — `swarm` role |
|
||||
| `/opt/iklimco/...` dizinleri + `/opt/iklimco/stacks` | **Ansible `07-prod-ansible-bootstrap.md`** — `node_dirs` role |
|
||||
| StorageBox DAVFS mount (`u469968-sub5`) | **Ansible `07-prod-ansible-bootstrap.md`** — `storagebox` role |
|
||||
| DB node'larını Swarm'a worker olarak join et | **Manuel `08-prod-db-cluster-kurulum.md`** — Bölüm 2 |
|
||||
| `role=db` node label (3 db node) | **Manuel `08-prod-db-cluster-kurulum.md`** — Bölüm 2 |
|
||||
| etcd cluster deploy (Patroni için) | **Manuel `08-prod-db-cluster-kurulum.md`** — Bölüm 5.2 |
|
||||
| MongoDB replica set deploy | **Manuel `08-prod-db-cluster-kurulum.md`** — Bölüm 4 |
|
||||
| Patroni + PostgreSQL HA deploy | **Manuel `08-prod-db-cluster-kurulum.md`** — Bölüm 5.4 |
|
||||
| 3× `act_runner` systemd (HA runner) | **Ansible `09-prod-runner-ha-ve-swarm.md`** — `gitea_runner` role |
|
||||
| GoDaddy credentials storagebox'a yükleme | **Manuel kalır** — secret yönetimi, Terraform/Ansible dışı |
|
||||
|
||||
## Klasör yapısı
|
||||
|
||||
```
|
||||
Environment_Infrastructure/
|
||||
setup/ ← Terraform + Ansible aşama dokümanları
|
||||
setup/ ← Terraform + Ansible aşama dokümanları
|
||||
00-genel-yol-haritasi.md
|
||||
01-test-terraform-iaac.md
|
||||
02-test-ansible-bootstrap.md
|
||||
03-test-runner-ve-deploy-onkosullari.md
|
||||
04-prod-terraform-iaac.md
|
||||
05-prod-ansible-bootstrap.md
|
||||
06-prod-runner-ha-ve-swarm.md
|
||||
07-private-network-port-matrisi.md
|
||||
01-private-network-port-matrisi.md
|
||||
02-test-terraform-iaac.md
|
||||
03-test-ansible-bootstrap.md
|
||||
04-test-db-docker-kurulum.md
|
||||
05-test-runner-ve-deploy-onkosullari.md
|
||||
06-prod-terraform-iaac.md
|
||||
07-prod-ansible-bootstrap.md
|
||||
08-prod-db-cluster-kurulum.md
|
||||
09-prod-runner-ha-ve-swarm.md
|
||||
roadmap/
|
||||
test-env/ ← Test ortamı Roadmap adımları
|
||||
prod-env/ ← Prod Roadmap adımları
|
||||
setup-vs-roadmap-map.md ← Bu dosya
|
||||
test-env/ ← Test ortamı Roadmap adımları
|
||||
prod-env/ ← Prod Roadmap adımları
|
||||
setup-vs-roadmap-map.md ← Bu dosya
|
||||
```
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
# 01 - Test Terraform IaC
|
||||
# 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.
|
||||
|
||||
@ -37,6 +37,7 @@ terraform/
|
||||
firewall.tf
|
||||
placement.tf
|
||||
servers.tf
|
||||
floating_ip.tf
|
||||
outputs.tf
|
||||
terraform.tfvars.example
|
||||
```
|
||||
@ -51,7 +52,7 @@ Minimum degiskenler:
|
||||
hcloud_token = "secret"
|
||||
location = "fsn1"
|
||||
image = "rocky-10"
|
||||
server_type_swarm = "cpx42"
|
||||
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"]
|
||||
@ -161,6 +162,10 @@ output "test_private_ips" {
|
||||
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.
|
||||
|
||||
@ -1,26 +1,99 @@
|
||||
# 02 - Test Ansible Bootstrap
|
||||
# 03 - 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.
|
||||
Bu aşamanın amacı Terraform ile oluşturulan test makinelerini Linux, hardening, Docker ve Swarm açısından hazır hale getirmektir. DB yazılımı kurulumu bu aşamanın dışındadır.
|
||||
|
||||
## Ansible Kurulumu
|
||||
|
||||
Ansible, kontrol makinesinde (kendi bilgisayarınızda) yüklü olmalıdır. Hedef sunuculara herhangi bir ajan kurulmaz, sadece SSH erişimi yeterlidir.
|
||||
|
||||
### İşletim Sistemine Göre Kurulum
|
||||
|
||||
- **Ubuntu / Debian:**
|
||||
```bash
|
||||
sudo apt update
|
||||
sudo apt install -y pipx python3-venv
|
||||
|
||||
pipx ensurepath
|
||||
export PATH="$HOME/.local/bin:$PATH"
|
||||
|
||||
pipx install --include-deps ansible
|
||||
```
|
||||
> Not: `sudo apt install ansible` komutu bazı Ubuntu/Debian sürümlerinde eski Ansible paketlerini kurabilir. Bu nedenle güncel Ansible kullanımı için `pipx` yöntemi tercih edilmelidir.
|
||||
|
||||
- **Fedora / Rocky Linux / RHEL:**
|
||||
```bash
|
||||
sudo dnf install -y pipx python3-virtualenv
|
||||
|
||||
pipx ensurepath
|
||||
export PATH="$HOME/.local/bin:$PATH"
|
||||
|
||||
pipx install --include-deps ansible
|
||||
```
|
||||
|
||||
- **macOS (Homebrew):**
|
||||
```bash
|
||||
brew install ansible
|
||||
```
|
||||
|
||||
- **Python Pip ile (Her platformda):**
|
||||
```bash
|
||||
pipx install --include-deps ansible
|
||||
```
|
||||
|
||||
### Kurulumun Doğrulanması
|
||||
|
||||
Hangi yöntemle kurarsanız kurun, kurulumun başarılı olduğunu doğrulamak için aşağıdaki komutları kullanın:
|
||||
|
||||
```bash
|
||||
# Ansible versiyonunu ve yapılandırma yollarını kontrol edin
|
||||
ansible --version
|
||||
|
||||
# Ansible binary’sinin hangi konumdan çalıştığını kontrol edin
|
||||
which -a ansible
|
||||
```
|
||||
|
||||
## Ansible Komutlarını Çalıştırma
|
||||
|
||||
Tüm komutlar projenin `ansible/` dizini altından çalıştırılmalıdır.
|
||||
|
||||
### 1. Bağlantı Testi (Ping)
|
||||
Sunuculara erişimi doğrulamak için:
|
||||
```bash
|
||||
ansible -i inventory/generated/test.yml all -m ping
|
||||
```
|
||||
|
||||
### 2. Bootstrap Playbook'unu Çalıştırma
|
||||
Tüm rolleri (base, hardening, docker, swarm vb.) uygulamak için:
|
||||
```bash
|
||||
ansible-playbook -i inventory/generated/test.yml playbooks/test-bootstrap.yml --ask-vault-pass
|
||||
```
|
||||
*Not: `--ask-vault-pass` parametresi, hassas verilerin (StorageBox şifresi vb.) çözülmesi için gereken Ansible Vault parolasını soracaktır.*
|
||||
|
||||
### 3. Sadece Belirli Bir Rolü Çalıştırma (Tags)
|
||||
Sadece belirli bir kısmı güncellemek isterseniz (örneğin sadece hardening):
|
||||
```bash
|
||||
ansible-playbook -i inventory/generated/test.yml playbooks/test-bootstrap.yml --tags "hardening" --ask-vault-pass
|
||||
```
|
||||
|
||||
## Hedef Makineler
|
||||
|
||||
| Host | Rol |
|
||||
| --- | --- |
|
||||
| `iklim-app-01` | Swarm manager + app worker |
|
||||
| `iklim-db-01` | Manuel DB kurulumu icin OS-hardening uygulanmis DB node |
|
||||
| `iklim-db-01` | Manuel DB kurulumu için OS-hardening uygulanmış DB node |
|
||||
|
||||
## Onerilen Dosya Yapisi
|
||||
## Önerilen Dosya Yapısı
|
||||
|
||||
```text
|
||||
ansible/
|
||||
ansible.cfg
|
||||
inventory/
|
||||
generated/
|
||||
test/
|
||||
ansible.cfg
|
||||
inventory/
|
||||
generated/
|
||||
test.yml
|
||||
group_vars/
|
||||
all.yml
|
||||
test.yml
|
||||
group_vars/
|
||||
all.yml
|
||||
test.yml
|
||||
playbooks/
|
||||
test-bootstrap.yml
|
||||
roles/
|
||||
base/
|
||||
@ -29,15 +102,16 @@ ansible/
|
||||
swarm/
|
||||
node_dirs/
|
||||
storagebox/
|
||||
storagebox_ssh_key/
|
||||
```
|
||||
|
||||
## Base Role
|
||||
|
||||
Tum test node'larina uygulanir:
|
||||
Tüm test node'larına uygulanır:
|
||||
|
||||
- `dnf update`
|
||||
- temel paketler (sirasıyla kurulur):
|
||||
- `epel-release` — fail2ban ve davfs2 bu repo'dan gelir; once kurulur
|
||||
- temel paketler (sırasıyla kurulur):
|
||||
- `epel-release` — fail2ban ve davfs2 bu repo'dan gelir; önce kurulur
|
||||
- `curl`
|
||||
- `wget`
|
||||
- `git`
|
||||
@ -45,46 +119,48 @@ Tum test node'larina uygulanir:
|
||||
- `tar`
|
||||
- `unzip`
|
||||
- `bash-completion`
|
||||
- `gettext` — envsubst icin; CI/CD deploy pipeline'larinda gerekli
|
||||
- `gettext` — envsubst için; CI/CD deploy pipeline'larında gerekli
|
||||
- `tree`
|
||||
- `ca-certificates`
|
||||
- `fail2ban`
|
||||
- `chrony`
|
||||
- `python3`
|
||||
- `python3-pip`
|
||||
- `htop` — interaktif proses izleme (EPEL)
|
||||
- `btop` — kaynak monitörü, grafik arayüz (EPEL)
|
||||
- timezone: `Europe/Istanbul`
|
||||
- hostname ayari
|
||||
- sistem reboot gerekiyorsa kontrollu reboot
|
||||
- hostname ayarı
|
||||
- sistem reboot gerekiyorsa kontrollü reboot
|
||||
|
||||
## Security Hardening Role
|
||||
|
||||
Tum test node'larina uygulanir:
|
||||
Tüm test node'larına uygulanır:
|
||||
|
||||
- SSH password login kapatilir.
|
||||
- Root SSH login kapatilir.
|
||||
- Sadece SSH key ile login kalir.
|
||||
- SSH password login kapatılır.
|
||||
- Root SSH login kapatılır.
|
||||
- Sadece SSH key ile login kalır.
|
||||
- `PermitEmptyPasswords no`
|
||||
- `MaxAuthTries 3`
|
||||
- `fail2ban` SSH jail aktif edilir.
|
||||
- `dnf-automatic` ile otomatik guvenlik guncellestirmeleri aktif edilir.
|
||||
- `dnf-automatic` ile otomatik güvenlik güncelleştirmeleri aktif edilir.
|
||||
- `firewalld` default:
|
||||
- incoming: deny (drop zone)
|
||||
- outgoing: allow
|
||||
- Public SSH sadece admin CIDR'dan acilir.
|
||||
- Public SSH sadece admin CIDR'dan açılır.
|
||||
|
||||
### SELinux Karari
|
||||
### SELinux Kararı
|
||||
|
||||
Rocky Linux 10 SELinux enforcing modda gelir. Karar: **disabled**.
|
||||
|
||||
Gerekce:
|
||||
- Hetzner Cloud firewall (dis perimeter) + firewalld (host) iki katman ag guvenligini saglar.
|
||||
- Docker + davfs2 + firewalld kombinasyonu SELinux enforcing modda ek policy ve volume label yonetimi gerektirir.
|
||||
- Utils VPS'te de disabled yapilmis; tutarlilik saglanir.
|
||||
Gerekçe:
|
||||
- Hetzner Cloud firewall (dış perimeter) + firewalld (host) iki katman ağ güvenliğini sağlar.
|
||||
- Docker + davfs2 + firewalld kombinasyonu SELinux enforcing modda ek policy ve volume label yönetimi gerektirir.
|
||||
- Utils VPS'te de disabled yapılmış; tutarlılık sağlanır.
|
||||
|
||||
```bash
|
||||
# /etc/selinux/config icinde:
|
||||
# /etc/selinux/config içinde:
|
||||
SELINUX=disabled
|
||||
# Degisiklik reboot sonrasi aktif olur
|
||||
# Değişiklik reboot sonrası aktif olur
|
||||
reboot
|
||||
```
|
||||
|
||||
@ -101,9 +177,9 @@ Ansible'da:
|
||||
when: selinux_change.changed
|
||||
```
|
||||
|
||||
### fail2ban Konfigurasyonu
|
||||
### fail2ban Konfigürasyonu
|
||||
|
||||
`/etc/fail2ban/jail.local` icerigi:
|
||||
`/etc/fail2ban/jail.local` içeriği:
|
||||
|
||||
```ini
|
||||
[DEFAULT]
|
||||
@ -119,19 +195,19 @@ enabled = true
|
||||
```
|
||||
|
||||
- `bantime`: 6 saat ban
|
||||
- `findtime`: 5 dakika icinde
|
||||
- `maxretry`: 5 basarisiz giris → ban
|
||||
- `ignoreip`: admin CIDR'lari ban'dan muaf tutar
|
||||
- `findtime`: 5 dakika içinde
|
||||
- `maxretry`: 5 başarısız giriş → ban
|
||||
- `ignoreip`: admin CIDR'ları ban'dan muaf tutar
|
||||
|
||||
Ansible'da `admin_allowed_cidrs` listesi space-separated stringe donusturulup template'e basilir.
|
||||
Ansible'da `admin_allowed_cidrs` listesi space-separated stringe dönüştürülüp template'e basılır.
|
||||
|
||||
Not: Docker iptables kurallari firewalld ile etkilesebilir. Hetzner Cloud firewall asil dis perimeter kabul edilir; firewalld host icinde ikinci katman olarak kullanilir.
|
||||
Not: Docker iptables kuralları firewalld ile etkileşebilir. Hetzner Cloud firewall asıl dış perimeter kabul edilir; firewalld host içinde ikinci katman olarak kullanılır.
|
||||
|
||||
## Docker Role
|
||||
|
||||
Sadece `iklim-app-01` uzerinde zorunludur. `iklim-db-01` uzerinde DB manual kurulum stratejisine gore opsiyonel tutulabilir.
|
||||
Her iki node (`iklim-app-01` ve `iklim-db-01`) üzerinde de zorunludur. DB node'u Swarm Worker olarak ağa dahil olacağı için Docker Engine her iki makinede de kurulu olmalıdır.
|
||||
|
||||
Docker kurulumu resmi Docker dnf repository uzerinden yapilir:
|
||||
Docker kurulumu resmi Docker dnf repository üzerinden yapılır:
|
||||
|
||||
- Docker GPG key + dnf repository (`https://download.docker.com/linux/rhel/docker-ce.repo`)
|
||||
- paketler:
|
||||
@ -142,30 +218,26 @@ Docker kurulumu resmi Docker dnf repository uzerinden yapilir:
|
||||
- `docker-compose-plugin`
|
||||
- Docker servisi enabled + started
|
||||
|
||||
Docker convenience script kullanilmayacak. Production benzeri test ortami icin paket repository yolu tercih edilir.
|
||||
Docker convenience script kullanılmayacak. Production benzeri test ortamı için 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`
|
||||
- `iklim-app-01` üzerinde Swarm Manager olarak init edilir.
|
||||
- `iklim-db-01` üzerinde Swarm Worker olarak join edilir (Overlay network erişimi için).
|
||||
- advertise addr: `10.10.10.11` (manager için)
|
||||
- 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.
|
||||
- Node etiketleri:
|
||||
- `iklim-app-01` -> `type=service`
|
||||
- `iklim-db-01` -> `role=db`
|
||||
- `iklim-app-01` üzerinde hem manager hem worker (Active) görevini sürdürür.
|
||||
|
||||
Test tek node Swarm oldugu icin join token kullanimi yoktur.
|
||||
|
||||
## Node Directory Role
|
||||
|
||||
`iklim-app-01` uzerinde deploy on kosullari:
|
||||
`iklim-app-01` üzerinde deploy ön koşulları:
|
||||
|
||||
```text
|
||||
/opt/iklimco
|
||||
@ -175,7 +247,7 @@ Test tek node Swarm oldugu icin join token kullanimi yoktur.
|
||||
/opt/iklimco/init/mongodb
|
||||
```
|
||||
|
||||
DB node uzerinde manuel DB kurulumu icin minimum:
|
||||
DB node üzerinde manuel DB kurulumu için minimum:
|
||||
|
||||
```text
|
||||
/opt/iklimco
|
||||
@ -185,57 +257,57 @@ DB node uzerinde manuel DB kurulumu icin minimum:
|
||||
|
||||
## StorageBox DAVFS Mount Role
|
||||
|
||||
Her iki node'a uygulanir (`iklim-app-01` ve `iklim-db-01`).
|
||||
Her iki node'a uygulanır (`iklim-app-01` ve `iklim-db-01`).
|
||||
|
||||
### Amac
|
||||
### Amaç
|
||||
|
||||
Hetzner StorageBox'u WebDAV (DAVFS) protokolü üzerinden `/mnt/storagebox` olarak mount eder. Docker volume'lari bu dizine baglanarak veri kaliciligini ve yedeklemeyi saglar.
|
||||
Hetzner StorageBox'u WebDAV (DAVFS) protokolü üzerinden `/mnt/storagebox` olarak mount eder. Docker volume'ları bu dizine bağlanarak veri kalıcılığını ve yedeklemeyi sağlar.
|
||||
|
||||
### Test Ortami Sub-Account
|
||||
### Test Ortamı Sub-Account
|
||||
|
||||
| Parametre | Degisken | Deger |
|
||||
| Parametre | Değişken | Değer |
|
||||
| --- | --- | --- |
|
||||
| Ana hesap | `storagebox_account` | `u469968` |
|
||||
| Sub-account | `storagebox_user` | `u469968-sub1` |
|
||||
| WebDAV URL | `storagebox_url` | `https://u469968-sub1.your-storagebox.de/` |
|
||||
| Sub-account | `storagebox_user` | `u469968-sub4` |
|
||||
| WebDAV URL | `storagebox_url` | `https://u469968-sub4.your-storagebox.de/` |
|
||||
| Mount point | `storagebox_mount_point` | `/mnt/storagebox` |
|
||||
|
||||
### Role Degiskenleri
|
||||
### Role Değişkenleri
|
||||
|
||||
`group_vars/all.yml` — tum ortamlar icin ortak:
|
||||
`group_vars/all.yml` — tüm ortamlar için ortak:
|
||||
|
||||
```yaml
|
||||
storagebox_account: "u469968"
|
||||
```
|
||||
|
||||
`group_vars/test.yml` — test ortamina ozgu; user ve url account'tan turetilir:
|
||||
`group_vars/test.yml` — test ortamına özgü; user ve url account'tan türetilir:
|
||||
|
||||
```yaml
|
||||
storagebox_user: "{{ storagebox_account }}-sub1"
|
||||
storagebox_url: "https://{{ storagebox_user }}.your-storagebox.de/"
|
||||
storagebox_password: "{{ vault_storagebox_password }}" # Ansible Vault ile saklanir
|
||||
storagebox_password: "{{ vault_storagebox_password }}" # Ansible Vault ile saklanır
|
||||
storagebox_mount_point: "/mnt/storagebox"
|
||||
```
|
||||
|
||||
Prod ortaminda yalnizca suffix degisir (`sub1` → `sub2`), geri kalan her sey turetilir.
|
||||
Prod ortamında yalnızca suffix değişir (`sub4` → `sub5`), geri kalan her şey türetilir.
|
||||
|
||||
`vault_storagebox_password` degeri Ansible Vault ile sifreli `group_vars/test-vault.yml` icinde tutulur:
|
||||
`vault_storagebox_password` değeri Ansible Vault ile şifreli `group_vars/test-vault.yml` içinde tutulur:
|
||||
|
||||
```bash
|
||||
# Sifreleme
|
||||
ansible-vault encrypt group_vars/test-vault.yml
|
||||
|
||||
# Duzenleme
|
||||
# Düzenleme
|
||||
ansible-vault edit group_vars/test-vault.yml
|
||||
```
|
||||
|
||||
`test-vault.yml` icerigi:
|
||||
`test-vault.yml` içeriği:
|
||||
|
||||
```yaml
|
||||
vault_storagebox_password: "SUB_ACCOUNT_PAROLASI"
|
||||
```
|
||||
|
||||
### Adimlar
|
||||
### Adımlar
|
||||
|
||||
1. **davfs2 kurulumu**
|
||||
|
||||
@ -246,7 +318,7 @@ vault_storagebox_password: "SUB_ACCOUNT_PAROLASI"
|
||||
state: present
|
||||
```
|
||||
|
||||
2. **Kimlik bilgileri dosyasi** (`/etc/davfs2/secrets`)
|
||||
2. **Kimlik bilgileri dosyası** (`/etc/davfs2/secrets`)
|
||||
|
||||
```yaml
|
||||
- name: Configure davfs2 secrets
|
||||
@ -259,7 +331,7 @@ vault_storagebox_password: "SUB_ACCOUNT_PAROLASI"
|
||||
group: root
|
||||
```
|
||||
|
||||
3. **Mount point olustur**
|
||||
3. **Mount point oluştur**
|
||||
|
||||
```yaml
|
||||
- name: Create mount point
|
||||
@ -290,7 +362,7 @@ vault_storagebox_password: "SUB_ACCOUNT_PAROLASI"
|
||||
creates: "{{ storagebox_mount_point }}/.mounted_marker"
|
||||
```
|
||||
|
||||
Mount basarisi icin dizine bir marker dosyasi yazilabilir:
|
||||
Mount başarısı için dizine bir marker dosyası yazılabilir:
|
||||
|
||||
```yaml
|
||||
- name: Write mount marker
|
||||
@ -302,58 +374,58 @@ vault_storagebox_password: "SUB_ACCOUNT_PAROLASI"
|
||||
### Notlar
|
||||
|
||||
- `davfs2` paketi EPEL repository'sinde bulunur; base role `epel-release`'i zaten kurar.
|
||||
- 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 Swarm servisleri `/mnt/storagebox/<env>/<service>/` altindaki dizinleri bind mount olarak kullanir.
|
||||
- StorageBox şifreleri asla plaintext olarak repository'e eklenmez; Ansible Vault zorunludur.
|
||||
- Mount noktası reboot'ta `_netdev` flag'ı sayesinde network hazır olduktan sonra otomatik mount edilir.
|
||||
- Docker Swarm servisleri `/mnt/storagebox/<env>/<service>/` altındaki dizinleri bind mount olarak kullanır.
|
||||
|
||||
## StorageBox SSH Key Role
|
||||
|
||||
Her iki node'a uygulanir (`iklim-app-01` ve `iklim-db-01`).
|
||||
Her iki node'a uygulanır (`iklim-app-01` ve `iklim-db-01`).
|
||||
|
||||
### Amac
|
||||
### Amaç
|
||||
|
||||
Sunucu uzerinde ed25519 SSH anahtar cifti uretilir ve StorageBox ana hesabina yuklenir.
|
||||
Bu sayede CI/CD pipeline'lari `STORAGEBOX_SSH_PRIV` Gitea secret'ini kullanarak
|
||||
sifre girmeden StorageBox'a erisebilir.
|
||||
Sunucu üzerinde ed25519 SSH anahtar çifti üretilir ve StorageBox ana hesabına yüklenir.
|
||||
Bu sayede CI/CD pipeline'ları `STORAGEBOX_SSH_PRIV` Gitea secret'ini kullanarak
|
||||
şifresiz erişim sağlayabilir.
|
||||
|
||||
### Adimlar
|
||||
### Adımlar
|
||||
|
||||
1. **SSH key uret** (eger yoksa)
|
||||
1. **SSH Key üretimi**
|
||||
|
||||
```yaml
|
||||
- name: Generate SSH key for storagebox
|
||||
- name: Generate SSH key for StorageBox
|
||||
ansible.builtin.user:
|
||||
name: root
|
||||
generate_ssh_key: yes
|
||||
ssh_key_type: ed25519
|
||||
ssh_key_file: /root/.ssh/id_ed25519_storagebox
|
||||
ssh_key_file: .ssh/id_ed25519_storagebox
|
||||
ssh_key_comment: "{{ inventory_hostname }}-storagebox"
|
||||
```
|
||||
|
||||
2. **Public key'i StorageBox'a yukle**
|
||||
2. **Public key'i StorageBox'a yükle**
|
||||
|
||||
Bu adim manuel yapilir (ilk kez sifre gerektirir):
|
||||
Bu adım manuel yapılır (ilk kez şifre gerektirir):
|
||||
|
||||
```bash
|
||||
cat /root/.ssh/id_ed25519_storagebox.pub | ssh -p23 u469968-sub1@u469968-sub1.your-storagebox.de install-ssh-key
|
||||
cat /root/.ssh/id_ed25519_storagebox.pub | ssh -p23 u469968-sub4@u469968-sub4.your-storagebox.de install-ssh-key
|
||||
```
|
||||
|
||||
Sonraki erisimler sifresiz calisir:
|
||||
Sonraki erişimler şifresiz çalışır:
|
||||
|
||||
```bash
|
||||
sftp -P23 u469968-sub1@u469968-sub1.your-storagebox.de
|
||||
sftp -P23 u469968-sub4@u469968-sub4.your-storagebox.de
|
||||
```
|
||||
|
||||
3. **Private ve public key'leri Gitea'ya ekle**
|
||||
|
||||
Gitea → Organization Settings → Actions → Secrets:
|
||||
|
||||
| Secret Adi | Deger |
|
||||
| Secret Adı | Değer |
|
||||
| --- | --- |
|
||||
| `STORAGEBOX_SSH_PRIV` | `/root/.ssh/id_ed25519_storagebox` icerigi |
|
||||
| `STORAGEBOX_SSH_PUB` | `/root/.ssh/id_ed25519_storagebox.pub` icerigi |
|
||||
| `STORAGEBOX_SSH_PRIV` | `/root/.ssh/id_ed25519_storagebox` içeriği |
|
||||
| `STORAGEBOX_SSH_PUB` | `/root/.ssh/id_ed25519_storagebox.pub` içeriği |
|
||||
|
||||
Key icerigini almak icin:
|
||||
Key içeriğini almak için:
|
||||
|
||||
```bash
|
||||
cat /root/.ssh/id_ed25519_storagebox
|
||||
@ -362,18 +434,7 @@ sifre girmeden StorageBox'a erisebilir.
|
||||
|
||||
### Notlar
|
||||
|
||||
- Her sunucu icin ayri key uretilir; tum public key'ler StorageBox ana hesabina yuklenir.
|
||||
- Private key asla repo'ya commit edilmez; yalnizca Gitea secret olarak saklanir.
|
||||
- Her sunucu için ayrı key üretilir; tüm public key'ler StorageBox ana hesabına yüklenir.
|
||||
- Private key asla repo'ya commit edilmez; yalnızca Gitea secret olarak saklanır.
|
||||
|
||||
## 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.
|
||||
|
||||
@ -1,112 +1,34 @@
|
||||
# 08 - Test DB Docker Kurulumu (Swarm)
|
||||
# 04 - Test DB Docker Kurulumu (Swarm Worker)
|
||||
|
||||
Bu asamanin amaci `iklim-db-01` node'unu Swarm'a worker olarak eklemek ve PostgreSQL ile MongoDB'yi Swarm servisi olarak calistirmaktir. Veri kaliciligini StorageBox saglar.
|
||||
Bu aşamanın amacı `iklim-db-01` node'unu Swarm'a worker olarak eklemek ve PostgreSQL ile MongoDB'yi Swarm servisi olarak çalıştırmaktır.
|
||||
|
||||
DB yazilimi Ansible tarafindan kurulmaz; bu belge DB node uzerinde elle veya ayri bir Ansible role ile uygulanir. `03-test-ansible-bootstrap.md` tamamlandiktan sonra baslayiniz.
|
||||
## Mimari Karar
|
||||
|
||||
## Mimari
|
||||
Yol haritasında DB'lerin "manuel" kurulacağı belirtilmiştir. Test ortamında bu "manuel" süreç, DB'lerin işletim sistemine doğrudan kurulması yerine, **Swarm Worker** üzerinde Docker konteynerleri olarak ayağa kaldırılması şeklinde uygulanacaktır.
|
||||
|
||||
```
|
||||
iklim-app-01 (Swarm manager, 10.10.10.11)
|
||||
|
|
||||
|-- iklimco-net (overlay)
|
||||
|
|
||||
iklim-db-01 (Swarm worker, 10.10.20.11) [role=db]
|
||||
|-- postgresql-v17 (Swarm service, placement: role=db)
|
||||
|-- mongo-v8 (Swarm service, placement: role=db)
|
||||
|
|
||||
/mnt/storagebox/test/db/
|
||||
postgresql/data/
|
||||
mongodb/data/
|
||||
mongodb/log/
|
||||
mongodb/config/
|
||||
```
|
||||
**Neden?**
|
||||
1. **Yönetim Kolaylığı:** Docker ile versiyon geçişleri ve konfigürasyon yönetimi çok daha hızlıdır.
|
||||
2. **Overlay Network:** Uygulama servisleri (`iklim-app-01`), DB'lere `iklimco-net` overlay network üzerinden şifreli ve izole bir şekilde erişebilir.
|
||||
3. **Veri Kalıcılığı:** Veriler Hetzner StorageBox (`/mnt/storagebox`) üzerinde saklanarak host bağımsızlığı sağlanır.
|
||||
|
||||
## On Kosullar
|
||||
## Ön Koşullar
|
||||
|
||||
- `03-test-ansible-bootstrap.md` her iki node'da tamamlanmis olmali.
|
||||
- StorageBox `/mnt/storagebox` olarak her iki node'da mount edilmis olmali.
|
||||
- Docker `iklim-db-01` uzerinde kurulu olmali (bootstrap role bunu yapar).
|
||||
- `03-test-ansible-bootstrap.md` her iki node'da tamamlanmış olmalı.
|
||||
- StorageBox `/mnt/storagebox` olarak her iki node'da mount edilmiş olmalı.
|
||||
- Docker `iklim-db-01` üzerinde kurulu olmalı (Bootstrap role bunu yapar).
|
||||
|
||||
## 1. Firewall Guncellemesi
|
||||
## 1. Firewall Güncellemesi
|
||||
|
||||
`iklim-db-01`'in Swarm'a katilabilmesi icin ek kurallara ihtiyac var.
|
||||
`terraform/hetzner/test/firewall.tf` dosyasina asagidaki kurallari ekle:
|
||||
`iklim-db-01`'in Swarm'a katılabilmesi ve uygulama trafiğini kabul etmesi için `terraform/hetzner/test/firewall.tf` dosyasına kurallar eklenmelidir.
|
||||
|
||||
`hcloud_firewall.swarm` icine (DB subnet'ten Swarm portlarina erisim):
|
||||
### Swarm İletişimi (App Subnet <-> DB Subnet)
|
||||
Swarm yönetimi için `2377/tcp`, `7946/tcp/udp` ve `4789/udp` portları her iki subnet arasında karşılıklı açık olmalıdır.
|
||||
|
||||
```hcl
|
||||
rule {
|
||||
direction = "in"
|
||||
protocol = "tcp"
|
||||
port = "2377"
|
||||
source_ips = [local.db_subnet_cidr]
|
||||
description = "Docker Swarm control plane from DB subnet"
|
||||
}
|
||||
|
||||
rule {
|
||||
direction = "in"
|
||||
protocol = "tcp"
|
||||
port = "7946"
|
||||
source_ips = [local.db_subnet_cidr]
|
||||
description = "Docker Swarm node discovery (TCP) from DB subnet"
|
||||
}
|
||||
|
||||
rule {
|
||||
direction = "in"
|
||||
protocol = "udp"
|
||||
port = "7946"
|
||||
source_ips = [local.db_subnet_cidr]
|
||||
description = "Docker Swarm node discovery (UDP) from DB subnet"
|
||||
}
|
||||
|
||||
rule {
|
||||
direction = "in"
|
||||
protocol = "udp"
|
||||
port = "4789"
|
||||
source_ips = [local.db_subnet_cidr]
|
||||
description = "Docker Swarm VXLAN overlay from DB subnet"
|
||||
}
|
||||
```
|
||||
|
||||
`hcloud_firewall.db` icine (app subnet'ten Swarm portlarina erisim):
|
||||
|
||||
```hcl
|
||||
rule {
|
||||
direction = "in"
|
||||
protocol = "tcp"
|
||||
port = "2377"
|
||||
source_ips = [local.app_subnet_cidr]
|
||||
description = "Docker Swarm control plane from app subnet"
|
||||
}
|
||||
|
||||
rule {
|
||||
direction = "in"
|
||||
protocol = "tcp"
|
||||
port = "7946"
|
||||
source_ips = [local.app_subnet_cidr]
|
||||
description = "Docker Swarm node discovery (TCP) from app subnet"
|
||||
}
|
||||
|
||||
rule {
|
||||
direction = "in"
|
||||
protocol = "udp"
|
||||
port = "7946"
|
||||
source_ips = [local.app_subnet_cidr]
|
||||
description = "Docker Swarm node discovery (UDP) from app subnet"
|
||||
}
|
||||
|
||||
rule {
|
||||
direction = "in"
|
||||
protocol = "udp"
|
||||
port = "4789"
|
||||
source_ips = [local.app_subnet_cidr]
|
||||
description = "Docker Swarm VXLAN overlay from app subnet"
|
||||
}
|
||||
```
|
||||
|
||||
Sonra uygula:
|
||||
### DB Erişimi (App Subnet -> DB Subnet)
|
||||
- **PostgreSQL:** `5432/tcp`
|
||||
- **MongoDB:** `27017/tcp`
|
||||
|
||||
Güncellemeyi yaptıktan sonra:
|
||||
```bash
|
||||
cd terraform/hetzner/test
|
||||
terraform apply
|
||||
@ -114,29 +36,24 @@ terraform apply
|
||||
|
||||
## 2. DB Node'u Swarm'a Ekleme
|
||||
|
||||
**iklim-app-01 uzerinde** join token al:
|
||||
|
||||
**iklim-app-01 üzerinde (Manager)** join token alın:
|
||||
```bash
|
||||
docker swarm join-token worker
|
||||
```
|
||||
|
||||
**iklim-db-01 uzerinde** Swarm'a katil:
|
||||
|
||||
**iklim-db-01 üzerinde (Worker)** Swarm'a katılın:
|
||||
```bash
|
||||
docker swarm join --token <TOKEN> 10.10.10.11:2377
|
||||
```
|
||||
|
||||
**iklim-app-01 uzerinde** node'u etiketle:
|
||||
|
||||
**iklim-app-01 üzerinde** node'u etiketleyin:
|
||||
```bash
|
||||
docker node update --label-add role=db iklim-db-01
|
||||
docker node ls
|
||||
```
|
||||
|
||||
## 3. StorageBox Dizin Yapisi
|
||||
|
||||
**iklim-db-01 uzerinde:**
|
||||
## 3. StorageBox Dizin Yapısı
|
||||
|
||||
**iklim-db-01 üzerinde:**
|
||||
```bash
|
||||
mkdir -p /mnt/storagebox/test/db/postgresql/data
|
||||
mkdir -p /mnt/storagebox/test/db/mongodb/data
|
||||
@ -144,36 +61,29 @@ mkdir -p /mnt/storagebox/test/db/mongodb/log
|
||||
mkdir -p /mnt/storagebox/test/db/mongodb/config
|
||||
```
|
||||
|
||||
## 4. PostgreSQL Stack
|
||||
|
||||
### mongod.conf
|
||||
|
||||
`/mnt/storagebox/test/db/mongodb/config/mongod.conf` dosyasini olustur:
|
||||
## 4. Veritabanı Konfigürasyonları
|
||||
|
||||
### MongoDB Config (`mongod.conf`)
|
||||
`/mnt/storagebox/test/db/mongodb/config/mongod.conf` dosyasını oluşturun:
|
||||
```yaml
|
||||
processManagement:
|
||||
pidFilePath: "/data/db/mongod.pid"
|
||||
storage:
|
||||
dbPath: /data/db
|
||||
journal:
|
||||
enabled: true
|
||||
systemLog:
|
||||
destination: file
|
||||
logAppend: true
|
||||
path: /data/log/mongod.log
|
||||
net:
|
||||
port: 27017
|
||||
storage:
|
||||
engine: "wiredTiger"
|
||||
dbPath: "/data/db"
|
||||
directoryPerDB: true
|
||||
systemLog:
|
||||
verbosity: 0
|
||||
timeStampFormat: "iso8601-local"
|
||||
destination: file
|
||||
path: "/data/log/mongo.log"
|
||||
logAppend: true
|
||||
logRotate: rename
|
||||
bindIp: 0.0.0.0
|
||||
security:
|
||||
authorization: enabled
|
||||
```
|
||||
|
||||
### Stack Dosyasi
|
||||
|
||||
`/opt/iklimco/stacks/db.yml`:
|
||||
## 5. DB Stack Kurulumu
|
||||
|
||||
`/opt/iklimco/stacks/db.yml` (iklim-app-01 üzerinde):
|
||||
```yaml
|
||||
version: "3.8"
|
||||
|
||||
@ -189,98 +99,44 @@ services:
|
||||
POSTGRES_PASSWORD: "${POSTGRES_PASSWORD}"
|
||||
POSTGRES_DB: postgres
|
||||
PGDATA: /var/lib/postgresql/data/pgdata
|
||||
TZ: "Europe/Istanbul"
|
||||
volumes:
|
||||
- /mnt/storagebox/test/db/postgresql/data:/var/lib/postgresql/data
|
||||
- /opt/iklimco/init/postgresql:/docker-entrypoint-initdb.d:ro
|
||||
networks:
|
||||
- iklimco-net
|
||||
deploy:
|
||||
replicas: 1
|
||||
placement:
|
||||
constraints:
|
||||
- node.labels.role == db
|
||||
restart_policy:
|
||||
condition: on-failure
|
||||
|
||||
mongodb:
|
||||
image: mongo:8
|
||||
environment:
|
||||
MONGO_INITDB_ROOT_USERNAME: mongo-root
|
||||
MONGO_INITDB_ROOT_USERNAME: "${DATABASE_MONGO_ROOT_USER}"
|
||||
MONGO_INITDB_ROOT_PASSWORD: "${MONGO_ROOT_PASSWORD}"
|
||||
volumes:
|
||||
- /mnt/storagebox/test/db/mongodb/data:/data/db
|
||||
- /mnt/storagebox/test/db/mongodb/log:/data/log
|
||||
- /mnt/storagebox/test/db/mongodb/config:/data/configdb
|
||||
- /mnt/storagebox/test/db/mongodb/config/mongod.conf:/etc/mongod.conf
|
||||
command: ["--config", "/etc/mongod.conf"]
|
||||
networks:
|
||||
- iklimco-net
|
||||
command: ["--config", "/data/configdb/mongod.conf"]
|
||||
deploy:
|
||||
replicas: 1
|
||||
placement:
|
||||
constraints:
|
||||
- node.labels.role == db
|
||||
restart_policy:
|
||||
condition: on-failure
|
||||
```
|
||||
|
||||
### .env Dosyasi
|
||||
|
||||
`/opt/iklimco/stacks/.env` (repo'ya commit edilmez):
|
||||
|
||||
```env
|
||||
DATABASE_POSTGRES_ROOT_USER=<kullanici-adi>
|
||||
POSTGRES_PASSWORD=<guclu-sifre>
|
||||
MONGO_ROOT_PASSWORD=<guclu-sifre>
|
||||
```
|
||||
|
||||
## 5. Deploy
|
||||
|
||||
### Deploy
|
||||
```bash
|
||||
# iklim-app-01 uzerinde (Swarm manager)
|
||||
docker stack deploy --compose-file /opt/iklimco/stacks/db.yml \
|
||||
--with-registry-auth \
|
||||
$(set -a; source /opt/iklimco/stacks/.env; set +a; echo "") \
|
||||
iklim-db
|
||||
# .env dosyasını oluşturun (Hassas veriler için)
|
||||
# DATABASE_POSTGRES_ROOT_USER, POSTGRES_PASSWORD, DATABASE_MONGO_ROOT_USER, MONGO_ROOT_PASSWORD
|
||||
|
||||
docker stack deploy -c /opt/iklimco/stacks/db.yml iklim-db
|
||||
```
|
||||
|
||||
Alternatif olarak env-file destegi icin:
|
||||
## 6. Kabul Kriterleri
|
||||
|
||||
```bash
|
||||
docker stack deploy \
|
||||
--compose-file <(docker-compose -f /opt/iklimco/stacks/db.yml config) \
|
||||
iklim-db
|
||||
```
|
||||
|
||||
Kontrol:
|
||||
|
||||
```bash
|
||||
docker stack services iklim-db
|
||||
docker service logs iklim-db_postgresql
|
||||
docker service logs iklim-db_mongodb
|
||||
```
|
||||
|
||||
## 6. App Servislerinden Erisim
|
||||
|
||||
Overlay network (`iklimco-net`) uzerinden servis adlariyla erisim:
|
||||
|
||||
| Servis | Host (overlay DNS) | Port |
|
||||
| --- | --- | --- |
|
||||
| PostgreSQL | `iklim-db_postgresql` | `5432` |
|
||||
| MongoDB | `iklim-db_mongodb` | `27017` |
|
||||
|
||||
Spring Boot vb. uygulama konfigurasyon ornegi:
|
||||
|
||||
```
|
||||
spring.datasource.url=jdbc:postgresql://iklim-db_postgresql:5432/iklimdb
|
||||
spring.data.mongodb.uri=mongodb://mongo-root:<sifre>@iklim-db_mongodb:27017/iklimdb?authSource=admin
|
||||
```
|
||||
|
||||
## Kabul Kriterleri
|
||||
|
||||
- `docker stack services iklim-db` her iki servisi `1/1` olarak gosterir.
|
||||
- `iklim-app-01` uzerinden `postgresql` servisine TCP 5432 overlay ile ulasilabilir.
|
||||
- `iklim-app-01` uzerinden `mongodb` servisine TCP 27017 overlay ile ulasilabilir.
|
||||
- `/mnt/storagebox/test/db/postgresql/data/` dizininde veri dosyalari olusur.
|
||||
- Servis yeniden baslatildiginda veri korunur.
|
||||
- `5432` ve `27017` portlari public internet'ten kapalidir.
|
||||
- `docker node ls` komutunda `iklim-db-01` Ready ve Active görünür.
|
||||
- `docker stack services iklim-db` her iki servisi 1/1 replica ile gösterir.
|
||||
- Uygulama node'undan `iklim-db_postgresql` ve `iklim-db_mongodb` DNS isimleriyle erişim sağlanır.
|
||||
- Reboot sonrası veriler `/mnt/storagebox` üzerinden korunur.
|
||||
|
||||
@ -1,154 +1,95 @@
|
||||
# 03 - Test Runner ve Deploy On Kosullari
|
||||
# 05 - Test Runner ve Deploy Ön Koşulları
|
||||
|
||||
Bu asamanin amaci test ortaminda Gitea Actions runner'i systemd servisi olarak kurmak ve mevcut test CI/CD pipeline'larinin calisabilecegi host on kosullarini hazirlamaktir.
|
||||
Bu aşamanın amacı test ortamında Gitea Actions runner'ı (`act_runner`) systemd servisi olarak kurmak ve CI/CD pipeline'larının çalışabileceği ortamı hazırlamaktır.
|
||||
|
||||
## Runner Yerlesimi
|
||||
## Runner Yerleşimi
|
||||
|
||||
Test ortaminda tek runner yeterlidir:
|
||||
Test ortamında maliyet ve basitlik için tek runner kullanılır:
|
||||
|
||||
| Host | Runner |
|
||||
| --- | --- |
|
||||
| `iklim-app-01` | `act_runner` systemd servisi |
|
||||
|
||||
Runner Docker container olarak calistirilmayacak. `/var/run/docker.sock` bir runner container'ina mount edilmeyecek.
|
||||
|
||||
## Neden Systemd Runner
|
||||
|
||||
Mevcut CI/CD akisinda Gitea job'lari gerekli hazirliklari kendi icinde yapip deploy komutlarini calistiriyor. Runner'in Docker container olmasi, Docker socket mount edilmesini gerektirir ve bu model ekstra yetki riski uretir. Systemd runner modelinde socket mount yoktur; ancak runner host uzerinde Docker kullanacagi icin runner kullanicisinin Docker erisimi yine yuksek yetki kabul edilir.
|
||||
|
||||
Bu nedenle:
|
||||
|
||||
- Runner sadece guvenilir Gitea instance/repo icin kullanilir.
|
||||
- Runner token Ansible Vault veya CI secret olarak saklanir.
|
||||
- Runner config ve token repo'ya commit edilmez.
|
||||
|
||||
## Runner Kullanicisi
|
||||
|
||||
Ansible `gitea_runner` role'u:
|
||||
|
||||
- `gitea-runner` sistem kullanicisi olusturur.
|
||||
- Kullanici shell'i ihtiyaca gore `/bin/bash` olabilir.
|
||||
- Kullanici Docker kullanacaksa `docker` grubuna eklenir.
|
||||
- Home dizini: `/var/lib/gitea-runner`
|
||||
- Config dizini: `/etc/gitea-act-runner`
|
||||
|
||||
Docker group root seviyesine yakin yetki verdigi icin bu karar bilincli kabul edilir.
|
||||
|
||||
## Runner Binary Kurulumu
|
||||
|
||||
Kurulum adimlari:
|
||||
|
||||
1. `act_runner` Linux amd64 binary indirilir.
|
||||
2. `/usr/local/bin/act_runner` olarak yerlestirilir.
|
||||
3. Executable permission verilir.
|
||||
4. Config uretilir veya template ile yazilir.
|
||||
5. Runner register edilir.
|
||||
6. Systemd unit enabled + started edilir.
|
||||
|
||||
## Runner Label PolitikasI
|
||||
|
||||
Test runner label'lari:
|
||||
|
||||
```text
|
||||
test-runner
|
||||
iklim-app-01
|
||||
ubuntu-24.04
|
||||
docker
|
||||
swarm-manager
|
||||
```
|
||||
|
||||
Mevcut workflow'larda `runs-on` degeri test icin bu label'lardan biriyle uyumlu hale getirilmelidir. Eski `ubuntu-latest` kullanimi self-hosted Gitea runner eslesmesi icin yeterli olmayabilir; bu durum Gitea Actions label konfigurasyonuna gore netlestirilmelidir.
|
||||
|
||||
## Deploy On Kosullari
|
||||
|
||||
Test deploy pipeline'lari icin `iklim-app-01` uzerinde bulunmasi gerekenler:
|
||||
|
||||
- Docker Engine
|
||||
- Docker Compose plugin
|
||||
- Git
|
||||
- curl
|
||||
- jq
|
||||
- gettext/envsubst
|
||||
- tree
|
||||
- ssh/scp client
|
||||
- Harbor registry erisimi
|
||||
- StorageBox erisimi
|
||||
- Gitea reposuna erisim
|
||||
- Swarm manager yetkisi
|
||||
- `iklimco-net` overlay network
|
||||
|
||||
CI/CD DB altyapisini kurmayacak. Test DB node hazir olacak; DB yazilimi ve cluster/manual setup ayridir.
|
||||
|
||||
## Deploy Lock Notu
|
||||
|
||||
Test ortaminda tek runner oldugu icin runner'lar arasi deploy yarismasi beklenmez.
|
||||
Yine de ayni branch'e arka arkaya push edilmesi veya manuel yeniden calistirma gibi
|
||||
durumlarda ayni servis deploy'u ust uste binebilir.
|
||||
|
||||
Test icin lock zorunlu degildir; ancak prod ile ayni aliskanligi kazanmak istenirse
|
||||
StorageBox uzerinde su path kullanilabilir:
|
||||
|
||||
```text
|
||||
test/locks/test-deploy.lock
|
||||
test/locks/services/<service-name>.lock
|
||||
```
|
||||
|
||||
Lock manuel olusturulmaz. Workflow basinda atomik `mkdir`, bitiste `rmdir` kullanilir.
|
||||
|
||||
## Secret Gereksinimleri
|
||||
|
||||
Runner kurulumu ve pipeline calismasi icin secret'lar:
|
||||
|
||||
- Gitea runner registration token
|
||||
- Harbor username/password veya token
|
||||
- StorageBox SSH key (priv + pub)
|
||||
- SSH deploy key
|
||||
- Hetzner token gerekmez; Terraform asamasinda kullanilir
|
||||
|
||||
Bu secret'lar repo'ya yazilmayacak.
|
||||
|
||||
## Gitea Organizasyon Secret'lari
|
||||
|
||||
Gitea → `git.tarla.io` → Organization → **Settings** → **Actions** → **Secrets** altina eklenir.
|
||||
|
||||
| Secret | Aciklama | Kaynak |
|
||||
| Host | Servis Adı | Label |
|
||||
| --- | --- | --- |
|
||||
| `STORAGEBOX_SSH_PRIV` | StorageBox erisimi icin private SSH key | Her sunucuda `/root/.ssh/id_ed25519_storagebox` |
|
||||
| `STORAGEBOX_SSH_PUB` | Eslesen public key | Her sunucuda `/root/.ssh/id_ed25519_storagebox.pub` |
|
||||
| `REPO_ACCESS_TOKEN` | Pipeline'in Gitea API'sini cagirabileceği token | Gitea → User Settings → Applications → Access Tokens |
|
||||
| `iklim-app-01` | `gitea-act-runner` | `test-runner`, `iklim-app-01`, `docker` |
|
||||
|
||||
Workflow'da kullanim ornegi:
|
||||
## 1. Runner Kullanıcısı ve Yetkiler
|
||||
|
||||
```yaml
|
||||
- name: Set up StorageBox SSH key
|
||||
run: |
|
||||
mkdir -p ~/.ssh
|
||||
echo "${{ secrets.STORAGEBOX_SSH_PRIV }}" > ~/.ssh/id_ed25519_storagebox
|
||||
echo "${{ secrets.STORAGEBOX_SSH_PUB }}" > ~/.ssh/id_ed25519_storagebox.pub
|
||||
chmod 600 ~/.ssh/id_ed25519_storagebox
|
||||
ssh-keyscan -p 23 u469968-sub1.your-storagebox.de >> ~/.ssh/known_hosts
|
||||
```
|
||||
|
||||
### Ansible Vault Secret'lari
|
||||
|
||||
CI/CD disindaki secret'lar `ansible/group_vars/test-vault.yml` icinde Ansible Vault ile sifrelenir:
|
||||
Runner, host üzerinde Docker komutlarını çalıştırabilmelidir.
|
||||
|
||||
```bash
|
||||
ansible-vault edit ansible/group_vars/test-vault.yml
|
||||
# Kullanıcıyı oluştur
|
||||
sudo useradd -m -s /bin/bash gitea-runner
|
||||
# Docker grubuna ekle
|
||||
sudo usermod -aG docker gitea-runner
|
||||
```
|
||||
|
||||
Icerik:
|
||||
## 2. act_runner Kurulumu
|
||||
|
||||
```yaml
|
||||
vault_storagebox_password: "SUB_ACCOUNT_PAROLASI"
|
||||
vault_gitea_runner_token: "RUNNER_REGISTRATION_TOKEN"
|
||||
### Binary İndirme
|
||||
```bash
|
||||
wget -O act_runner https://dl.gitea.com/act_runner/0.2.10/act_runner-0.2.10-linux-amd64
|
||||
sudo mv act_runner /usr/local/bin/
|
||||
sudo chmod +x /usr/local/bin/act_runner
|
||||
```
|
||||
|
||||
### Kayıt (Registration)
|
||||
Gitea arayüzünden (Organization -> Settings -> Actions -> Runners) bir **Registration Token** alın.
|
||||
|
||||
```bash
|
||||
# Config dosyasını oluştur
|
||||
act_runner generate-config > config.yaml
|
||||
|
||||
# Kayıt işlemini gerçekleştir
|
||||
act_runner register --instance https://git.tarla.io --token <TOKEN> --no-interactive
|
||||
```
|
||||
*Not: Kayıt sırasında label olarak `test-runner,iklim-app-01,docker` girildiğinden emin olun.*
|
||||
|
||||
## 3. Systemd Servisi
|
||||
|
||||
`/etc/systemd/system/gitea-act-runner.service` dosyasını oluşturun:
|
||||
|
||||
```ini
|
||||
[Unit]
|
||||
Description=Gitea Actions runner
|
||||
After=network.target docker.service
|
||||
|
||||
[Service]
|
||||
ExecStart=/usr/local/bin/act_runner daemon --config /etc/gitea-act-runner/config.yaml
|
||||
WorkingDirectory=/var/lib/gitea-runner
|
||||
User=gitea-runner
|
||||
Group=gitea-runner
|
||||
Restart=always
|
||||
RestartSec=5
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
```
|
||||
|
||||
Servisi başlatın:
|
||||
```bash
|
||||
sudo systemctl daemon-reload
|
||||
sudo systemctl enable --now gitea-act-runner
|
||||
```
|
||||
|
||||
## 4. Deploy Ön Koşulları
|
||||
|
||||
Pipeline'ın `iklim-app-01` üzerinde başarılı deploy yapabilmesi için şu araçların kurulu olması şarttır:
|
||||
- `docker-ce` ve `docker-compose-plugin`
|
||||
- `gettext` (`envsubst` komutu için)
|
||||
- `jq`
|
||||
- `git`
|
||||
|
||||
## 5. Gitea Organization Secrets
|
||||
|
||||
Pipeline'ların çalışması için Gitea Organization seviyesinde şu secret'lar tanımlanmalıdır:
|
||||
|
||||
| Secret | Açıklama |
|
||||
| --- | --- |
|
||||
| `STORAGEBOX_SSH_PRIV` | StorageBox'a erişim için private key |
|
||||
| `HARBOR_USERNAME` | Container registry kullanıcı adı |
|
||||
| `HARBOR_PASSWORD` | Container registry şifresi |
|
||||
|
||||
## Kabul Kriterleri
|
||||
|
||||
- `systemctl status gitea-act-runner` active gorunur.
|
||||
- Gitea UI icinde test runner online gorunur.
|
||||
- Runner label'lari test workflow `runs-on` ile eslesir.
|
||||
- Basit bir test workflow runner uzerinde calisir.
|
||||
- Runner job'u Docker komutu calistirabiliyorsa deploy on kosulu saglanmistir.
|
||||
- `8200/tcp` public internete acik degildir.
|
||||
1. Gitea Runners sayfasında `iklim-app-01` statusü **Idle** (yeşil) görünür.
|
||||
2. Bir test workflow'u (`runs-on: test-runner`) başarıyla tetiklenir.
|
||||
3. Runner, host üzerindeki Docker daemon'a erişip konteyner oluşturabilir.
|
||||
4. `8200/tcp` (Vault) portu public internete kapalıdır.
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
# 04 - Prod Terraform IaC
|
||||
# 06 - 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.
|
||||
|
||||
@ -29,6 +29,13 @@ Terraform prod ortaminda sunlari olusturur:
|
||||
|
||||
DB cluster yazilimi Terraform ile kurulmayacak. DB node'lari sadece makine, network ve firewall seviyesinde hazirlanacak.
|
||||
|
||||
## Versiyon Gereksinimleri
|
||||
|
||||
```text
|
||||
Terraform >= 1.6
|
||||
hcloud provider ~> 1.49
|
||||
```
|
||||
|
||||
## Onerilen Dosya Yapisi
|
||||
|
||||
```text
|
||||
@ -174,11 +181,16 @@ DB subnet kaynakli (`iklim-db-*` node'lari Swarm'a worker olarak katildigi icin)
|
||||
|
||||
### DB Firewall — Private Ingress
|
||||
|
||||
Admin erisimi:
|
||||
|
||||
| Port | Servis | Kaynak |
|
||||
| --- | --- | --- |
|
||||
| `22/tcp` | SSH | `admin_allowed_cidrs` |
|
||||
|
||||
App subnet kaynakli (`10.20.10.0/24`):
|
||||
|
||||
| Port | Servis | Not |
|
||||
| --- | --- | --- |
|
||||
| `22/tcp` | SSH | `admin_allowed_cidrs` |
|
||||
| `5432/tcp` | PostgreSQL (Patroni primary) | App subnet erisimi |
|
||||
| `27017/tcp` | MongoDB replica set endpoint | App subnet erisimi |
|
||||
| `2377/tcp` | Docker Swarm control plane | App subnet icinden |
|
||||
@ -197,6 +209,24 @@ DB subnet icindeki karsilikli erisim (`10.20.20.0/24`):
|
||||
|
||||
IP kisitlamasi Hetzner firewall'da degil, SWAG nginx konfigurasyonunda yapilir.
|
||||
|
||||
## Outputs
|
||||
|
||||
`terraform apply` veya `terraform output` sonrasi asagidaki degerler alinabilir:
|
||||
|
||||
| Output | Aciklama |
|
||||
| --- | --- |
|
||||
| `ansible_inventory_yaml` | Ansible inventory YAML — `ansible/inventory/generated/prod.yml` dosyasina yazilir |
|
||||
| `prod_private_ips` | Tum node'larin private IP haritasi (`swarm` ve `db` alt anahtarlari) |
|
||||
| `prod_public_ips` | Tum node'larin public IPv4 haritasi |
|
||||
| `prod_floating_ip` | Swarm giris noktasi icin Floating IP adresi (DNS A kaydi bu IP'ye yonlendirilir) |
|
||||
|
||||
Ansible inventory cikarmak icin:
|
||||
|
||||
```bash
|
||||
terraform output -raw ansible_inventory_yaml > \
|
||||
../../ansible/inventory/generated/prod.yml
|
||||
```
|
||||
|
||||
## Lifecycle ve Resize Politikasi
|
||||
|
||||
### server_type Degisikligi (Yeniden Boyutlandirma)
|
||||
@ -232,6 +262,78 @@ ayri resource tanimlanir:
|
||||
Her sunucuya `lifecycle { prevent_destroy = true }` eklenir. Kasitli silmek icin
|
||||
once lifecycle blogunu gecici olarak kaldir.
|
||||
|
||||
## Nasil Calistirilir
|
||||
|
||||
### Hazirlik
|
||||
|
||||
**1. tfvars olustur (bir kere):**
|
||||
|
||||
```bash
|
||||
cd Environment_Infrastructure/terraform/hetzner/prod
|
||||
cp terraform.tfvars.example terraform.tfvars
|
||||
# terraform.tfvars icerigini gercek degerlerle doldur
|
||||
# (hcloud_token, admin_allowed_cidrs, vb.)
|
||||
```
|
||||
|
||||
`terraform.tfvars` commit edilmez — `.gitignore` ile korunur.
|
||||
|
||||
**2. Provider yukle (bir kere):**
|
||||
|
||||
```bash
|
||||
terraform init
|
||||
```
|
||||
|
||||
### Ilk Uygulama
|
||||
|
||||
```bash
|
||||
# Nelerin olusacagini goster — bozma yapma
|
||||
terraform plan
|
||||
|
||||
# Onayla ve olustur
|
||||
terraform apply
|
||||
```
|
||||
|
||||
`apply` sonrasi 6 sunucu, 2 firewall, 1 floating IP ve network kaynaklari Hetzner'da gorunur.
|
||||
|
||||
### Ansible Inventory Alma
|
||||
|
||||
```bash
|
||||
terraform output -raw ansible_inventory_yaml > \
|
||||
../../ansible/inventory/generated/prod.yml
|
||||
```
|
||||
|
||||
### Resize (Server Type Degistirme)
|
||||
|
||||
`terraform.tfvars` icinde `server_type_swarm` veya `server_type_db` degerini degistir:
|
||||
|
||||
```bash
|
||||
terraform apply
|
||||
```
|
||||
|
||||
Sunucu durdurulur, Hetzner Resize API cagirilir, yeniden baslatilir. Disk ve Docker volumes korunur. Downtime olur.
|
||||
|
||||
### Sunucu Silme (Zorla)
|
||||
|
||||
`prevent_destroy = true` oldugu icin normal `terraform destroy` hata verir. Once `servers.tf` icindeki `lifecycle` blogunu gecici kaldir:
|
||||
|
||||
```hcl
|
||||
# lifecycle {
|
||||
# prevent_destroy = true
|
||||
# }
|
||||
```
|
||||
|
||||
Sonra:
|
||||
|
||||
```bash
|
||||
terraform destroy -target=hcloud_server.swarm["iklim-app-01"]
|
||||
```
|
||||
|
||||
Islemi tamamladiktan sonra lifecycle blogunu geri ekle.
|
||||
|
||||
### State Yonetimi
|
||||
|
||||
Simdilik local state kullanilmaktadir (`terraform.tfstate`). State dosyasi repo'ya commit edilmez. Ekipte birden fazla kisi calisiyorsa Hetzner Object Storage veya HCP Terraform remote state kullanilmalidir.
|
||||
|
||||
## Kabul Kriterleri
|
||||
|
||||
- `terraform plan` sadece prod Hetzner Project token'i ile calisir.
|
||||
|
||||
@ -1,6 +1,71 @@
|
||||
# 05 - Prod Ansible Bootstrap
|
||||
# 07 - Prod Ansible Bootstrap
|
||||
|
||||
Bu asamanin amaci Terraform ile olusturulan prod makinelerini Linux, security hardening, Docker ve Swarm acisindan hazir hale getirmektir. DB cluster yazilimi manuel kurulacaktir; bu playbook DB node'larinda sadece OS ve temel guvenlik hazirligini yapar.
|
||||
Bu aşamanın amacı Terraform ile oluşturulan prod makinelerini Linux, security hardening, Docker ve Swarm açısından hazır hale getirmektir. DB cluster yazılımı bu playbook tarafından kurulmaz; ancak DB node'ları Swarm'a worker olarak katılır.
|
||||
|
||||
## Ansible Kurulumu
|
||||
|
||||
Ansible, kontrol makinesinde (kendi bilgisayarınızda) yüklü olmalıdır. Hedef sunuculara herhangi bir ajan kurulmaz, sadece SSH erişimi yeterlidir.
|
||||
|
||||
### İşletim Sistemine Göre Kurulum
|
||||
|
||||
- **Ubuntu / Debian:**
|
||||
```bash
|
||||
sudo apt update
|
||||
sudo apt install -y pipx python3-venv
|
||||
|
||||
pipx ensurepath
|
||||
export PATH="$HOME/.local/bin:$PATH"
|
||||
|
||||
pipx install --include-deps ansible
|
||||
```
|
||||
|
||||
- **Fedora / Rocky Linux / RHEL:**
|
||||
```bash
|
||||
sudo dnf install -y pipx python3-virtualenv
|
||||
|
||||
pipx ensurepath
|
||||
export PATH="$HOME/.local/bin:$PATH"
|
||||
|
||||
pipx install --include-deps ansible
|
||||
```
|
||||
|
||||
- **macOS (Homebrew):**
|
||||
```bash
|
||||
brew install ansible
|
||||
```
|
||||
|
||||
- **Python Pip ile (Her platformda):**
|
||||
```bash
|
||||
pipx install --include-deps ansible
|
||||
```
|
||||
|
||||
### Kurulumun Doğrulanması
|
||||
|
||||
Hangi yöntemle kurarsanız kurun, kurulumun başarılı olduğunu doğrulamak için aşağıdaki komutları kullanın:
|
||||
|
||||
```bash
|
||||
# Ansible versiyonunu ve yapılandırma yollarını kontrol edin
|
||||
ansible --version
|
||||
|
||||
# Ansible binary’sinin hangi konumdan çalıştığını kontrol edin
|
||||
which -a ansible
|
||||
```
|
||||
|
||||
## Ansible Komutlarını Çalıştırma
|
||||
|
||||
Tüm komutlar projenin `ansible/` dizini altından çalıştırılmalıdır.
|
||||
|
||||
### 1. Bağlantı Testi (Ping)
|
||||
Sunuculara erişimi doğrulamak için:
|
||||
```bash
|
||||
ansible -i inventory/generated/prod.yml all -m ping
|
||||
```
|
||||
|
||||
### 2. Bootstrap Playbook'unu Çalıştırma
|
||||
Tüm rolleri (base, hardening, docker, swarm vb.) uygulamak için:
|
||||
```bash
|
||||
ansible-playbook -i inventory/generated/prod.yml playbooks/prod-bootstrap.yml --ask-vault-pass
|
||||
```
|
||||
|
||||
## Hedef Makineler
|
||||
|
||||
@ -13,18 +78,18 @@ Bu asamanin amaci Terraform ile olusturulan prod makinelerini Linux, security ha
|
||||
| `iklim-db-02` | Manuel DB cluster node |
|
||||
| `iklim-db-03` | Manuel DB cluster node |
|
||||
|
||||
## Onerilen Dosya Yapisi
|
||||
## Önerilen Dosya Yapısı
|
||||
|
||||
```text
|
||||
ansible/
|
||||
ansible.cfg
|
||||
inventory/
|
||||
generated/
|
||||
prod/
|
||||
ansible.cfg
|
||||
inventory/
|
||||
generated/
|
||||
prod.yml
|
||||
group_vars/
|
||||
all.yml
|
||||
prod.yml
|
||||
group_vars/
|
||||
all.yml
|
||||
prod.yml
|
||||
playbooks/
|
||||
prod-bootstrap.yml
|
||||
roles/
|
||||
base/
|
||||
@ -32,15 +97,16 @@ ansible/
|
||||
docker/
|
||||
swarm/
|
||||
node_dirs/
|
||||
storagebox/
|
||||
```
|
||||
|
||||
## Base Role
|
||||
|
||||
Tum prod node'larina uygulanir:
|
||||
Tüm prod node'larına uygulanır:
|
||||
|
||||
- Paket cache update
|
||||
- Temel paketler (sirasıyla kurulur):
|
||||
- `epel-release` — fail2ban ve davfs2 bu repo'dan gelir; once kurulur
|
||||
- Temel paketler (sırasıyla kurulur):
|
||||
- `epel-release` — fail2ban ve davfs2 bu repo'dan gelir; önce kurulur
|
||||
- `curl`
|
||||
- `wget`
|
||||
- `git`
|
||||
@ -48,7 +114,7 @@ Tum prod node'larina uygulanir:
|
||||
- `tar`
|
||||
- `unzip`
|
||||
- `bash-completion`
|
||||
- `gettext` — envsubst icin; CI/CD deploy pipeline'larinda gerekli
|
||||
- `gettext` — envsubst için; CI/CD deploy pipeline'larında gerekli
|
||||
- `tree`
|
||||
- `ca-certificates`
|
||||
- `fail2ban`
|
||||
@ -56,30 +122,32 @@ Tum prod node'larina uygulanir:
|
||||
- `chrony`
|
||||
- `python3`
|
||||
- `python3-pip`
|
||||
- `htop` — interaktif proses izleme (EPEL)
|
||||
- `btop` — kaynak monitörü, grafik arayüz (EPEL)
|
||||
- timezone: `Europe/Istanbul`
|
||||
- hostname ayari
|
||||
- hostname ayarı
|
||||
- chrony/NTP aktif
|
||||
|
||||
## Security Hardening Role
|
||||
|
||||
Tum prod node'larina uygulanir:
|
||||
Tüm prod node'larına uygulanır:
|
||||
|
||||
- SSH password auth kapatilir.
|
||||
- Root SSH login kapatilir.
|
||||
- Sadece SSH key auth kalir.
|
||||
- SSH password auth kapatılır.
|
||||
- Root SSH login kapatılır.
|
||||
- Sadece SSH key auth kalır.
|
||||
- `PermitEmptyPasswords no`
|
||||
- `MaxAuthTries 3`
|
||||
- `fail2ban` aktif edilir.
|
||||
- `unattended-upgrades` aktif edilir.
|
||||
- UFW default incoming deny, outgoing allow.
|
||||
- SSH sadece admin CIDR'dan acilir.
|
||||
- DB portlari public acilmaz.
|
||||
- `dnf-automatic` ile otomatik güvenlik güncelleştirmeleri aktif edilir.
|
||||
- `firewalld` default: incoming deny (drop zone), outgoing allow.
|
||||
- SSH sadece admin CIDR'dan açılır.
|
||||
- DB portları public açılmaz.
|
||||
|
||||
Hetzner Cloud Firewall asil perimeter kabul edilir. UFW host uzerinde ikinci savunma katmanidir.
|
||||
Hetzner Cloud Firewall asıl perimeter kabul edilir. firewalld host üzerinde ikinci savunma katmanıdır.
|
||||
|
||||
## Docker Role
|
||||
|
||||
Sadece `iklim-app-*` node'larinda zorunludur.
|
||||
Tüm prod node'larında (hem app hem db) zorunludur. DB node'ları Swarm Worker olarak ağa dahil olacağı için Docker Engine her makinede kurulu olmalıdır.
|
||||
|
||||
Kurulacak paketler:
|
||||
|
||||
@ -89,61 +157,60 @@ Kurulacak paketler:
|
||||
- `docker-buildx-plugin`
|
||||
- `docker-compose-plugin`
|
||||
|
||||
Kurulum resmi Docker apt repository uzerinden yapilacak. Convenience script kullanilmayacak.
|
||||
|
||||
DB node'larinda Docker zorunlu degildir. DB manuel kurulum stratejisi container tabanli olacaksa daha sonra ayri DB dokumaninda ele alinmalidir.
|
||||
Kurulum resmi Docker dnf repository üzerinden yapılacak (`https://download.docker.com/linux/rhel/docker-ce.repo`).
|
||||
|
||||
## Swarm Role
|
||||
|
||||
Prod Swarm 3 manager ile kurulacak:
|
||||
|
||||
1. `iklim-app-01` uzerinde `docker swarm init`
|
||||
2. Advertise/data path addr: `10.20.10.11`
|
||||
3. Manager join token alinir.
|
||||
4. `iklim-app-02` ve `iklim-app-03` manager olarak join olur.
|
||||
5. Overlay network olusturulur:
|
||||
- `iklimco-net`
|
||||
- driver: `overlay`
|
||||
- attachable: `true`
|
||||
6. Tum 3 node `type=service` label'i ile isaretlenir:
|
||||
```bash
|
||||
for node in iklim-app-01 iklim-app-02 iklim-app-03; do
|
||||
docker node update --label-add type=service "$node"
|
||||
done
|
||||
```
|
||||
7. Hicbir node drain edilmez. 3 node da `AVAILABILITY=Active` kalir; hem manager hem app worker olarak calisir.
|
||||
|
||||
> DB node'lari (`iklim-db-*`) Swarm'a join ettirilmez. DB cluster ayri yonetilir.
|
||||
1. `iklim-app-01` üzerinde `docker swarm init` (Advertise/data path addr: `10.20.10.11`)
|
||||
2. `iklim-app-02` ve `iklim-app-03` manager olarak join olur.
|
||||
3. `iklim-db-01/02/03` worker olarak join olur.
|
||||
4. Overlay network oluşturulur: `iklimco-net`
|
||||
5. Node etiketleri:
|
||||
- `iklim-app-*` -> `type=service`
|
||||
- `iklim-db-*` -> `role=db`
|
||||
6. Tüm node'lar `AVAILABILITY=Active` kalır.
|
||||
|
||||
## Node Directory Role
|
||||
|
||||
Tum `iklim-app-*` node'larinda:
|
||||
|
||||
Tüm `iklim-app-*` node'larında:
|
||||
```text
|
||||
/opt/iklimco
|
||||
/opt/iklimco/ssl
|
||||
/opt/iklimco/init
|
||||
/opt/iklimco/init/postgresql
|
||||
/opt/iklimco/init/mongodb
|
||||
/opt/iklimco/stacks
|
||||
```
|
||||
|
||||
DB node'larinda manuel DB kurulumu icin:
|
||||
|
||||
DB node'larında:
|
||||
```text
|
||||
/opt/iklimco
|
||||
/opt/iklimco/db
|
||||
/opt/iklimco/backup
|
||||
```
|
||||
|
||||
## StorageBox DAVFS Mount Role
|
||||
|
||||
Her node'a uygulanır (tüm `iklim-app-*` ve `iklim-db-*`).
|
||||
|
||||
### Prod Sub-Account
|
||||
|
||||
| Parametre | Değişken | Değer |
|
||||
| --- | --- | --- |
|
||||
| Ana hesap | `storagebox_account` | `u469968` |
|
||||
| Sub-account | `storagebox_user` | `u469968-sub5` |
|
||||
| WebDAV URL | `storagebox_url` | `https://u469968-sub5.your-storagebox.de/` |
|
||||
| Mount point | `storagebox_mount_point` | `/mnt/storagebox` |
|
||||
|
||||
## StorageBox SSH Key Role
|
||||
|
||||
Her node'a uygulanır. Sunucu üzerinde ed25519 SSH anahtar çifti üretilir ve StorageBox ana hesabına yüklenir.
|
||||
|
||||
## Kabul Kriterleri
|
||||
|
||||
- `ansible -i inventory/generated/prod.yml all -m ping` basarili olur.
|
||||
- 3 Swarm node `docker node ls` icinde manager olarak gorunur; hepsi `AVAILABILITY=Active`.
|
||||
- Manager quorum saglanir (3 manager, 1 kayip tolere edilir).
|
||||
- `iklimco-net` overlay network vardir.
|
||||
- `docker node inspect iklim-app-01 --format '{{.Spec.Labels}}'` ciktisi `map[type:service]` icerir.
|
||||
- DB node'lari `docker node ls` ciktisinda gorunmez.
|
||||
- `ansible -i inventory/generated/prod.yml all -m ping` başarılı olur.
|
||||
- 3 Swarm manager node `docker node ls` içinde Leader/Reachable görünür.
|
||||
- 3 DB node `docker node ls` içinde Worker olarak görünür.
|
||||
- Manager quorum sağlanır (3 manager, 1 kayıp tolere edilir).
|
||||
- `iklimco-net` overlay network vardır.
|
||||
- Node etiketleri (`type=service`, `role=db`) inspect ile doğrulanır.
|
||||
- Her node'da `/mnt/storagebox` mount edilmiştir.
|
||||
- Public firewall sadece `22`, `80`, `443` ingress'e izin verir.
|
||||
- DB node'lari public DB portu acmaz.
|
||||
- DB yazilimi kurulumu bu playbook tarafindan yapilmaz.
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
# 09 - Prod DB Cluster Kurulumu (Swarm)
|
||||
# 08 - Prod DB Cluster Kurulumu (Swarm)
|
||||
|
||||
Bu aşamanın amacı üç DB node'unu Docker Swarm'a worker olarak eklemek, MongoDB replica set ve Patroni + etcd ile yönetilen PostgreSQL yüksek erişilebilirlik konfigürasyonunu yapmaktır.
|
||||
|
||||
@ -31,9 +31,9 @@ DB container'ları birbirlerini overlay DNS adıyla değil, **Hetzner private IP
|
||||
|
||||
## 1. Firewall Güncellemesi
|
||||
|
||||
`terraform/hetzner/prod/firewall.tf` dosyasına aşağıdaki kuralları ekle.
|
||||
`terraform/hetzner/prod/firewall.tf` dosyasında aşağıdaki kuralların mevcut olduğunu doğrula; eksik varsa ekle ve `terraform apply` çalıştır.
|
||||
|
||||
`hcloud_firewall.swarm` içine (DB subnet'ten Swarm portlarına):
|
||||
`hcloud_firewall.swarm` içinde (DB subnet'ten Swarm portlarına):
|
||||
|
||||
```hcl
|
||||
rule {
|
||||
@ -69,7 +69,7 @@ rule {
|
||||
}
|
||||
```
|
||||
|
||||
`hcloud_firewall.db` içine (app subnet'ten Swarm portlarına + overlay; DB subnet içi etcd/Patroni trafiği):
|
||||
`hcloud_firewall.db` içinde (app subnet'ten Swarm portlarına + overlay; DB subnet içi etcd/Patroni trafiği):
|
||||
|
||||
```hcl
|
||||
rule {
|
||||
@ -131,6 +131,7 @@ rule {
|
||||
|
||||
```bash
|
||||
cd terraform/hetzner/prod
|
||||
terraform plan
|
||||
terraform apply
|
||||
```
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
# 06 - Prod Runner HA ve Swarm Deploy Modeli
|
||||
# 09 - Prod Runner HA ve Swarm Deploy Modeli
|
||||
|
||||
Bu asamanin amaci prod ortaminda Gitea Actions runner'lari HA calisacak sekilde kurmak ve Swarm uzerinde servislerin 3 node'a dagitilmasina uygun on kosullari tanimlamaktir.
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user