【问题标题】:How to backup a Postgres database in Kubernetes on Google Cloud?如何在 Google Cloud 上的 Kubernetes 中备份 Postgres 数据库?
【发布时间】:2017-07-10 16:39:18
【问题描述】:

备份在Google Cloud Container Engine 上运行的 Postgres 数据库的最佳做法是什么?

我的想法是将备份存储在Google Cloud Storage,但我不确定如何将磁盘/Pod 连接到存储桶。

我正在使用以下配置在 Kubernetes 集群中运行 Postgres:

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: postgres-deployment
spec:
  replicas: 1
  template:
    metadata:
      labels:
        app: postgres
    spec:
      containers:
        - image: postgres:9.6.2-alpine
          imagePullPolicy: IfNotPresent
          env:
            - name: PGDATA
              value: /var/lib/postgresql/data
            - name: POSTGRES_DB
              value: my-database-name
            - name: POSTGRES_PASSWORD
              value: my-password
            - name: POSTGRES_USER
              value: my-database-user
          name: postgres-container
          ports:
            - containerPort: 5432
          volumeMounts:
            - mountPath: /var/lib/postgresql
              name: my-postgres-volume
      volumes:
        - gcePersistentDisk:
            fsType: ext4
            pdName: my-postgres-disk
          name: my-postgres-volume

我已尝试创建 Job 来运行备份:

apiVersion: batch/v1
kind: Job
metadata:
  name: postgres-dump-job
spec:
  template:
    metadata:
      labels:
        app: postgres-dump
    spec:
      containers:
        - command:
            - pg_dump
            - my-database-name
          # `env` value matches `env` from previous configuration.
          image: postgres:9.6.2-alpine
          imagePullPolicy: IfNotPresent
          name: my-postgres-dump-container
          volumeMounts:
            - mountPath: /var/lib/postgresql
              name: my-postgres-volume
              readOnly: true
      restartPolicy: Never
      volumes:
        - gcePersistentDisk:
            fsType: ext4
            pdName: my-postgres-disk
          name: my-postgres-volume

(据我了解)这应该运行pg_dump 命令并将备份数据输出到标准输出(应该出现在kubectl logs 中)。

顺便说一句,当我检查 Pod(使用 kubectl get pods)时,它显示 Pod 永远不会退出“待定”状态,我认为这是因为没有足够的资源来启动 Job。

将此进程作为作业运行是否正确? 如何将作业连接到 Google Cloud Storage? 还是我应该做一些完全不同的事情?

我猜由于性能下降,在数据库容器中运行pg_dump(带有kubectl exec)是不明智的,但也许这在开发/登台服务器中可以吗?

【问题讨论】:

  • 这正是我的情况。您找到可以分享的可行解决方案了吗?

标签: postgresql google-cloud-storage kubernetes google-kubernetes-engine


【解决方案1】:

正如@Marco Lamina 所说,您可以像这样在 postgres pod 上运行 pg_dump

DUMP
// pod-name         name of the postgres pod
// postgres-user    database user that is able to access the database
// database-name    name of the database
kubectl exec [pod-name] -- bash -c "pg_dump -U [postgres-user] [database-name]" > database.sql


RESTORE
// pod-name         name of the postgres pod
// postgres-user    database user that is able to access the database
// database-name    name of the database
cat database.sql | kubectl exec -i [pod-name] -- psql -U [postgres-user] -d [database-name]

您可以拥有一个运行此命令并将其导出到文件存储系统(例如 AWS s3)的作业 pod。

【讨论】:

  • pg_dump 过程是最简单的部分。困难在于将其复制到 GCS 存储桶中,这就是我将这个问题悬而未决的原因。
【解决方案2】:

我认为将 pg_dump 作为作业运行是一个好主意,但直接连接到数据库的永久磁盘则不是。尝试让 pg_dump 通过网络连接到您的数据库!然后,您可以拥有第二个磁盘,您的 pg_dump 命令将备份转储到该磁盘上。为了安全起见,您可以创建第二个磁盘的常规快照。

