Files
ubicloud/rhizome/postgres/bin/configure
shikharbhardwaj 6f6267ce29 Configure hugepages for Postgres
This commit introduces a hugepages configuration for postgres via a
rhizome lib+bin.

At the moment, it uses the default huge page size (2M), and calculates
the number of huge pages as 25% of the total available memory. The setup
adjusts the shared_buffers accordingly to fit the shared memory within
the allocated number of hugepages.

The configuration happens as an `ExecStartPre` script added to the
existing systemd unit managed by pg_ctlcluster. To keep the semantics of
the `start` command unchanged, the hugepages script *does not* stop an
existing cluster to configure hugepages, and only does it when the
cluster is not running.

In a subsequent change, we can consider adding the boot parameters to
setup 1G hugepages for larger instances (possibly standard-30+), where
they are most useful.

[1]: https://www.postgresql.org/docs/current/kernel-resources.html#LINUX-HUGE-PAGES
2025-06-30 17:16:50 +05:30

139 lines
5.3 KiB
Ruby
Executable File

#!/bin/env ruby
# frozen_string_literal: true
require "json"
require_relative "../../common/lib/util"
require_relative "../lib/pgbouncer_setup"
if ARGV.count != 1
fail "Wrong number of arguments. Expected 1, Given #{ARGV.count}"
end
v = ARGV[0]
configure_hash = JSON.parse($stdin.read)
# Update /etc/hosts
hosts = <<-HOSTS
127.0.0.1 localhost
::1 ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
ff02::3 ip6-allhosts
#{configure_hash["hosts"]}
HOSTS
safe_write_to_file("/etc/hosts", hosts)
# Update postgresql.conf
configs = configure_hash["configs"].map { |k, v| "#{k} = #{v}" }.join("\n")
safe_write_to_file("/etc/postgresql/#{v}/main/conf.d/001-service.conf", configs)
# Update pg_hba.conf
private_subnets = configure_hash["private_subnets"].flat_map {
[
"host all all #{_1["net4"]} scram-sha-256",
"host all all #{_1["net6"]} scram-sha-256"
]
}.join("\n")
pg_hba_entries = <<-PG_HBA
# PostgreSQL Client Authentication Configuration File
# ===================================================
#
# Refer to the "Client Authentication" section in the PostgreSQL
# documentation for a complete description of this file.
# TYPE DATABASE USER ADDRESS METHOD
# Database administrative login by Unix domain socket
local all postgres peer map=system2postgres
local all pgbouncer peer map=system2pgbouncer
# Allow connections from localhost with ubi_monitoring OS user as
# ubi_monitoring database user. This will be used by postgres_exporter
# to scrape metrics and expose them to prometheus.
local all ubi_monitoring peer
# "local" is for Unix domain socket connections only
# Use SCRAM authentication for all local connections to allow pgbouncer
# passthrough to work for all non-unix users
local all all scram-sha-256
# IPv4 local connections:
host all all 127.0.0.1/32 scram-sha-256
# IPv6 local connections:
host all all ::1/128 scram-sha-256
# Allow replication connections from localhost, by a user with the
# replication privilege.
local replication all peer
host replication all 127.0.0.1/32 scram-sha-256
host replication all ::1/128 scram-sha-256
# Allow connections from private subnet with SCRAM authentication
#{private_subnets}
# Allow replication connection using special replication user for
# HA standbys
hostssl replication ubi_replication all cert map=standby2replication
# Allow connections from public internet with md5 authentication
# Note that if the password is encrypted as scram-sha-256, PostgreSQL
# still uses scram-sha-256 for authentication.
host all all all md5
PG_HBA
safe_write_to_file("/etc/postgresql/#{v}/main/pg_hba.conf", pg_hba_entries)
identity = configure_hash["identity"]
pg_ident_entries = <<-PG_IDENT
# PostgreSQL User Name Maps
# =========================
#
# Refer to the PostgreSQL documentation, chapter "Client
# Authentication" for a complete description.
# MAPNAME SYSTEM-USERNAME PG-USERNAME
system2postgres postgres postgres
system2pgbouncer postgres pgbouncer
system2postgres ubi postgres
standby2replication #{identity} ubi_replication
PG_IDENT
safe_write_to_file("/etc/postgresql/#{v}/main/pg_ident.conf", pg_ident_entries)
# Configure system hugepages
meminfo = File.read("/proc/meminfo")
hugepage_size_kib = Integer(meminfo[/^Hugepagesize:\s*(\d+)\s*kB/, 1], 10)
memory_total_kib = Integer(meminfo[/^MemTotal:\s*(\d+)\s*kB/, 1], 10)
target_hugepages_size_kib = memory_total_kib / 4
target_hugepages = target_hugepages_size_kib / hugepage_size_kib
r "echo 'vm.nr_hugepages = #{target_hugepages}' | sudo tee /etc/sysctl.d/10-hugepages.conf"
r "sync"
r "echo 3 | sudo tee /proc/sys/vm/drop_caches"
r "echo 1 | sudo tee /proc/sys/vm/compact_memory"
r "sudo sysctl --system"
meminfo = File.read("/proc/meminfo")
allocated_hugepages = Integer(meminfo[/^HugePages_Total:\s*(\d+)/, 1], 10)
if allocated_hugepages < target_hugepages
puts "Failed to allocate #{target_hugepages} hugepages. Only #{allocated_hugepages} were allocated."
exit 1
else
puts "Successfully allocated #{allocated_hugepages} hugepages."
end
# Create drop-in directory for postgresql@.service to override
# the default systemd service file with a custom ExecStartPre to configure hugepages.
r "mkdir -p /etc/systemd/system/postgresql@.service.d"
execstartpre_hugepages_conf = <<-HUGEPAGES_CONF
[Service]
ExecStartPre=/home/ubi/postgres/bin/configure-hugepages %i
HUGEPAGES_CONF
safe_write_to_file("/etc/systemd/system/postgresql@.service.d/hugepages.conf", execstartpre_hugepages_conf)
# Reload the postmaster to apply changes
r "pg_ctlcluster #{v} main reload || pg_ctlcluster #{v} main restart"
pgbouncer_setup = PgBouncerSetup.new(v, configure_hash["configs"]["max_connections"], configure_hash["pgbouncer_instances"])
pgbouncer_setup.setup