- Documented infrastructure changes for Redis Sentinel and RabbitMQ clustering. - Updated setup guides for Terraform, Ansible, and Swarm node recovery. - Clarified APISIX rate limit policy and degradation settings.
298 lines
8.8 KiB
Markdown
298 lines
8.8 KiB
Markdown
# 07 - Prod Ansible Bootstrap
|
||
|
||
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
|
||
```
|
||
|
||
### Ek Python Bağımlılıkları
|
||
|
||
`password_hash` filtresi için `passlib` kontrol makinesinde gereklidir:
|
||
|
||
```bash
|
||
pipx inject ansible passlib
|
||
```
|
||
|
||
> `pip` ile kurduysanız: `pip install passlib`
|
||
|
||
### 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 `ansible/prod/` dizininden çalıştırılmalıdır. `ansible.cfg` inventory ve roles_path'i otomatik olarak tanımlar.
|
||
|
||
### 0. Gerekli Collection'ları Kur (İlk kurulumda bir kez)
|
||
|
||
```bash
|
||
ansible-galaxy collection install -r ../requirements.yml
|
||
```
|
||
|
||
### 1. Bağlantı Testi (Ping)
|
||
|
||
```bash
|
||
ansible all -m ping
|
||
```
|
||
|
||
### 2. Bootstrap Playbook'unu Çalıştırma
|
||
|
||
```bash
|
||
ansible-playbook prod-bootstrap.yml --ask-vault-pass
|
||
```
|
||
|
||
*Not: `--ask-vault-pass` parametresi Ansible Vault parolasını sorar; StorageBox şifresi bu şekilde çözülür.*
|
||
|
||
### 3. Sadece Belirli Bir Rolü Çalıştırma (Tags)
|
||
|
||
```bash
|
||
ansible-playbook prod-bootstrap.yml --tags "hardening" --ask-vault-pass
|
||
```
|
||
|
||
## Hedef Makineler
|
||
|
||
| Host | Rol |
|
||
| --- | --- |
|
||
| `iklim-app-01` | Swarm manager + app worker |
|
||
| `iklim-app-02` | Swarm manager + app worker |
|
||
| `iklim-app-03` | Swarm manager + app worker |
|
||
| `iklim-db-01` | Manuel DB cluster node |
|
||
| `iklim-db-02` | Manuel DB cluster node |
|
||
| `iklim-db-03` | Manuel DB cluster node |
|
||
|
||
## Önerilen Dosya Yapısı
|
||
|
||
```text
|
||
ansible/
|
||
prod/
|
||
ansible.cfg
|
||
inventory/
|
||
generated/
|
||
prod.yml
|
||
group_vars/
|
||
all/
|
||
vars.yml
|
||
vault.yml
|
||
prod-bootstrap.yml
|
||
roles/
|
||
base/
|
||
hardening/
|
||
docker/
|
||
swarm/
|
||
node_dirs/
|
||
storagebox/
|
||
storagebox_ssh_key/
|
||
act_runner/
|
||
db_stack/
|
||
```
|
||
|
||
## Base Role
|
||
|
||
Tüm prod node'larına uygulanır:
|
||
|
||
- Paket cache update
|
||
- `epel-release` — ayrı task olarak önce kurulur; `fail2ban`, `davfs2`, `htop`, `btop` bu repoya bağımlı
|
||
- temel paketler (`epel-release` aktif olduktan sonra):
|
||
- `curl`
|
||
- `wget`
|
||
- `git`
|
||
- `jq`
|
||
- `tar`
|
||
- `unzip`
|
||
- `bash-completion`
|
||
- `gettext` — envsubst için; CI/CD deploy pipeline'larında gerekli
|
||
- `tree`
|
||
- `ca-certificates`
|
||
- `fail2ban`
|
||
- `chrony`
|
||
- `python3`
|
||
- `python3-pip`
|
||
- `python3-passlib` — `password_hash` filtresi için (EPEL)
|
||
- `htop` — interaktif proses izleme (EPEL)
|
||
- `btop` — kaynak monitörü, grafik arayüz (EPEL)
|
||
- timezone: `Europe/Istanbul`
|
||
- hostname ayarı
|
||
- klavye düzeni: `trq` (Türkçe Q)
|
||
- chrony/NTP aktif
|
||
|
||
## Security Hardening Role
|
||
|
||
Tüm prod node'larına uygulanır:
|
||
|
||
- 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.
|
||
- `dnf-automatic` ile otomatik güvenlik güncelleştirmeleri aktif edilir.
|
||
- `iklim` sistem kullanıcısı oluşturulur; `wheel` grubuna eklenir (şifre vault'tan alınır).
|
||
- `firewalld` default: incoming deny (drop zone), outgoing allow.
|
||
- SSH kuralı önce `drop` zone'a rich rule olarak yazılır, ardından default zone `drop` yapılır.
|
||
- SSH sadece admin CIDR'dan açılır.
|
||
- DB portları public açılmaz.
|
||
|
||
Hetzner Cloud Firewall asıl perimeter kabul edilir. firewalld host üzerinde ikinci savunma katmanıdır.
|
||
|
||
## Docker Role
|
||
|
||
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:
|
||
|
||
- `docker-ce`
|
||
- `docker-ce-cli`
|
||
- `containerd.io`
|
||
- `docker-buildx-plugin`
|
||
- `docker-compose-plugin`
|
||
|
||
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` ü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`, `db-index=01/02/03` (Patroni node koordinasyonu için)
|
||
6. Tüm node'lar `AVAILABILITY=Active` kalır.
|
||
|
||
`db-index` etiketleri prod-bootstrap.yml içinde ayrı bir play ile `iklim-app-01` üzerinden eklenir (swarm role tarafından değil).
|
||
|
||
## Node Directory Role
|
||
|
||
Tüm `iklim-app-*` node'larında:
|
||
```text
|
||
/opt/iklimco/ssl
|
||
/opt/iklimco/init
|
||
/opt/iklimco/stacks
|
||
```
|
||
|
||
DB node'larında:
|
||
```text
|
||
/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 `/root/.ssh/id_ed25519_storagebox` ed25519 anahtar çifti üretilir. Üretilen public key'in StorageBox ana hesabına yüklenmesi (SSH authorized_keys) ayrı bir manuel adımdır:
|
||
|
||
```bash
|
||
# Her node için:
|
||
cat /root/.ssh/id_ed25519_storagebox.pub | \
|
||
ssh -p 23 STORAGEBOX_USER@STORAGEBOX_USER.your-storagebox.de \
|
||
"cat >> .ssh/authorized_keys"
|
||
```
|
||
|
||
## Act Runner Role
|
||
|
||
`iklim-app-*` node'larına uygulanır. Her app node'a Gitea Act Runner kurulur ve systemd servisi olarak başlatılır. Prod ortamında 3 app node üzerinde runner çalışır; deploy pipeline bu runner'lardan herhangi birinde tetiklenebilir.
|
||
|
||
## DB Stack Role
|
||
|
||
`iklim-db-*` node'larına uygulanır. MongoDB için `/opt/iklimco/db/mongodb/config/` dizinini ve `mongod.conf` dosyasını oluşturur. `group_vars/prod.yml` içinde tanımlı `mongodb_replset_name: "rs0"` değişkeniyle `mongod.conf` replicaSet ve keyFile bloklarını otomatik içerir.
|
||
|
||
## /opt/iklimco/stacks/.env
|
||
|
||
DB cluster stack'lerinin gerektirdiği şifre değişkenleri `/opt/iklimco/stacks/.env` dosyasında saklanır. Bu dosya StorageBox'ta `prod/secrets/iklim.co/.env.stacks` olarak tutulur. İlk deploy öncesinde `iklim-app-01` üzerinde aşağıdaki komutla çekilir:
|
||
|
||
```bash
|
||
scp -P 23 STORAGEBOX_USER@STORAGEBOX_USER.your-storagebox.de:prod/secrets/iklim.co/.env.stacks \
|
||
/opt/iklimco/stacks/.env
|
||
chmod 600 /opt/iklimco/stacks/.env
|
||
```
|
||
|
||
## Swarm Kurulum Doğrulaması
|
||
|
||
Bootstrap sonrası aşağıdaki komutlarla Swarm durumu kontrol edilir:
|
||
|
||
```bash
|
||
# 6 node: 3 manager (Leader/Reachable), 3 worker (Ready)
|
||
docker node ls
|
||
|
||
# App node etiketi
|
||
docker node inspect iklim-app-01 --format '{{.Spec.Labels}}'
|
||
# Beklenen: map[type:service]
|
||
|
||
# DB node etiketi
|
||
docker node inspect iklim-db-01 --format '{{.Spec.Labels}}'
|
||
# Beklenen: map[db-index:01 role:db]
|
||
|
||
# swarm-init.sh idempotency — zaten aktif Swarm'da tekrar init denemez
|
||
grep -n "swarm init\|swarm join" init/swarm-init.sh
|
||
```
|
||
|
||
## Kabul Kriterleri
|
||
|
||
- `ansible 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`, `db-index=01/02/03`) inspect ile doğrulanır.
|
||
- `swarm-init.sh` aktif Swarm'da tekrar init denemez (idempotent).
|
||
- Her node'da `/mnt/storagebox` mount edilmiştir.
|
||
- Her app node'da Gitea Act Runner servisi çalışmaktadır.
|
||
- DB node'larında `/opt/iklimco/db/mongodb/config/mongod.conf` oluşturulmuştur ve `replSetName: rs0` içermektedir.
|
||
- Public firewall sadece `22`, `80`, `443` ingress'e izin verir.
|