无法使k8上的Postgresql数据持久化

htrmnn0y  于 2023-01-25  发布在  PostgreSQL
关注(0)|答案(1)|浏览(122)

我正在kubernetes上构建postgresql,但我无法持久化postgres数据。主机是Ubuntu-20. 4的GCP示例。磁盘卷使用GCP卷,这些卷在连接到示例后安装。

Filesystem      1K-blocks    Used Available Use% Mounted on
/dev/root         9982728 4252592   5713752  43% /
devtmpfs          4038244       0   4038244   0% /dev
tmpfs             4059524       0   4059524   0% /dev/shm
tmpfs              811908    1568    810340   1% /run
tmpfs                5120       0      5120   0% /run/lock
tmpfs             4059524       0   4059524   0% /sys/fs/cgroup
/dev/loop0          50304   50304         0 100% /snap/core18/2671
/dev/loop2         217856  217856         0 100% /snap/google-cloud-cli/98
/dev/loop3          94208   94208         0 100% /snap/lxd/24065
/dev/loop1          60544   60544         0 100% /snap/core20/1782
/dev/loop4          44032   44032         0 100% /snap/snapd/17885
/dev/nvme0n1p15     99801    6004     93797   7% /boot/efi
tmpfs              811904       0    811904   0% /run/user/1001
shm                 65536       0     65536   0% /run/containerd/io.containerd.grpc.v1.cri/sandboxes/49ebcf7b449f4b13d52aab6f52c28f139c551f83070f6f21207dbf52315dc264/shm
shm                 65536       0     65536   0% /run/containerd/io.containerd.grpc.v1.cri/sandboxes/e46f0c6b19e5ccff9bb51fa3f7669a9a6a2e7cfccf54681e316a9cd58183dce4/shm
shm                 65536       0     65536   0% /run/containerd/io.containerd.grpc.v1.cri/sandboxes/495c80e87521bfdda55827df64cdb84cddad149fb502ac7ee12f3607badd4649/shm
shm                 65536       0     65536   0% /run/containerd/io.containerd.grpc.v1.cri/sandboxes/443e7b254d02c88873c59edc6d5b0a71e80da382ea81105e8b312ad4122d694a/shm
/dev/nvme0n3     10218772      12   9678088   1% /var/lib/postgresql ※ disk for postgres
/dev/nvme0n2      3021608      24   2847916   1% /var/lib/pgadmin ※ disk for pgadmin
shm                 65536    1052     64484   2% /run/containerd/io.containerd.grpc.v1.cri/sandboxes/bd83982e91b6a3bce7853416d72878d5473174e884c15578c47a8d8952f4e718/shm

此外,还使用持久卷和持久卷声明分配Pod卷。
x一个一个一个一个x一个一个二个x
但是,当pod被删除时,postgres数据也随之消失,我可以确认它不是持久的。
如果你知道这个问题的原因,请让我知道。提前感谢你。
以下各项均不起作用

  • 对Pod卷使用主机路径
  • 使用默认PGDATA
mnowg1ta

mnowg1ta1#

您的问题的根源在这里:

volumeMounts:
  - name: postgredb
    mountPath: /var/lib/postgresql

postgres映像本身在/var/lib/postgresql/data上挂载了一个卷。如果我们检查该映像,可以看到:

$ docker image inspect docker.io/postgres:14 | jq '.[0].ContainerConfig.Volumes'
{
  "/var/lib/postgresql/data": {}
}

您在/var/lib/postgresql上的挂载实际上是一个空操作,每次容器启动时都会在/var/lib/postgresql/data上创建一个临时卷,由于这是默认的PGDATA位置,因此当容器退出时,您的数据实际上会被丢弃。
我在本地环境中创建了一个示例来演示这种行为,并对您的示例做了一些小的更改,这些更改不会对操作产生任何影响。
我用postgres凭据创建了以下Secret;通过像这样命名密钥,我们可以使用单个envFrom块而不是多个env条目(有关详细信息,请参见部署):

apiVersion: v1
kind: Secret
metadata:
  name: postgres-env
type: Opaque
stringData:
  POSTGRES_USER: example
  POSTGRES_PASSWORD: secret

根据我的评论,我将从以下ConfigMap向/docker-entrypoint-initdb.d注入一个文件:

apiVersion: v1
kind: ConfigMap
metadata:
  name: postgres-config
