feat(infra): Refactor Swarm networking for reliable DNS and stack ownership

Moves `iklimco-net` overlay network creation to be managed by the Docker Swarm stack, ensuring reliable embedded DNS resolution for inter-service communication. This resolves issues where services on external overlay networks failed to discover each other via Docker DNS.

This refactoring includes:
*   Removing the manual `iklimco-net` creation from the Ansible `swarm` role.
*   Adjusting `act_runner` configuration to connect job containers to `iklimco-net` only after the stack has deployed and created the network.
*   Setting `storagebox_file_mode` to `0600` for DB nodes to prevent "too open" errors with MongoDB keyfiles.
*   Provisioning dedicated bind mount directories for MongoDB and PostgreSQL on DB nodes with correct ownership and permissions.
*   Updating documentation to reflect the consolidated stack and network changes.
This commit is contained in:
Murat ÖZDEMİR 2026-05-26 01:08:12 +03:00
parent 6798426841
commit 51933afea6
6 changed files with 45 additions and 17 deletions

View File

@ -312,7 +312,7 @@ Ana playbook: `prod-bootstrap.yml`
| `node_dirs` | `node_dirs` | `all` | Node dizinleri (`/opt/iklimco/...`) | | `node_dirs` | `node_dirs` | `all` | Node dizinleri (`/opt/iklimco/...`) |
| `storagebox` | `storagebox` | `all` | WebDAV mount ve yönetilen dizinlerin oluşturulması | | `storagebox` | `storagebox` | `all` | WebDAV mount ve yönetilen dizinlerin oluşturulması |
| `storagebox_ssh_key` | `storagebox_ssh_key` | `all` | StorageBox SSH key üretimi | | `storagebox_ssh_key` | `storagebox_ssh_key` | `all` | StorageBox SSH key üretimi |
| `swarm` | `swarm` | `app`, `db` | Swarm init/join, overlay ağ, node label'ları | | `swarm` | `swarm` | `app`, `db` | Swarm init/join, `iklimco-net` overlay ağı (MTU=1400), node label'ları |
| `db_labels` | inline task | `iklim-app-01` | DB node'larına `role=db` ve `db-index=01/02/03` label'ı ekler | | `db_labels` | inline task | `iklim-app-01` | DB node'larına `role=db` ve `db-index=01/02/03` label'ı ekler |
| `db_stack` | `db_stack` | `db` | StorageBox'ta MongoDB ve PostgreSQL config dizinleri | | `db_stack` | `db_stack` | `db` | StorageBox'ta MongoDB ve PostgreSQL config dizinleri |
| `act_runner` | `act_runner` | `app` | Gitea Actions runner kurulumu ve kaydı | | `act_runner` | `act_runner` | `app` | Gitea Actions runner kurulumu ve kaydı |

View File

@ -1,6 +1,7 @@
# DB node'larında StorageBox uid/gid=999 (mongodb ve postgres container user) # DB node'larında StorageBox uid/gid=999 (mongodb ve postgres container user)
# davfs2 dosyaları uid 999 sahibi gösterir; container içi erişim açılır. # davfs2 dosyaları uid 999 sahibi gösterir; container içi erişim açılır.
# file_mode=0600: MongoDB keyfile "too open" hatasını engeller (0666 reddedilir).
storagebox_dir_mode: "0777" storagebox_dir_mode: "0777"
storagebox_file_mode: "0666" storagebox_file_mode: "0600"
storagebox_uid: "999" storagebox_uid: "999"
storagebox_gid: "999" storagebox_gid: "999"

View File

@ -21,9 +21,9 @@ cache:
external_server: "" external_server: ""
container: container:
# Job container'ları iklimco-net overlay network'üne katılır; # Job containers start on bridge. The deploy workflow connects them to iklimco-net
# böylece iklim-db_postgresql ve iklim-db_mongodb servislerine direkt erişebilir. # after the stack is deployed (so iklimco-net exists before the runner tries to use it).
network: "iklimco-net" network: "bridge"
enable_ipv6: false enable_ipv6: false
privileged: false privileged: false
options: "-v /mnt/storagebox:/mnt/storagebox" options: "-v /mnt/storagebox:/mnt/storagebox"

View File

