深入分析Spilo项目的组成以及工作原理。

Spilo

Postgres-Operator根据自定义的CRD,在Kubernetes中运行Spilo镜像。

1.容器运行环境

当运行基础配置的postgresql实例时,Spilo镜像运行时包含以下内容。

环境变量:

Name Value 说明
SCOPE rccp-tiny postgresql 集群的实例名称
PGVERSION 11
PGROOT /home/postgres/pgdata/pgroot
POD_IP status.podIP
POD_NAMESPACE metadata.namespace
PGUSER_SUPERUSER postgres
PGPASSWORD_SUPERUSER Secret的password字段
PGUSER_STANDBY standby
PGPASSWORD_STANDBY Secret的password字段
PAM_OAUTH2 无论是否配置了PAM,默认情况下都会注入一个URL
KUBERNETES_LABELS {“application”:“spilo”}
KUBERNETES_SCOPE_LABEL cluster-name
KUBERNETES_ROLE_LABEL spilo-role
HUMAN_ROLE zalandos
DCS_ENABLE_KUBERNETES_API value true
SPILO_CONFIGURATION

SPILO_CONFIGURATION环境变量的内容:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
{
    "postgresql": {},
    "bootstrap": {
        "initdb": [
            {
                "auth-host": "md5"
            },
            {
                "auth-local": "trust"
            }
        ],
        "users": {
            "zalandos": {
                "password": "",
                "options": [
                    "CREATEDB",
                    "NOLOGIN"
                ]
            }
        },
        "dcs": {}
    }
}

挂载的目录:

Mount 类型 说明
/home/postgres/pgdata PVC 数据库目录
/dev/shm Memory 内存临时盘

2.容器内脚本脚本

Spilo容器包含以下脚本:

文件名 说名
/launch.sh 容器的启动脚本
/etc/runit/runsvdir/default/ runit的默认配置文件:包括etcd、patroni、pgbouncer、pqgd
/scripts 该目录下的依赖,包括:shell、SQL、Python3的脚本

1. launch.sh

/launch.sh 是镜像的启动脚本,运行时启动命令如下:

1
CMD ["/bin/sh", "/launch.sh", "init"]

launch.sh 相关逻辑参考Gist:https://gist.github.com/QQGoblin/4536f34959d81884ab2794dee95e46e6

2. configure_spilo.py

configure_spilo.py 脚本的主要工作:生成对应模块的配置配置文件,以下列表列出了所有模块的生成配置文件

模块名称 配置文件 Runit 触发配置的ENV 备注
patroni /run/ postgres.yml patroni 基础配置 不可省略
certificate /run/certs 基础配置 不可省略
pgqd /home/postgres/pgq_ticker.ini pgqd 基础配置 ???
log /run/etc/log.d/env/ LOG_S3_BUCKET 可省略
crontab /run/cron crontab USE_WALE
USE_WALE
LOG_S3_BUCKET
拥有SYS_NICE权限
可省略
pam-oauth2 /etc/pam.d/postgresql 基础配置 可省略
pgbouncer /run/pgbouncer pgbouncer PGBOUNCER_CONFIGURATION
bootstrap /run/etc/wal-e.d/env CLONE_WITH_WALE
CLONE_WITH_BASEBACKUP
CLONE、备份相关
依赖wal-e
wal-e /run/etc/wal-e.d/env USE_WALE CLONE、备份相关
依赖wal-e
standby-cluster /run/etc/wal-e.d/env STANDBY_WITH_WALE CLONE、备份相关
依赖wal-e

3. Runit服务

1.Crontab

configure_spilo.py 会在特定条件下触发以下三个crontab任务,但是都不是必须

Crontab脚本 触发条件 作用
/scripts/renice.sh 容器具备SYS_NICE权限 调整checkpointer、archiver、startup、walsender、walreceiver进程的优先级
/scripts/test_reload_ssl.sh SSL_TEST_RELOAD 检查SSL证书是否变更,如果证书变更执行 pg_ctl reload
/scripts/postgres_backup.sh USE_WALE 定时生成基础BACKUP
/scripts/upload_pg_log_to_s3.py LOG_S3_BUCKET 上传日志文件到S3

2. Etcd

容器内启动单机etcd

3.pgbouncer

启动pgbouncer进程,启动命令/usr/bin/pgbouncer /run/pgbouncer/pgbouncer.ini

4. patroni

启动patroni服务,启动命令patroni /home/postgres/postgres.yml

启动前脚本会清理觉大部分环境变量,因此通过注入环境变量的方式修改patroni参数可能存在问题

1
2
3
for E in $(printenv -0 | tr '\n' ' ' | sed 's/\x00/\n/g' | grep -vE '^(KUBERNETES_(SERVICE|PORT|ROLE)[_=]|((POD_(IP|NAMESPACE))|HOSTNAME|PATH|PGHOME|LC_ALL|ENABLE_PG_MON)=)' | sed 's/=.*//g'); do
    unset $E
done

5.PGQD

PGQD 服务中执行以下命令:

1
env -i PGAPPNAME="pgq ticker" /scripts/patroni_wait.sh --role master -- /usr/bin/pgqd /home/postgres/pgq_ticker.ini

由于/scripts/patroni_wait.sh --role master脚本的作用,实际上只有Master节点会真正执行启动pgqd进程,Standby节点会没60秒检查自己是否成为了Master,如果是就执行/usr/bin/pgqd /home/postgres/pgq_ticker.ini。