data:
  initdb.sql: |
    CREATE TABLE people (
      id SERIAL,
      name VARCHAR(40),
      favorite_color VARCHAR(10)
    );

    INSERT INTO people (name, favorite_color) VALUES ('bob', 'red');
    INSERT INTO people (name, favorite_color) VALUES ('alice', 'blue');
    INSERT INTO people (name, favorite_color) VALUES ('mallory', 'purple');

我正在使用这个持久卷声明:

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: postgres-pv-claim
spec:
  accessModes:
  - ReadWriteOnce
  resources:
    requests:
      storage: 1Gi

最后,我将在此部署中将所有这些联系在一起:

apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: postgres
  name: postgresql
spec:
  replicas: 1
  strategy:
    type: Recreate
  selector:
    matchLabels:
      app: postgres
  template:
    metadata:
      labels:
        app: postgres
    spec:
      containers:
      - envFrom:
        - secretRef:
            name: postgres-env
        image: docker.io/postgres:14
        name: postgresql
        ports:
        - containerPort: 5432
          name: postgresql
        volumeMounts:
        - mountPath: /docker-entrypoint-initdb.d
          name: postgres-config
        - mountPath: /var/lib/postgresql
          name: postgres-data
      volumes:
      - name: postgres-data
        persistentVolumeClaim:
          claimName: postgres-pv-claim
      - configMap:
          name: postgres-config
        name: postgres-config

这方面的重大变化包括:
1.我使用单个envFrom块从postgres-env secret中的键设置环境变量。
1.我使用的是上游docker.io/postgres:14映像,而不是构建自己的自定义映像。
1.我正在从postgres-config配置Map注入/docker-entrypoint-initdb.d的内容。
请注意,此部署使用的mountPath与示例中的相同。
如果打开这个环境,可以看到数据库初始化脚本执行正确,people表存在并包含预期的数据:

$ kubtectl exec -it deploy/postgresql -- psql -U example -c 'select * from people'
id |  name   | favorite_color
----+---------+----------------
1 | bob     | red
2 | alice   | blue
3 | mallory | purple
(3 rows)

让我们对数据库进行更改,看看重启pod后会发生什么。首先,我们向表中添加一个新行,并查看更新后的表:

$ kubectl exec -it deploy/postgresql -- psql -U example -c "insert into people (name, favorite_color) values ('carol', 'green')"
INSERT 0 1
$ kubectl exec -it deploy/postgresql -- psql -U example -c 'select * from people'
id |  name   | favorite_color
----+---------+----------------
1 | bob     | red
2 | alice   | blue
3 | mallory | purple
4 | carol   | green
(4 rows)

现在我们重新启动数据库pod:

$ kubectl rollout restart deployment/postgresql

最后检查我们的更改是否在重新启动后仍然存在:

$ kubectl exec -it deploy/postgresql -- psql -U example -c 'select * from people' id |  name   | favorite_color
----+---------+----------------
1 | bob     | red
2 | alice   | blue
3 | mallory | purple
(3 rows)

不出所料,他们没有!让我们更改部署中的mountPath,使其如下所示:

apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: postgres
  name: postgresql
spec:
  replicas: 1
  strategy:
    type: Recreate
  selector:
    matchLabels:
      app: postgres
  template:
    metadata:
      labels:
        app: postgres
    spec:
      containers:
      - envFrom:
        - secretRef:
            name: postgres-env
        image: docker.io/postgres:14
        name: postgresql
        ports:
        - containerPort: 5432
          name: postgresql
        volumeMounts:
        - mountPath: /docker-entrypoint-initdb.d
          name: postgres-config
        - mountPath: /var/lib/postgresql/data
          name: postgres-data
      volumes:
      - name: postgres-data
        persistentVolumeClaim:
          claimName: postgres-pv-claim
      - configMap:
          name: postgres-config
        name: postgres-config

使用此部署,不做其他更改,我们可以重新运行之前的测试,并看到数据按预期持续存在:

$ kubectl exec -it deploy/postgresql -- psql -U example -c "insert into people (name, favorite_color) values ('carol', 'green')"
INSERT 0 1
$ k rollout restart deployment/postgresql
deployment.apps/postgresql restarted
$ k exec -it deploy/postgresql -- psql -U example -c 'select * from people' id |  name   | favorite_color
----+---------+----------------
  1 | bob     | red
  2 | alice   | blue
  3 | mallory | purple
  4 | carol   | green
(4 rows)

另一种解决方案是将卷挂载到一个完全不同的位置,然后适当地设置PGDATA

...
          env:
            - name: PGDATA
              value: /data
          ...
          volumeMounts:
            - name: postgres-data
              mountPath: /data
          ...

相关问题