데이터베이스 사용자¶
Tenax는 각 데이터베이스를 사용자 하나, tenax로 백업하며, 이 사용자의 비밀번호는 데이터베이스 옆의 tenax-*
이름의 Secret에 저장됩니다. 관리자 계정은 절대 사용하지 않습니다. 사용자 생성에는 명령어 두 개가 필요하고, 어떤 초로든
복원하려면 서버 설정 한 줄이 더 필요합니다.
NS=team-a # the database's namespace
PASSWORD=$(openssl rand -hex 24) # hex: no quoting surprises
# 1. The Secret Tenax reads
kubectl -n $NS create secret generic tenax-postgres \
--from-literal=username=tenax --from-file=password=<(printf %s "$PASSWORD")
# 2. The user, as a superuser, through the database's pod (deploy/…, sts/… or a pod)
kubectl -n $NS exec -i deploy/postgres -- psql -U postgres -v ON_ERROR_STOP=1 <<SQL
\set tenax_password '$PASSWORD'
SELECT 'CREATE ROLE tenax LOGIN REPLICATION' WHERE NOT EXISTS (SELECT 1 FROM pg_roles WHERE rolname = 'tenax') \gexec
ALTER ROLE tenax WITH LOGIN REPLICATION PASSWORD :'tenax_password';
GRANT pg_read_all_data, pg_monitor TO tenax;
ALTER SYSTEM SET max_slot_wal_keep_size = '2GB';
SELECT pg_reload_conf();
SQL
3. 어떤 초로든 복원하려면 사용자에게 복제 권한을 주세요. 다음 줄을 pg_hba.conf에 추가하고 다시 로드합니다
(재시작 불필요).
오퍼레이터나 Helm 차트가 Postgres를 관리한다면, pg_hba를 설정하는 곳에 이 줄을 추가하세요(예: CloudNativePG의
spec.postgresql.pg_hba 또는 차트의 pgHbaConfiguration 값).
같은 SQL을 주석과 함께 담은 파일 (docs/sql/postgres-users.sql)
-- Tenax's database user for PostgreSQL 15/16/17 (run once as a superuser, e.g. with psql):
--
-- psql -v tenax_password="$TENAX_PASSWORD" -f postgres-users.sql
--
-- One user, `tenax`, does everything (ADR 0016): inventory queries, logical dumps (pg_dump), exports and checks
-- with pg_read_all_data + pg_monitor; physical base backups (pg_basebackup) and the WAL stream with REPLICATION.
--
-- For physical backups and point-in-time restore pg_hba.conf must also allow it to replicate, then reload:
-- host replication tenax all scram-sha-256
-- Without that rule Tenax still works: it takes logical backups and tells you the rule to add.
-- Also needed: wal_level = replica (the default) and max_wal_senders >= 2 (default 10).
\set ON_ERROR_STOP on
SELECT format('CREATE ROLE tenax LOGIN REPLICATION PASSWORD %L', :'tenax_password')
WHERE NOT EXISTS (SELECT 1 FROM pg_roles WHERE rolname = 'tenax') \gexec
ALTER ROLE tenax WITH LOGIN REPLICATION NOSUPERUSER NOCREATEDB NOCREATEROLE PASSWORD :'tenax_password';
GRANT pg_read_all_data, pg_monitor TO tenax;
-- Keep backup sessions bounded.
ALTER ROLE tenax SET idle_in_transaction_session_timeout = '10min';
-- A stopped streamer must never fill the database disk: cap WAL retained by replication slots (no restart needed).
ALTER SYSTEM SET max_slot_wal_keep_size = '2GB';
SELECT pg_reload_conf();
NS=team-a
PASSWORD=$(openssl rand -hex 24)
# 1. The Secret Tenax reads
kubectl -n $NS create secret generic tenax-mysql \
--from-literal=username=tenax --from-file=password=<(printf %s "$PASSWORD")
# 2. The user, as root (the official image has the root password in MYSQL_ROOT_PASSWORD)
kubectl -n $NS exec -i deploy/mysql -- sh -c 'MYSQL_PWD="$MYSQL_ROOT_PASSWORD" mysql -uroot' <<SQL
CREATE USER IF NOT EXISTS 'tenax'@'%' IDENTIFIED BY '$PASSWORD';
GRANT SELECT, SHOW VIEW, TRIGGER, EVENT, LOCK TABLES, PROCESS, RELOAD, SHOW_ROUTINE,
REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO 'tenax'@'%';
SQL
3. 어떤 초로든 복원하려면 binlog가 켜져 있고 row 형식이어야 합니다. 둘 다 MySQL 8의 기본값입니다.
select @@log_bin, @@binlog_format은 1, ROW를 표시합니다.
같은 SQL을 주석과 함께 담은 파일 (docs/sql/mysql-users.sql)
-- Tenax's database user for MySQL 8.4 (run once as root, replace the password):
--
-- mysql -uroot -p < mysql-users.sql
--
-- One user, `tenax`, does everything (ADR 0016): consistent logical dumps (mysqldump --single-transaction
-- --source-data=2), inventory and checks, and the binlog stream (mysqlbinlog --read-from-remote-server).
-- Without REPLICATION SLAVE / REPLICATION CLIENT Tenax still takes dumps, but without point-in-time restore.
--
-- Server settings (all MySQL 8 defaults except GTIDs): log_bin=ON, binlog_format=ROW, a unique server_id;
-- gtid_mode=ON with enforce_gtid_consistency=ON is recommended; binlog_expire_logs_seconds long enough for the
-- streamer to catch up after an outage (default 30 days).
CREATE USER IF NOT EXISTS 'tenax'@'%' IDENTIFIED BY 'CHANGE_ME_PASSWORD';
GRANT SELECT, SHOW VIEW, TRIGGER, EVENT, LOCK TABLES, PROCESS, RELOAD, SHOW_ROUTINE,
REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO 'tenax'@'%';
FLUSH PRIVILEGES;
이것으로 끝입니다. 대상이 Secret을 가리키도록 하세요.
3단계 없이¶
아무것도 실패하지 않습니다. Tenax는 이 사용자로 복제를 시도하고, 데이터베이스가 거부하면 다음과 같이 동작합니다.
- 전체 백업은 정책의 일정에 따라 논리 백업으로 수행됩니다.
- 대상의
Replication컨디션, 콘솔, 각 백업의 경고에 무엇을 추가해야 하는지 정확히 표시됩니다. - Tenax는 몇 분마다 다시 확인하고, 추가가 끝나면 스스로 스트리밍을 시작합니다.
| 사용자 권한 | 얻을 수 있는 것 | 권한 |
|---|---|---|
| 모든 데이터 읽기 | 논리 백업, 인벤토리, 내보내기, 검사 | Postgres pg_read_all_data + pg_monitor; MySQL SELECT, SHOW VIEW, TRIGGER, EVENT, LOCK TABLES, PROCESS, RELOAD, SHOW_ROUTINE |
| 복제 | 물리 백업(Postgres)과 변경 스트림: 어떤 초로든 복원 | Postgres REPLICATION과 pg_hba.conf 규칙; MySQL REPLICATION SLAVE, REPLICATION CLIENT |
복제 슬롯
Postgres 스트림은 Tenax가 WAL을 저장할 때까지 복제 슬롯에 보관합니다. SQL은 멈춘 streamer가 보관할 수 있는 양을
2 GB로 제한하며(max_slot_wal_keep_size), Tenax는 그보다 훨씬 전에 TenaxSlotWALRetentionHigh 알림을 보냅니다.
대상이 삭제되거나 특정 시점 복원이 꺼지면 슬롯을 삭제합니다.
고급: 비밀번호가 교체되고 데이터베이스가 다시 만들어지는 GitOps 환경이라면 사용자를 자동으로 동기화하세요.