Kubernetes PostgreSQL:如何将配置文件存储在数据目录之外?

3

目前我正在尝试创建一个基于postgres:latest镜像的PostgreSQL复制部署。

配置文件默认位于数据目录/var/lib/postgresql/data中。为了使复制正常工作,我需要让数据目录为空,但这意味着我必须将配置文件保留在其他地方。

参考PostgreSQL文档

如果您希望将配置文件保留在数据目录之外,则postgres -D命令行选项或PGDATA环境变量必须指向包含配置文件的目录,并且必须在postgresql.conf(或命令行上)中设置参数以显示实际位于何处的数据目录。请注意,覆盖了-D和PGDATA的数据目录位置,但没有覆盖配置文件的位置。

在物理机器设置中,我们可以手动移动文件并在postgresql.conf文件中设置数据目录的位置。但是在Kubernetes中并不那么简单。

我尝试使用volumeMountsubPath来挂载配置文件到其他位置,然后使用command更改postgresql.conf的新位置。

示例.yaml文件:

apiVersion: v1
kind: ConfigMap
metadata:
  name: pg-replica
  labels:
    app: postgres
    name: pg-replica
data:
  POSTGRES_DB: postgres
  POSTGRES_USER: postgres
  POSTGRES_PASSWORD: mypassword
  pg_hba.conf: |
    # Contents
  postgresql.conf: |
    data_directory = /var/lib/postgresql/data/data-directory
  recovery.conf: |
    # Contents
---
apiVersion: v1
kind: Service
metadata:
  name: pg-replica
  labels:
    app: postgres
    name: pg-replica
spec:
  type: NodePort
  ports:
  - nodePort: 31000
    port: 5432
  selector:
    app: postgres
    name: pg-replica
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: pg-replica
spec:
  selector:
    matchLabels:
      app: postgres
      name: pg-replica
  replicas: 1
  template:
    metadata:
      labels:
        app: postgres
        name: pg-replica
    spec:
      containers:
        - name: pg-replica
          image: postgres:latest
          imagePullPolicy: "IfNotPresent"
          ports:
            - containerPort: 5432
          envFrom:
            - configMapRef:
                name: pg-replica
          volumeMounts:
            - name: pg-replica
              mountPath: /var/lib/postgresql/data
            - name: replica-config
              mountPath: /var/lib/postgresql/postgresql.conf
              subPath: postgresql.conf
            - name: replica-config
              mountPath: /var/lib/postgresql/pg_hba.conf
              subPath: pg_hba.conf
            - name: replica-config
              mountPath: /var/lib/postgresql/recovery.conf
              subPath: recovery.conf
          command:
            - "/bin/bash"
            - "postgres -c config_file=/var/lib/postgresql/postgresql.conf"
      volumes:
        - name: pg-replica
          persistentVolumeClaim:
            claimName: pv-replica-claim
        - name: replica-config
          configMap:
            name: pg-replica

返回结果:

返回的消息如下:

/bin/bash: postgres -c config_file=/var/lib/postgresql/postgresql.conf: 没有那个文件或目录

这个配置有什么问题?我需要采取哪些步骤使其正常工作?

编辑: 使用volumeMount字段时,尽管我用subPath指定了要挂载的确切文件,但该目录被覆盖(所有其他文件都被删除)。这可能是什么原因?

2个回答

4

在发布这个问题之后,我意识到有一些错误...

  1. 我以前使用过PostgreSQL 11进行复制,因此我认为它们的工作方式相同(当然是错误的,有一些改变)。在PostgreSQL 12中,recovery.conf被省略了,当我使用它时会出现错误消息FATAL: XX000: using recovery command file "recovery.conf" is not supported,所以我不得不将其从我的ConfigMap中删除。

  2. 我对Docker的Entrypoint & Command与Kubernetes的Command & Args产生了混淆。在被我的上级纠正之后,我知道Kubernetes的Command将覆盖Docker的Entrypoint,之后我将只需要和使用Args

以下是我对ConfigMap和Deployment做出的更改。

apiVersion: v1
kind: ConfigMap
metadata:
  name: pg-replica
  labels:
    app: postgres
    name: pg-replica
data:
  POSTGRES_DB: postgres
  POSTGRES_USER: postgres
  POSTGRES_PASSWORD: mypassword
  pg_hba.conf: |
    # Contents
  postgresql.conf: |
    data_directory = '/var/lib/postgresql/data'
    # the contents from recovery.conf are intergrated into postgresql.conf
    primary_conninfo = # host address and authentication credentials
    promote_trigger_file = # trigger file path
  extra.sh: |
    #!/bin/sh
    postgres -D /var/lib/postgresql
---
apiVersion: v1
kind: Service
metadata:
  name: pg-replica
  labels:
    app: postgres
    name: pg-replica
spec:
  type: NodePort
  ports:
  - nodePort: 31000
    port: 5432
  selector:
    app: postgres
    name: pg-replica
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: pg-replica
spec:
  selector:
    matchLabels:
      app: postgres
      name: pg-replica
  replicas: 1
  template:
    metadata:
      labels:
        app: postgres
        name: pg-replica
    spec:
      containers:
        - name: pg-replica
          image: postgres:latest
          imagePullPolicy: "IfNotPresent"
          ports:
            - containerPort: 5432
          envFrom:
            - configMapRef:
                name: pg-replica
          volumeMounts:
            - name: pg-replica
              mountPath: /var/lib/postgresql/data
            - name: replica-config
              mountPath: /var/lib/postgresql/postgresql.conf
              subPath: postgresql.conf
            - name: replica-config
              mountPath: /var/lib/postgresql/pg_hba.conf
              subPath: pg_hba.conf
            - name: replica-config
              mountPath: /docker-entrypoint-initdb.d/extra.sh
              subPath: extra.sh
          args:
            - "-c"
            - "config_file=/var/lib/postgresql/postgresql.conf"
            - "-c"
            - "hba_file=/var/lib/postgresql/pg_hba.conf"
      volumes:
        - name: pg-replica
          persistentVolumeClaim:
            claimName: pv-replica-claim
        - name: replica-config
          configMap:
            name: pg-replica

Args中的参数将设置.conf文件的位置为我指定的位置。

进行复制的进一步步骤:

  1. 在Pod启动后,我手动使用kubectl exec命令运行了pod的shell。

  2. 在第3步中(复制来自主节点的文件),我从data-directory中删除了所有文件。

rm -rf /var/lib/postgresql/data/*
  1. 使用 pg_basebackup 命令从主节点备份数据。
pg_basebackup -h <host IP> --port=<port number used> -D  /var/lib/postgresql/data -P -U replica -R -X stream

就是这样了。现在我的pg-replica pod已经成功地复制了我的主 pod。


我看到你解决了这个问题,但是你考虑使用一个Helm Chart来设置一个带有复制和高可用性的Postgres服务吗?在这里看一下。 - Mr.KoopaKiller
@KoopaKiller,感谢您提供的参考,这将在接下来的几个步骤中使用! - hs-
好的,仅供参考,因为在操作系统运行后执行这些手动步骤并不是很好。如果 Pod 挂掉,您将会失去所有所做的配置。 - Mr.KoopaKiller

1

如评论中所述,我真的鼓励您使用Postgres Helm图表来设置您的环境。

您解决问题的方式可能有效,但如果Pod由于某种原因而死亡,则您所做的所有工作都将丢失,并且您将需要重新配置所有内容。

在这里您可以找到有关如何创建具有高可用性和复制的Postgres部署的所有信息。

要安装HELM,请按照此指南进行操作。


是的,已经使用Helm Chart来完成设置。感谢提及! - hs-

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接