Add DB-specific StorageBox ownership variables and make the davfs mount role honor configurable uid and gid values so database containers can access mounted files. Extend the prod DB node role to sync StorageBox writes, generate and distribute the MongoDB replica set keyfile, wait for the keyfile on each node, and enforce keyfile permissions. Tune MongoDB and Patroni templates for quieter logging, correct secret variable names, local bootstrap trust, and production network pg_hba coverage. Refresh the production setup history with the current bootstrap sequence, DB stack deployment workflow, MongoDB replica set initialization, Patroni validation, and completed DB cluster status.
178 lines
5.5 KiB
Markdown
178 lines
5.5 KiB
Markdown
# Prod Ortamı Kurulum Geçmişi
|
||
|
||
Prod kurulum adımları ve mevcut yapı.
|
||
|
||
## Terraform
|
||
|
||
### Hetzner Cloud Yapılandırması
|
||
|
||
Test ve prod ayrı Hetzner Cloud projelerinde çalışır; her proje için ayrı API token kullanılır. `terraform/hetzner/prod/terraform.tfvars` içindeki `hcloud_token` değeri `iklim_prod` projesinin token'ına aittir.
|
||
|
||
Prod sunucuları `lifecycle { prevent_destroy = true }` ile korunur.
|
||
|
||
### Inventory Üretimi
|
||
|
||
```bash
|
||
cd Environment_Infrastructure/terraform/hetzner/prod
|
||
mkdir -p ../../../ansible/prod/inventory/generated
|
||
terraform output -raw ansible_inventory_yaml > ../../../ansible/prod/inventory/generated/prod.yml
|
||
```
|
||
|
||
## Ansible
|
||
|
||
### Yapılandırma Notları
|
||
|
||
`group_vars/all/vars.yml` içindeki `admin_allowed_cidrs` tüm admin IP'lerini boşlukla ayrılmış string olarak içerir ve Terraform `terraform.tfvars` ile birebir uyumludur:
|
||
|
||
```yaml
|
||
admin_allowed_cidrs: "78.187.87.109/32 95.70.151.248/32"
|
||
admin_ssh_public_key_path: "~/.ssh/id_rsa.pub"
|
||
```
|
||
|
||
Hardening rolü `PermitRootLogin prohibit-password` uygular — key tabanlı root girişi açık, parola ile root girişi kapalıdır.
|
||
|
||
`vault_iklim_password` per-host `host_vars/<hostname>/vault.yml` dosyalarında tanımlıdır, her sunucu farklı şifreye sahiptir:
|
||
|
||
```text
|
||
prod/
|
||
host_vars/
|
||
iklim-app-01/vault.yml
|
||
iklim-app-02/vault.yml
|
||
iklim-app-03/vault.yml
|
||
iklim-db-01/vault.yml
|
||
iklim-db-02/vault.yml
|
||
iklim-db-03/vault.yml
|
||
```
|
||
|
||
### StorageBox Mount
|
||
|
||
StorageBox WebDAV mount (`/mnt/storagebox`) davfs2 ile yapılır. DB node'larında `uid=999,gid=999` parametreleriyle mount edilir (PostgreSQL/MongoDB container uid'i ile uyumlu). `group_vars/db/vars.yml` içinde tanımlanır:
|
||
|
||
```yaml
|
||
storagebox_uid: "999"
|
||
storagebox_gid: "999"
|
||
```
|
||
|
||
### Bootstrap Çalıştırma Sırası
|
||
|
||
```bash
|
||
cd Environment_Infrastructure/ansible/prod
|
||
|
||
# 1. Tüm node'lar — base, hardening, docker, dizinler, storagebox
|
||
ansible-playbook prod-bootstrap.yml \
|
||
--tags base,hardening,docker,node_dirs,storagebox,storagebox_ssh_key \
|
||
--vault-password-file=../.vault_pass
|
||
|
||
# 2. Swarm kurulumu
|
||
ansible-playbook prod-bootstrap.yml \
|
||
--tags swarm \
|
||
--vault-password-file=../.vault_pass
|
||
|
||
# 3. DB node label'ları
|
||
ansible-playbook prod-bootstrap.yml \
|
||
--tags db_labels \
|
||
--vault-password-file=../.vault_pass
|
||
|
||
# 4. DB node konfigürasyonu (StorageBox dizinleri, patroni.yml, mongod.conf, keyfile)
|
||
ansible-playbook prod-bootstrap.yml \
|
||
--tags db_stack \
|
||
--limit db \
|
||
--vault-password-file=../.vault_pass
|
||
|
||
# 5. Act runner kurulumu
|
||
ansible-playbook prod-bootstrap.yml \
|
||
--tags act_runner \
|
||
--vault-password-file=../.vault_pass
|
||
```
|
||
|
||
## DB Stack Deploy
|
||
|
||
### Custom Image Build
|
||
|
||
`build/patroni-postgis/` altında PostGIS + Patroni imajı bulunur (`registry.tarla.io/iklimco/custom-patroni-postgis:18-3.6`). `ops/push-harbor-custom-images.sh` ile Harbor'a push edilir.
|
||
|
||
### Stack Deploy
|
||
|
||
```bash
|
||
# Lokal → app-01
|
||
scp ./docker-stack-* root@178.104.210.41:/home/iklim/
|
||
|
||
# app-01'de
|
||
cd /home/iklim
|
||
# password; 'https://passwords.tarla.io' içinde "tarla.io›[Hetzner] Utils Server" klasörünün altında
|
||
scp -P 23 u469968@u469968.your-storagebox.de:prod/secrets/iklim.co/.env.secrets.shared \
|
||
/tmp/.env.secrets.shared
|
||
chmod 600 /tmp/.env.secrets.shared
|
||
scp -P 23 u469968@u469968.your-storagebox.de:prod/secrets/iklim.co/.env.secrets \
|
||
/tmp/.env
|
||
chmod 600 /tmp/.env
|
||
|
||
export $(grep -v '^\s*#' /tmp/.env.secrets.shared | grep -v '^\s*$' | xargs)
|
||
export $(grep -v '^\s*#' /tmp/.env | grep -v '^\s*$' | xargs)
|
||
docker stack deploy --with-registry-auth -c docker-stack-db.prod.yml iklim-db
|
||
|
||
# deploy başarılı bir şekilde tamamlanınca
|
||
rm /tmp/.env
|
||
rm /tmp/.env.secrets.shared
|
||
history -c && history -w
|
||
```
|
||
|
||
### MongoDB Replica Set Init
|
||
|
||
```bash
|
||
ssh root@<db-01-ip>
|
||
|
||
# password; 'https://passwords.tarla.io' içinde "tarla.io›[Hetzner] Utils Server" klasörünün altında
|
||
scp -P 23 u469968@u469968.your-storagebox.de:prod/secrets/iklim.co/.env.secrets.shared \
|
||
/tmp/.env.secrets.shared
|
||
chmod 600 /tmp/.env.secrets.shared
|
||
scp -P 23 u469968@u469968.your-storagebox.de:prod/secrets/iklim.co/.env.secrets \
|
||
/tmp/.env
|
||
chmod 600 /tmp/.env
|
||
|
||
export $(grep -v '^\s*#' /tmp/.env.secrets.shared | grep -v '^\s*$' | xargs)
|
||
export $(grep -v '^\s*#' /tmp/.env | grep -v '^\s*$' | xargs)
|
||
|
||
MONGO_CID=$(docker ps --filter name=iklim-db_mongodb-01 --format "{{.ID}}" | head -1)
|
||
docker exec -it $MONGO_CID mongosh \
|
||
-u "$DATABASE_MONGODB_ROOT_USER" \
|
||
-p "$DATABASE_MONGODB_ROOT_PASSWD" \
|
||
--authenticationDatabase admin --eval '
|
||
rs.initiate({
|
||
_id: "rs0",
|
||
members: [
|
||
{ _id: 0, host: "mongodb-01:27017" },
|
||
{ _id: 1, host: "mongodb-02:27017" },
|
||
{ _id: 2, host: "mongodb-03:27017" }
|
||
]
|
||
})'
|
||
|
||
rm /tmp/.env
|
||
rm /tmp/.env.secrets.shared
|
||
history -c && history -w
|
||
```
|
||
|
||
### Patroni Cluster Doğrulama
|
||
|
||
```bash
|
||
# app-01'den
|
||
curl -s http://10.20.20.11:8008/cluster | python3 -m json.tool
|
||
```
|
||
|
||
## Mevcut Durum (2026-05-21)
|
||
|
||
| Adım | Durum |
|
||
| --- | --- |
|
||
| Terraform — 6 sunucu, ağ, firewall, floating IP | ✅ |
|
||
| Ansible base + hardening + docker + node_dirs | ✅ |
|
||
| Ansible storagebox + storagebox_ssh_key | ✅ |
|
||
| Ansible swarm (3 manager app + 3 worker db) | ✅ |
|
||
| Ansible db_labels | ✅ |
|
||
| Ansible db_stack (StorageBox DB dizinleri + config) | ✅ |
|
||
| Ansible act_runner (3 prod runner Gitea'da Idle) | ✅ |
|
||
| DB stack deploy (etcd + MongoDB + Patroni) | ✅ |
|
||
| MongoDB replica set init (rs0: 1 primary, 2 secondary) | ✅ |
|
||
| Patroni HA cluster (1 leader, 2 replica, lag=0) | ✅ |
|
||
| Ana infra stack deploy (docker-stack-infra.prod.yml) | ⏳ bekliyor |
|
||
| Deploy pipeline ilk çalışma | ⏳ bekliyor |
|