【讨论】:

  • 请问您为什么需要将备份保存在 Google Cloud Storage 中?我认为最简单的方法是编写一个执行 pg_dump 并将数据直接推送到 Google Cloud Storage 的小脚本。将脚本容器化,将其作为 K8 作业运行,您就完成了!
  • Buckets 似乎更具可扩展性(没有大小管理),并提供用于本地安装的工具。磁盘出现在计算部分,因此它们似乎针对的是运行实例而不是长期存储。整个过程需要自动进行(无需手动创建磁盘或快照),因此帮助编写脚本(连接到适当的存储)正是我提出这个问题的目的。
  • @MarcoLamina 您能否详细说明“将脚本容器化,将其作为 K8 作业运行”?
  • @void 作业是一个 K8 资源,用于运行容器一次(或 x 次)直到完成:kubernetes.io/docs/concepts/workloads/controllers/…
【解决方案3】:

Jobs POD 保持Pending 状态的原因是它永远尝试附加/挂载 GCE 永久磁盘,但由于它已经附加/挂载到另一个 POD 而失败。

仅当所有 POD 都以只读模式附加/挂载卷时,才支持将永久磁盘附加到多个 POD。这对你来说当然不是可行的解决方案。

我从未使用过 GCE,但应该可以从 GCE 中轻松地从 PD 创建快照。这不会提供非常干净的备份,更像是处于“中间崩溃但可恢复”状态的东西,但这可能对您来说是可以接受的。

在数据库 POD 中运行 pg_dump 是一个可行的解决方案,但您已经注意到了一些缺点,尤其是性能。之后,您还必须从 POD 中移出生成的备份,例如通过使用kubectl cp 和另一个exec 来清理POD 中的备份。

【讨论】:

  • 感谢您的建议,但正如您所说,虽然磁盘快照是可能的,但它们远非理想的备份解决方案。我正在寻找可以在生产中使用的稳定的东西,所以我将把这个问题留给其他解决方案。对磁盘很感兴趣,我认为以只读方式连接是可能的,但似乎不行。
  • 如前所述,仅当所有 POD 都附加/安装为只读时。否则无法保证与只读挂载的一致性。
【解决方案4】:

您可以使用Minio Client

首先使用简单的 dockerfile 使 docker 镜像包含 postgres 以及 minio 客户端(让这个镜像命名为 postgres_backup):

FROM postgres

RUN apt-get update && apt-get install -y wget

RUN wget https://dl.min.io/client/mc/release/linux-amd64/mc

RUN chmod +x mc

RUN ./mc alias set gcs  https://storage.googleapis.com BKIKJAA5BMMU2RHO6IBB V8f1CwQqAcwo80UEIJEjc5gVQUSSx5ohQ9GSrr12

现在您可以在您的 CronJob 中使用 postgres_backup 图像(我假设您在 Google 存储中创建了 backups 存储桶):

apiVersion: batch/v1beta1
kind: CronJob
metadata:
  name: backup-job
spec:
  # Backup the database every day at 2AM
  schedule: "0 2 * * *"
  jobTemplate:
    spec:
      template:
        spec:
          containers:
          - name: postgres-backup
            image: postgres_backup
            env:
            - name: POSTGRES_HOST_AUTH_METHOD
              value: trust
            command: ["/bin/sh"]
            args: ["-c", 'pg_dump -Fc -U [Your Postgres Username] -W [Your Postgres Password] -h [Your Postgres Host] [Your Postgres Database] | ./mc pipe gcs/backups/$(date -Iseconds).dump']
          restartPolicy: Never

【讨论】:

    【解决方案5】:

    很多教程使用kubectl cp或将文件传输到pod内部,但您也可以将pg_dump容器输出直接管道到另一个进程。

    kubectl run --env=PGPASSWORD=$PASSWORD --image=bitnami/postgresql postgresql -it --rm -- \
      bash -c "pg_dump -U $USER -h $HOST -d $DATABASE" |\
      gzip > backup.sql.gz
    

    【讨论】:

      猜你喜欢
      • 2021-07-27
      • 2021-12-08
      • 2022-01-10
      • 1970-01-01
      • 2018-07-17
      • 2021-08-24
      • 1970-01-01
      • 1970-01-01
      • 2013-08-29
      相关资源
      最近更新 更多