Skip to content

修复使用 K8S 部署 PostgreSQL 时每次重启后数据丢失的问题

🏷️ Kubernetes PostgreSQL

本来挂载的卷是配置到 data 目录的:

yaml
volumeMounts:
  - mountPath: /var/lib/postgresql/data
    name: data

但是启动时报了如下错误:

initdb: error: directory "/var/lib/postgresql/data" exists but is not empty
It contains a lost+found directory, perhaps due to it being a mount point.
Using a mount point directly as the data directory is not recommended.
Create a subdirectory under the mount point.

使用 PVC 创建的卷默认会有一个 lost+found 目录,所以导致了这个错误,于是将挂载目录改成 data 目录的上一级目录。

yaml
volumeMounts:
  - mountPath: /var/lib/postgresql
    name: data

之后就可以正常启动了,但后来发现容器重启后所有的表和数据都没了。

这篇博客上说是必须将卷挂载到 data 目录。

这里要注意的是一定要映射到容器中的 /var/lib/postgresql/data 文件夹,而不是 /var/lib/postgresql

为了解决 data 目录不为空的启动异常,在部署的清单文件上添加了 initContainers 配置:

yaml
initContainers:
  - command:
      - rm
      - -fr
      - /var/lib/postgresql/data/lost+found
    image: busybox:1.32
    imagePullPolicy: IfNotPresent
    name: remove-lost-found
    resources:
      requests:
        cpu: 10m
        memory: 10Mi
    terminationMessagePath: /dev/termination-log
    terminationMessagePolicy: File
    volumeMounts:
      - mountPath: /var/lib/postgresql/data
        name: data

这里使用了 busybox 工具,在 container 创建时删除这个 lost+found 目录,这样初始化数据库时就不会报错了。

记录下完整的清单文件,以供今后参考:

yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: jiajia-postgres-deploy
  namespace: jiajia-test
spec:
  replicas: 1
  revisionHistoryLimit: 3
  selector:
    matchLabels:
      app: jiajia-postgres
  template:
    metadata:
      labels:
        app: jiajia-postgres
    spec:
      containers:
        - env:
            - name: POSTGRES_DB
              value: jiajia
            - name: POSTGRES_USER
              value: jiajia
            - name: POSTGRES_PASSWORD
              value: aPassword
            - name: TZ
              value: Asia/Shanghai
          image: postgres:13.4
          imagePullPolicy: Always
          name: jiajia-postgres
          ports:
            - containerPort: 5432
          volumeMounts:
            - mountPath: /var/lib/postgresql/data
              name: data
      initContainers:
        - command:
            - rm
            - -fr
            - /var/lib/postgresql/data/lost+found
          image: busybox:14.3
          imagePullPolicy: IfNotPresent
          name: remove-lost-found
          resources:
            requests:
              cpu: 10m
              memory: 10Mi
          terminationMessagePath: /dev/termination-log
          terminationMessagePolicy: File
          volumeMounts:
            - mountPath: /var/lib/postgresql/data
              name: data
      imagePullSecrets:
        - name: jiajia-artifacts
      volumes:
        - name: data
          persistentVolumeClaim:
            claimName: pvc-jiajia-postgres