Role in the deployment¶
One PostgreSQL instance carries two very different workloads:
- the iRODS catalog (iCAT), which is latency-sensitive and touched by every data operation, and
- the DE service databases, which are created and migrated by Ansible.
Because both live in the same instance in a pilot, tuning is sized against the memory and cores you deliberately reserve for the database — not against the machine's total capacity. Decide that reservation first, from component inventory (the pilot reserved 22 cores and 56 GB), then compute the settings below from it.
Separating the catalog onto its own instance is the first split most sites make as they grow, because the DE and the catalog otherwise compete for the same buffer cache.
Host preparation¶
Transparent huge pages¶
PostgreSQL uses explicit huge pages; transparent huge pages cause latency spikes and have to be off.
- Append
transparent_hugepage=nevertoGRUB_CMDLINE_LINUX_DEFAULTin/etc/default/grub. - Run
update-grubto write the boot loader configuration. - Reboot for the change to take effect.
Kernel parameters¶
Persist these (/etc/sysctl.d/), do not just sysctl -w them:
| Parameter | Value |
|---|---|
vm.nr_hugepages |
0.6 × (memory_available_to_postgres_in_kiB ÷ 2048) |
vm.swappiness |
5 |
The huge pages figure reserves roughly 60% of the database's memory allocation
as 2 MiB pages, which is what shared_buffers plus overhead needs when
huge_pages = on.
Packages¶
Install postgresql, postgresql-client, and python3-psycopg2 — the last one
so Ansible's PostgreSQL modules can talk to the instance. The pilot ran
PostgreSQL 16 from the distribution packages, which puts configuration in
/etc/postgresql/16/main/.
Tuning¶
Substitute your own reservation for M (memory available to PostgreSQL, in
kiB) and C (cores available to PostgreSQL):
| Setting | Value | Why |
|---|---|---|
max_connections |
300 |
Estimated by the deployment team for the DE service set plus iRODS agents |
shared_buffers |
M ÷ 4 kB |
Conventional quarter-of-memory starting point |
huge_pages |
on |
Pairs with vm.nr_hugepages above |
work_mem |
150MB |
Starting point only; tune against real query plans |
maintenance_work_mem |
2GB |
Keeps index builds and vacuums off disk |
effective_io_concurrency |
200 |
Assumes SSD or NVMe storage |
max_worker_processes |
C |
|
max_parallel_maintenance_workers |
C |
|
max_parallel_workers_per_gather |
C |
|
max_parallel_workers |
C |
|
checkpoint_timeout |
15min |
Fewer, larger checkpoints |
max_wal_size |
4GB |
|
min_wal_size |
1GB |
|
random_page_cost |
1.1 |
Assumes SSD or NVMe storage |
effective_cache_size |
M ÷ 2 kB |
What the planner assumes the OS caches |
shared_preload_libraries |
'pg_stat_statements' |
Query-level visibility |
pg_stat_statements.max |
10000 |
|
pg_stat_statements.track |
all |
|
standard_conforming_strings |
off |
Required by the DE database |
listen_addresses |
'*' |
Needed for cluster pods and the other node |
work_mem is per sort, not per connection
With max_connections = 300, a plan with several concurrent sorts can
multiply work_mem well past what you expect. Treat 150MB as a starting
point and lower it if the instance starts swapping.
standard_conforming_strings = off
The DE database expects this off. Leaving it on causes some migrations to be
skipped; re-running the update-databases tag after fixing it picks them
up. See troubleshooting.
Restart PostgreSQL after editing postgresql.conf.
Prepare for iRODS¶
Follow the iRODS project's instructions for preparing PostgreSQL for
iRODS,1 which cover creating the catalog database, the irods
role, and its ODBC connectivity. Then create a role for the DE with a generated
password and SELECT on all tables in the catalog database — the DE reads the
catalog directly for some listings and never writes to it.
Access control¶
pg_hba.conf is edited twice, in two different phases:
- Phase 2, before the cluster exists: allow your admin host or hosts and
both deployment nodes, with method
scram-sha-256. - Phase 4, once the cluster exists: add the Kubernetes pod CIDR or CIDRs, because the DE services connect from pods:
kubectl get nodes -o jsonpath='{.items[*].spec.podCIDR}' && echo
For each distinct CIDR add:
host all all <pod-cidr> scram-sha-256
Restart PostgreSQL after each change.
Do not use trust, and prefer scram-sha-256 over md5
Older CyVerse deployment notes used md5. New deployments should use
scram-sha-256 throughout: it is the default from PostgreSQL 14 onward, and
md5 is deprecated upstream.
Databases and their owners¶
Created in phase 2, listed here because they all live in this instance:
| Database | Owner role |
|---|---|
| iCAT (name chosen at iRODS install time) | irods |
de |
de |
notifications |
de |
metadata |
de |
qms |
de |
unleash |
unleash |
grouper |
grouper |
portal |
portal_db_reader |
keycloak |
keycloak |
Merged databases
The former permissions database has been merged into the DE database. A
deployment created from current playbooks will not have a separate
permissions database, and older configuration that refers to one is stale.
Related¶
-
iRODS 4.3.3 installation guide ↩