# Upgrading PostgreSQL for Auto DevOps

> 原文：[https://docs.gitlab.com/ee/topics/autodevops/upgrading_postgresql.html](https://docs.gitlab.com/ee/topics/autodevops/upgrading_postgresql.html)

*   [Prerequisites](#prerequisites)
*   [Take your application offline](#take-your-application-offline)
*   [Backup](#backup)
*   [Retain persistent volumes](#retain-persistent-volumes)
*   [Install new PostgreSQL](#install-new-postgresql)
*   [Restore](#restore)
*   [Reinstate your application](#reinstate-your-application)

# Upgrading PostgreSQL for Auto DevOps[](#upgrading-postgresql-for-auto-devops "Permalink")

Auto DevOps 为您的应用程序提供[集群内 PostgreSQL 数据库](customize.html#postgresql-database-support) .

用于配置 PostgreSQL 的图表的版本：

*   在 GitLab 12.8 及更早版本中为 0.7.1.
*   在 GitLab 12.9 及更高版本中可以设置为 0.7.1 至 8.2.1.

GitLab 鼓励用户将其数据库迁移到较新的 PostgreSQL 图表.

本指南提供有关如何迁移 PostgreSQL 数据库的说明，其中包括：

1.  对数据进行数据库转储.
2.  使用图表的较新版本 8.2.1 安装新的 PostgreSQL 数据库，并删除旧的 PostgreSQL 安装.
3.  将数据库转储还原到新的 PostgreSQL 中.

## Prerequisites[](#prerequisites "Permalink")

1.  Install [`kubectl`](https://kubernetes.io/docs/tasks/tools/install-kubectl/).
2.  确保您可以使用`kubectl`访问 Kubernetes 集群. 这取决于 Kubernetes 提供者.
3.  准备停机. 下面的步骤包括使应用程序脱机，以便在创建数据库转储后不修改集群内数据库.
4.  确保尚未将`POSTGRES_ENABLED`设置为`false` ，因为此设置将删除任何现有的通道 1 数据库. 有关更多信息，请参见[检测到现有的 PostgreSQL 数据库](index.html#detected-an-existing-postgresql-database) .

**提示：**如果已将 Auto DevOps 配置为具有暂存，请考虑先尝试暂存并还原备份和还原步骤，或者在审阅应用程序中尝试此步骤.

## Take your application offline[](#take-your-application-offline "Permalink")

如果需要，请使应用程序脱机，以防止在创建数据库转储后修改数据库.

1.  获取环境的 Kubernetes 命名空间. 它通常看起来像`<project-name>-<project-id>-<environment>` . 在我们的示例中，名称空间称为`minimal-ruby-app-4349298-production` .

    ```
     $ kubectl get ns

     NAME                                                  STATUS   AGE
     minimal-ruby-app-4349298-production                   Active   7d14h 
    ```

2.  为了易于使用，请导出名称空间名称：

    ```
    export APP_NAMESPACE=minimal-ruby-app-4349298-production 
    ```

3.  使用以下命令获取应用程序的部署名称. 在我们的示例中，部署名称为`production` .

    ```
     $ kubectl get deployment --namespace "$APP_NAMESPACE"
     NAME                  READY   UP-TO-DATE   AVAILABLE   AGE
     production            2/2     2            2           7d21h
     production-postgres   1/1     1            1           7d21h 
    ```

4.  为了防止数据库被修改，请使用以下命令将副本的副本数设置为 0\. 我们使用上一步中的部署名称（ `deployments/<DEPLOYMENT_NAME>` ）.

    ```
     $ kubectl scale --replicas=0 deployments/production --namespace "$APP_NAMESPACE"
     deployment.extensions/production scaled 
    ```

5.  如果有的话，还需要将 worker 的副本设置为零.

## Backup[](#backup "Permalink")

1.  获取 PostgreSQL 的服务名称. 服务的名称应以`-postgres` . 在我们的示例中，服务名称为`production-postgres` .

    ```
     $ kubectl get svc --namespace "$APP_NAMESPACE"
     NAME                     TYPE        CLUSTER-IP    EXTERNAL-IP   PORT(S)    AGE
     production-auto-deploy   ClusterIP   10.30.13.90   <none>        5000/TCP   7d14h
     production-postgres      ClusterIP   10.30.4.57    <none>        5432/TCP   7d14h 
    ```

2.  使用以下命令获取 PostgreSQL 的 pod 名称. 在我们的示例中，吊舱名称为`production-postgres-5db86568d7-qxlxv` .

    ```
     $ kubectl get pod --namespace "$APP_NAMESPACE" -l app=production-postgres
     NAME                                   READY   STATUS    RESTARTS   AGE
     production-postgres-5db86568d7-qxlxv   1/1     Running   0          7d14h 
    ```

3.  通过以下方式连接到吊舱：

    ```
     kubectl exec -it production-postgres-5db86568d7-qxlxv --namespace "$APP_NAMESPACE" bash 
    ```

4.  连接后，使用以下命令创建转储文件.

    *   `SERVICE_NAME`是在上一步中获得的服务名称.
    *   `USERNAME`是您为 PostgreSQL 配置的用户名. 默认值为`user` .
    *   `DATABASE_NAME`通常是环境名称.

    *   系统将要求您输入数据库密码，默认`testing-password`是`testing-password` .

    ```
     ## Format is:
     # pg_dump -h SERVICE_NAME -U USERNAME DATABASE_NAME > /tmp/backup.sql

     pg_dump -h production-postgres -U user production > /tmp/backup.sql 
    ```

5.  备份转储完成后，使用`Control-D` `exit` Kubernetes exec 进程或`exit` .

6.  使用以下命令下载转储文件：

    ```
     kubectl cp --namespace "$APP_NAMESPACE" production-postgres-5db86568d7-qxlxv:/tmp/backup.sql backup.sql 
    ```

## Retain persistent volumes[](#retain-persistent-volumes "Permalink")

默认情况下，当`Delete`使用该卷的 Pod 和 Pod 声明时，用于存储 PostgreSQL 基础数据的[持久卷](https://kubernetes.io/docs/concepts/storage/persistent-volumes/)将标记为`Delete` .

这很重要，因为当您选择使用较新的 8.2.1 PostgreSQL 时，会删除较旧的 0.7.1 PostgreSQL，从而导致永久卷也被删除.

您可以使用以下命令进行验证：

```
$ kubectl get pv
NAME                                       CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM                                                     STORAGECLASS   REASON   AGE
pvc-0da80c08-5239-11ea-9c8d-42010a8e0096   8Gi        RWO            Delete           Bound    minimal-ruby-app-4349298-staging/staging-postgres         standard                7d22h
pvc-9085e3d3-5239-11ea-9c8d-42010a8e0096   8Gi        RWO            Delete           Bound    minimal-ruby-app-4349298-production/production-postgres   standard                7d22h 
```

为了保留持久卷，即使删除了较旧的 0.7.1 PostgreSQL，我们也可以将保留策略更改为`Retain` . 在此示例中，我们通过查看声明名称来找到持久卷名称. 由于我们有兴趣保留用于`minimal-ruby-app-4349298`应用程序的阶段和生产的卷，因此此处的卷名称为`pvc-0da80c08-5239-11ea-9c8d-42010a8e0096`和`pvc-9085e3d3-5239-11ea-9c8d-42010a8e0096` ：

```
$ kubectl patch pv  pvc-0da80c08-5239-11ea-9c8d-42010a8e0096 -p '{"spec":{"persistentVolumeReclaimPolicy":"Retain"}}'
persistentvolume/pvc-0da80c08-5239-11ea-9c8d-42010a8e0096 patched
$ kubectl patch pv  pvc-9085e3d3-5239-11ea-9c8d-42010a8e0096 -p '{"spec":{"persistentVolumeReclaimPolicy":"Retain"}}'
persistentvolume/pvc-9085e3d3-5239-11ea-9c8d-42010a8e0096 patched
$ kubectl get pv
NAME                                       CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM                                                     STORAGECLASS   REASON   AGE
pvc-0da80c08-5239-11ea-9c8d-42010a8e0096   8Gi        RWO            Retain           Bound    minimal-ruby-app-4349298-staging/staging-postgres         standard                7d22h
pvc-9085e3d3-5239-11ea-9c8d-42010a8e0096   8Gi        RWO            Retain           Bound    minimal-ruby-app-4349298-production/production-postgres   standard                7d22h 
```

## Install new PostgreSQL[](#install-new-postgresql "Permalink")

**注意：**使用较新版本的 PostgreSQL 将删除较旧的 0.7.1 PostgreSQL. 为了防止基础数据被删除，您可以选择保留[持久卷](#retain-persistent-volumes) .**提示：**您还可以将`AUTO_DEVOPS_POSTGRES_CHANNEL` ， `AUTO_DEVOPS_POSTGRES_DELETE_V1`和`POSTGRES_VERSION`变量的[作用域](../../ci/environments/index.html#scoping-environments-with-specs)设置为特定环境，例如`staging` .

1.  将`AUTO_DEVOPS_POSTGRES_CHANNEL`设置为`2` . 选择使用较新的基于 8.2.1 的 PostgreSQL，并删除较旧的基于 0.7.1 的 PostgreSQL.
2.  将`AUTO_DEVOPS_POSTGRES_DELETE_V1`设置为非空值. 此标志是防止意外删除数据库的保护措施.
3.  将`POSTGRES_VERSION`设置为`11.7` . 这是支持的最低 PostgreSQL 版本.
4.  将`PRODUCTION_REPLICAS`设置为`0` . 对于其他环境， `REPLICAS`在[环境范围内](../../ci/environments/index.html#scoping-environments-with-specs)使用`REPLICAS` .
5.  如果已设置`DB_INITIALIZE`或`DB_MIGRATE`变量，请删除变量，或将变量临时重命名为`XDB_INITIALIZE`或`XDB_MIGRATE`以有效地禁用它们.
6.  Run a new CI pipeline for the branch. In this case, we run a new CI pipeline for `master`.
7.  一旦管道成功，您的应用程序现在将安装新的 PostgreSQL 进行升级. 复制品也将为零，这意味着将不为您的应用程序提供任何流量（以防止新数据进入）.

## Restore[](#restore "Permalink")

1.  获取新 PostgreSQL 的容器名称，在我们的示例中，容器名称为`production-postgresql-0` ：

    ```
     $ kubectl get pod --namespace "$APP_NAMESPACE" -l app=postgresql
     NAME                      READY   STATUS    RESTARTS   AGE
     production-postgresql-0   1/1     Running   0          19m 
    ```

2.  将转储文件从备份步骤复制到 Pod：

    ```
    kubectl cp --namespace "$APP_NAMESPACE" backup.sql production-postgresql-0:/tmp/backup.sql 
    ```

3.  连接到吊舱：

    ```
    kubectl exec -it production-postgresql-0 --namespace "$APP_NAMESPACE" bash 
    ```

4.  连接到 Pod 后，运行以下命令来还原数据库.

    *   系统将要求您输入数据库密码，默认`testing-password`是`testing-password` .
    *   `USERNAME`是您为 PostgreSQL 配置的用户名. 默认值为`user` .
    *   `DATABASE_NAME`通常是环境名称.

    ```
    ## Format is:
    # psql -U USERNAME -d DATABASE_NAME < /tmp/backup.sql

    psql -U user -d production < /tmp/backup.sql 
    ```

5.  现在，您可以检查还原完成后是否已正确还原数据. 您可以使用`psql`对数据进行抽查.

## Reinstate your application[](#reinstate-your-application "Permalink")

对数据库已还原感到满意后，请运行以下步骤来恢复您的应用程序：

1.  如果先前已删除或禁用了`DB_INITIALIZE`和`DB_MIGRATE`变量，则将其还原.
2.  将`PRODUCTION_REPLICAS`或`REPLICAS`变量恢复为其原始值.
3.  为分支运行新的 CI 管道. 在这种情况下，我们为`master`运行新的 CI 管道. 管道成功后，您的应用程序应该像以前一样提供流量.