@ -15,6 +15,18 @@
- /opt/iklimco/backup - /opt/iklimco/backup
when: inventory_hostname in groups['db'] when: inventory_hostname in groups['db']
- name: Create db data directories (bind mounts for MongoDB and PostgreSQL)
ansible.builtin.file:
path: "{{ item }}"
state: directory
owner: "999"
group: "999"
mode: '0700'
loop:
- /opt/iklimco/db/mongodb
- /opt/iklimco/db/postgresql
when: inventory_hostname in groups['db']
- name: Create service node directories - name: Create service node directories
ansible.builtin.file: ansible.builtin.file:
path: "{{ item }}" path: "{{ item }}"

View File

@ -52,17 +52,9 @@
- inventory_hostname in groups['db'] - inventory_hostname in groups['db']
- swarm_status.stdout != 'active' - swarm_status.stdout != 'active'
# 5. Overlay Network oluşturulması (Sadece bir kez Leader üzerinden) # 5. Node Etiketleri (Labels)
- name: Create iklimco-net overlay network # iklimco-net overlay network is created and owned by the Swarm stack (docker-stac-infra_db-prod.yml).
community.docker.docker_network: # Stack-owned networks get full Docker DNS (service VIPs, aliases). No manual creation needed.
name: iklimco-net
driver: overlay
attachable: yes
state: present
delegate_to: "{{ groups['app'][0] }}"
run_once: true
# 6. Node Etiketleri (Labels)
- name: Label App nodes (service) - name: Label App nodes (service)
ansible.builtin.shell: docker node update --label-add type=service {{ inventory_hostname }} ansible.builtin.shell: docker node update --label-add type=service {{ inventory_hostname }}
delegate_to: "{{ groups['app'][0] }}" delegate_to: "{{ groups['app'][0] }}"

View File

@ -260,5 +260,28 @@ curl -s http://10.20.20.11:8008/cluster | python3 -m json.tool
| DB stack deploy (etcd + MongoDB + Patroni) | ✅ | | DB stack deploy (etcd + MongoDB + Patroni) | ✅ |
| MongoDB replica set init (rs0: 1 primary, 2 secondary) | ✅ | | MongoDB replica set init (rs0: 1 primary, 2 secondary) | ✅ |
| Patroni HA cluster (1 leader, 2 replica, lag=0) | ✅ | | Patroni HA cluster (1 leader, 2 replica, lag=0) | ✅ |
| Ana infra stack deploy (docker-stack-infra.prod.yml) | ⏳ bekliyor | | Ana infra stack deploy (docker-stac-infra_db-prod.yml) | ⏳ bekliyor |
| MongoDB rs.initiate (ilk deploy sonrası elle) | ⏳ bekliyor |
| Deploy pipeline ilk çalışma | ⏳ bekliyor | | Deploy pipeline ilk çalışma | ⏳ bekliyor |
## Önemli Mimari Notlar
### Tek Stack Yaklaşımı (2026-05-26)
`docker-stack-infra-prod.yml` ve `docker-stack-db-prod.yml` tek dosyada birleştirildi: `docker-stac-infra_db-prod.yml`. Her iki dosya da aynı `iklimco` stack adına deploy edildiğinden servis isimleri değişmedi.
**Neden birleştirildi:** External overlay network'lerde Docker embedded DNS hiçbir entry kaydetmez (servis VIP'leri, alias'lar dahil). Stack-owned network'te Docker DNS tam çalışır — vault `retry_join`, etcd alias'ları ve tüm servis discovery sorunları çözüldü.
**Network:** `iklimco-net` artık stack tarafından oluşturulur (MTU=1400, attachable). Ansible `swarm` rolündeki network oluşturma task'ı kaldırıldı.
**MongoDB rs.initiate:** İlk deploy sonrası `rs.initiate` elle verilmeli (DB Stack Deploy bölümüne bakınız).
**Network silinirse:** Stack'i yeniden deploy et — `docker stack deploy -c docker-stac-infra_db-prod.yml iklimco`
### Vault retry_join (2026-05-25)
`retry_join.leader_api_addr` olarak `iklimco_vault` (Swarm servis adı) kullanılır. Stack-owned network sayesinde Docker DNS bu VIP'i kayıt eder. `leader_tls_server_name: vault.iklim.co` ile `*.iklim.co` sertifikası TLS doğrulamasını geçer.
### Runner / iklimco-net (2026-05-26)
Act runner config'de `container.network: "bridge"` kullanılır (önceki `iklimco-net`). Workflow'da "Connect Runner to Overlay Network" adımı "Deploy Swarm Stacks" sonrasına taşındı — böylece stack'in oluşturduğu `iklimco-net`'e runner job container bağlanabilir.