You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Patroni Helm Chart自动创建数据库Schema时root角色不存在错误排查

解决Patroni Helm Chart自动创建数据库Schema的问题

你遇到的核心问题有两个:一是Patroni容器不会自动执行/docker-entrypoint-initdb.d/下的脚本(因为Patroni的启动流程和原生Postgres容器逻辑不同),二是手动执行时用root用户没有对应的Postgres数据库角色权限。下面是针对性的解决方案:

为什么脚本没自动执行?

原生Postgres容器的entrypoint会在数据库第一次初始化时扫描/docker-entrypoint-initdb.d/目录并执行脚本,但Patroni是通过自身进程管理Postgres实例的,它有独立的初始化逻辑,不会触发这个目录的脚本执行。

解决方案1:利用Patroni的post_init钩子(推荐)

Patroni原生支持在Postgres实例初始化完成后执行自定义脚本,这是最贴合Patroni架构的实现方式:

  1. 更新你的ConfigMap,添加Patroni配置和初始化脚本:
kind: ConfigMap
apiVersion: v1
metadata:
  name: {{ template "patroni.fullname" . }}
  labels:
    app: {{ template "patroni.fullname" . }}
    release: {{ .Release.Name }}
data:
  patroni.yml: |
    # 保留你原有的Patroni配置,新增post_init部分
    post_init:
      - command: ["psql", "-U", "postgres", "-f", "/mnt/init.sql"]
        timeout: 300
  init.sql: |-
    -- 替换为你的Schema创建语句,示例:
    CREATE SCHEMA IF NOT EXISTS my_app_schema;
    CREATE TABLE IF NOT EXISTS my_app_schema.user_info (
      id SERIAL PRIMARY KEY,
      username VARCHAR(50) NOT NULL UNIQUE,
      created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
    );
  1. 在StatefulSet的volumeMounts中添加ConfigMap挂载,将init.sql映射到容器内的/mnt/init.sql
volumeMounts:
  - mountPath: /mnt/init.sql
    name: patroni-config
    subPath: init.sql
  # 保留你原有的其他volumeMounts配置
volumes:
  - name: patroni-config
    configMap:
      name: {{ template "patroni.fullname" . }}

这样,当Patroni完成Postgres实例初始化时,会自动以postgres用户执行你的Schema创建脚本,无需手动干预。

解决方案2:自定义Supervisord进程执行初始化脚本

如果你的Helm Chart不支持直接修改Patroni配置,也可以通过新增Supervisord进程来实现初始化逻辑,确保只执行一次且用正确的用户:

  1. 扩展你的ConfigMap,添加一个启动控制脚本:
data:
  init-schema.sh: |
    #!/bin/bash
    # 标记文件,避免重复执行初始化
    MARKER_FILE="/var/lib/postgresql/data/.schema_initialized"
    
    if [ ! -f "$MARKER_FILE" ]; then
      # 等待Postgres服务启动完成
      until psql -U postgres -c "SELECT 1" > /dev/null 2>&1; do
        echo "Waiting for Postgres to become available..."
        sleep 2
      done
      
      # 执行Schema创建脚本
      echo "Running schema initialization..."
      psql -U postgres -f /docker-entrypoint-initdb.d/init.sql
      
      # 创建标记文件
      touch "$MARKER_FILE"
      echo "Schema initialization completed."
    fi
    
    # 保持进程运行(Supervisord需要进程持续存活)
    tail -f /dev/null
  init.sql: |-
    **DB SCHEMA TO BE CREATED**
  1. 在StatefulSet中挂载脚本并赋予执行权限:
volumeMounts:
  - mountPath: /docker-entrypoint-initdb.d/
    name: patroni-config
  - mountPath: /opt/init-schema.sh
    name: patroni-config
    subPath: init-schema.sh
volumes:
  - name: patroni-config
    configMap:
      name: {{ template "patroni.fullname" . }}
      defaultMode: 0755 # 确保脚本有执行权限
  1. 修改Supervisord配置,新增一个初始化进程:
# 在你的Supervisord配置中添加以下内容
[program:init-schema]
command=/bin/bash /opt/init-schema.sh
user=postgres
autostart=true
autorestart=false
startretries=3
stdout_logfile=/var/log/supervisor/init-schema.log
stderr_logfile=/var/log/supervisor/init-schema.err

这个进程会在Pod启动时以postgres用户运行,等待Postgres可用后执行脚本,并通过标记文件避免每次重启重复执行。

手动执行的正确方式(用于测试)

如果需要手动验证脚本,一定要切换到postgres用户执行,不要用root:

# 直接在外部执行
oc exec -it postgres-ha-test-patroni-0 -- su - postgres -c "psql -f /docker-entrypoint-initdb.d/init.sql"

# 或者进入容器后切换用户
oc exec -it postgres-ha-test-patroni-0 bash
su - postgres
psql -f /docker-entrypoint-initdb.d/init.sql

内容的提问来源于stack exchange,提问作者Apurva

火山引擎 最新活动