zam@zsbahtiar:~$

cat ~/notes/postgres-shared-memory-docker-swarm.md

shared memory postgresql di docker swarm: waktu disk kosong ga ada artinya

[en]

shared memory postgresql di docker swarm: waktu disk kosong ga ada artinya

Satu query admin yg udah jalan berbulan-bulan tiba-tiba balikin HTTP 500.

PostgreSQL ngeluarin error ini:

could not resize shared memory segment "/PostgreSQL.3291219976"
to 16777216 bytes: No space left on device
SQLSTATE 53100

Disk VM masih kosong. Container database keliatan sehat. Query-nya juga bukan lagi nulis export gede.

No space left on device ternyata akurat, tapi device yg dimaksud bukan disk. Yg penuh adalah /dev/shm di dalam container.

Memory yg mana yg habis?

Request tadi ngeload satu administrative data view dan beberapa aggregate statistics. Pas query jalan, PostgreSQL butuh tambahan dynamic shared memory sebesar 16 MB. Alokasinya gagal karena /dev/shm di container terlalu kecil.

PostgreSQL bisa pakai dynamic shared memory buat parallel query execution dan kerja runtime lainnya. Sementara itu, container Docker biasanya mulai dengan POSIX shared memory filesystem yg kecil kalo ukurannya ga diatur eksplisit.

Limit ini beda dari cache database dan persistent disk:

resourcegunanya
shared_buffersbuffer cache utama PostgreSQL
/dev/shmruntime shared memory, termasuk alokasi query dinamis
/var/lib/postgresqlfile database permanen

Nilai shared_buffers yg gede ga otomatis bikin /dev/shm ikut gede. Space kosong di /var/lib/postgresql juga ga membantu.

Konfigurasi yg keliatannya benar

Percobaan pertama gw nambahin field tmpfs langsung ke service:

services:
  postgres:
    tmpfs:
      - /dev/shm:size=1g

Stack-nya deploy tanpa error yg jelas. Container yg jalan tetap punya ukuran shared memory lama.

Check yg berguna justru live service specification:

docker service inspect app_postgres \
  --format '{{json .Spec.TaskTemplate.ContainerSpec.Mounts}}' | jq

Hasilnya punya persistent database volume, tapi ga punya mount /dev/shm.

YAML-nya udah ngejelasin apa yg gw mau. Task yg hidup buktiin kalo Swarm ga menerapkannya.

Masang tmpfs di service Swarm

Buat stack ini, form yg jalan adalah entry long-form di bawah volumes:

services:
  postgres:
    image: postgres:18
    volumes:
      - postgres_data:/var/lib/postgresql
      - type: tmpfs
        target: /dev/shm
        tmpfs:
          size: 1073741824

Ukurannya pakai bytes, jadi 1073741824 sama dengan 1 GiB.

Dua mount itu punya kerjaan terpisah. postgres_data nyimpen file database walaupun task diganti. /dev/shm jadi workspace RAM-backed yg hilang bareng container.

Verifikasi dari container yg hidup

Setelah deploy stack yg benar, gw cek mount dari dalam task baru:

PG=$(docker ps -q --filter name=app_postgres | head -n1)
docker exec "$PG" df -h /dev/shm

Hasilnya:

Filesystem      Size  Used Avail Use% Mounted on
tmpfs           1.0G  1.1M  1023M   1% /dev/shm

Output itu ngekonfirmasi tiga hal:

  • Swarm udah bikin task baru
  • mount tmpfs aktif dengan ukuran yg benar
  • persistent database volume ga disentuh

Query admin jalan lagi tanpa error shared memory.

Tmpfs 1 GiB makan memory berapa?

Nilai 1g itu limit, bukan memory yg langsung direservasi saat startup. Mount-nya hampir ga makan memory di awal dan baru membesar waktu ada proses yg nulis ke sana.

Tetap aja ini memory beneran dari container dan host. Setelah limit dinaikin, penggunaan memory PostgreSQL perlu dipantau, apalagi kalo shared_buffers sama work_mem udah agresif.

Mount baru juga bikin task PostgreSQL diganti. Ada interupsi database sebentar, tapi persistent data ga ikut hilang.

Percaya ke live mount

Waktu PostgreSQL bilang No space left on device, tiga command ini jawab pertanyaan yg beda:

df -h
docker exec "$PG" df -h /dev/shm
docker service inspect app_postgres \
  --format '{{json .Spec.TaskTemplate.ContainerSpec.Mounts}}' | jq

Command pertama ngecek filesystem host. Command kedua ngecek shared memory di dalam container. Command ketiga ngecek apakah Swarm beneran masang mount yg diminta.

Disk sehat, service 1/1, dan deploy sukses bisa muncul barengan sama /dev/shm yg salah. Container yg lagi hidup tetap jadi source of truth.


← kembali ke blog