# Geo database replication

> 原文：[https://docs.gitlab.com/ee/administration/geo/replication/database.html](https://docs.gitlab.com/ee/administration/geo/replication/database.html)

*   [PostgreSQL replication](#postgresql-replication)
    *   [Step 1\. Configure the **primary** server](#step-1-configure-the-primary-server)
    *   [Step 2\. Configure the **secondary** server](#step-2-configure-the-secondary-server)
    *   [Step 3\. Initiate the replication process](#step-3-initiate-the-replication-process)
*   [PgBouncer support (optional)](#pgbouncer-support-optional)
*   [Troubleshooting](#troubleshooting)

# Geo database replication[](#geo-database-replication-premium-only "Permalink")

**注意：**如果您的 GitLab 安装使用外部（不受 Omnibus 管理）PostgreSQL 实例，则 Omnibus 角色将无法执行所有必要的配置步骤. 在这种情况下，请[改用 Geo with external PostgreSQL instances 文档](external_database.html) .**Note:** The stages of the setup process must be completed in the documented order. Before attempting the steps in this stage, [complete all prior stages](index.html#using-omnibus-gitlab).

本文档介绍了将**主** GitLab 数据库复制到**辅助**节点的数据库时必须执行的最少步骤. 您可能需要根据数据库设置，数据库大小等来更改一些值.

我们鼓励您先阅读所有步骤，然后再在测试/生产环境中执行这些步骤.

## PostgreSQL replication[](#postgresql-replication "Permalink")

进行写操作的 GitLab **主**节点将连接到**主**数据库服务器， **辅助**节点将连接到他们自己的数据库服务器（也是只读的）.

我们建议使用[PostgreSQL 复制插槽，](https://medium.com/@tk512/replication-slots-in-postgresql-b4b03d277c75)以确保**主**节点保留恢复**次**节点所需的所有数据. 请参阅下面的更多细节.

The following guide assumes that:

*   您使用的是 Omnibus，因此使用的是 PostgreSQL 11 或更高版本，其中包括[`pg_basebackup`工具](https://s0www0postgresql0org.icopy.site/docs/11/app-pgbasebackup.html)和改进的[Foreign Data Wrapper](https://s0www0postgresql0org.icopy.site/docs/11/postgres-fdw.html)支持.
*   您已经设置了一个**主**节点（您要从中复制的 GitLab 服务器），并且正在运行 Omnibus 的 PostgreSQL（或等效版本），并且已经设置了一个新的**辅助**服务器，并且具有相同版本的 OS，PostgreSQL 和 GitLab.所有节点.

**警告：** Geo 可用于流复制. 目前不支持逻辑复制. 在[讨论支持问题](https://gitlab.com/gitlab-org/gitlab/-/issues/7420) .

### Step 1\. Configure the **primary** server[](#step-1-configure-the-primary-server "Permalink")

1.  SSH 到您的 GitLab **主**服务器并以 root 用户身份登录：

    ```
    sudo -i 
    ```

2.  编辑`/etc/gitlab/gitlab.rb`并为您的节点添加一个**唯一的**名称：

    ```
    # The unique identifier for the Geo node.
    gitlab_rails['geo_node_name'] = '<node_name_here>' 
    ```

3.  重新配置**主**节点以使更改生效：

    ```
    gitlab-ctl reconfigure 
    ```

4.  执行以下命令以将节点定义**为主**节点：

    ```
    gitlab-ctl set-geo-primary-node 
    ```

    该命令将使用您在`/etc/gitlab/gitlab.rb`定义的`external_url` .

5.  仅限于 GitLab 10.4 及更高版本：执行以下操作以确保`gitlab`数据库用户已定义密码：

    生成所需密码的 MD5 哈希值：

    ```
    gitlab-ctl pg-password-md5 gitlab
    # Enter password: <your_password_here>
    # Confirm password: <your_password_here>
    # fca0b89a972d69f00eb3ec98a5838484 
    ```

    Edit `/etc/gitlab/gitlab.rb`:

    ```
    # Fill with the hash generated by `gitlab-ctl pg-password-md5 gitlab`
    postgresql['sql_user_password'] = '<md5_hash_of_your_password>'

    # Every node that runs Puma or Sidekiq needs to have the database
    # password specified as below. If you have a high-availability setup, this
    # must be present in all application nodes.
    gitlab_rails['db_password'] = '<your_password_here>' 
    ```

6.  Omnibus GitLab 已经有一个名为`gitlab_replicator`的[复制用户](https://wiki.postgresql.org/wiki/Streaming_Replication) . 您必须手动设置该用户的密码. 系统将提示您输入密码：

    ```
    gitlab-ctl set-replication-password 
    ```

    如果您已将`gitlab_replicator`用户名更改为其他名称，则此命令还将读取`postgresql['sql_replication_user']` Omnibus 设置.

    如果您使用的不是由 Omnibus GitLab 管理的外部数据库，则需要创建复制器用户并手动为其定义密码：

    ```
    --- Create a new user 'replicator'
    CREATE USER gitlab_replicator;

    --- Set/change a password and grants replication privilege
    ALTER USER gitlab_replicator WITH REPLICATION ENCRYPTED PASSWORD '<replication_password>'; 
    ```

7.  配置 PostgreSQL 以侦听网络接口：

    出于安全原因，PostgreSQL 默认情况下不侦听任何网络接口. 但是，Geo 要求**辅助**节点能够连接到**主**节点的数据库. 因此，我们需要每个节点的地址.

    **注意：**对于外部 PostgreSQL 实例，请参见[其他说明](external_database.html) .

    如果使用的是云提供商，则可以通过云提供商的管理控制台查找每个地理节点的地址.

    要查找 Geo 节点的地址，请 SSH 到 Geo 节点并执行：

    ```
    ##
    ## Private address
    ##
    ip route get 255.255.255.255 | awk '{print "Private address:", $NF; exit}'

    ##
    ## Public address
    ##
    echo "External address: $(curl --silent ipinfo.io/ip)" 
    ```

    在大多数情况下，以下地址将用于配置 GitLab Geo：

    | Configuration | Address |
    | --- | --- |
    | `postgresql['listen_address']` | **主**节点的公用或 VPC 专用地址. |
    | `postgresql['md5_auth_cidr_addresses']` | **辅助**节点的公用或 VPC 专用地址. |

    如果您使用的是 Google Cloud Platform，SoftLayer 或提供虚拟私有云（VPC）的任何其他供应商，则可以将**主**节点和**辅助**节点的私有地址（对应于 Google Cloud Platform 的"内部地址"）用于`postgresql['md5_auth_cidr_addresses']`和`postgresql['listen_address']` .

    `listen_address`选项打开 PostgreSQL 直至与给定地址对应的接口的网络连接. 有关更多详细信息，请参见[PostgreSQL 文档](https://s0www0postgresql0org.icopy.site/docs/11/runtime-config-connection.html) .

    根据您的网络配置，建议的地址可能不正确. 如果您的**主**节点和**辅助**节点通过局域网或连接可用性区域的虚拟网络（例如[Amazon 的 VPC](https://aws.amazon.com/vpc/)或[Google 的 VPC）进行连接](https://cloud.google.com/vpc/) ，则应将**辅助**节点的私有地址用于`postgresql['md5_auth_cidr_addresses']` .

    编辑`/etc/gitlab/gitlab.rb`并添加以下内容，将 IP 地址替换为适合您的网络配置的地址：

    ```
    ##
    ## Geo Primary role
    ## - configure dependent flags automatically to enable Geo
    ##
    roles ['geo_primary_role']

    ##
    ## Primary address
    ## - replace '<primary_node_ip>' with the public or VPC address of your Geo primary node
    ##
    postgresql['listen_address'] = '<primary_node_ip>'

    ##
    # Allow PostgreSQL client authentication from the primary and secondary IPs. These IPs may be
    # public or VPC addresses in CIDR format, for example ['198.51.100.1/32', '198.51.100.2/32']
    ##
    postgresql['md5_auth_cidr_addresses'] = ['<primary_node_ip>/32', '<secondary_node_ip>/32']

    ##
    ## Replication settings
    ## - set this to be the number of Geo secondary nodes you have
    ##
    postgresql['max_replication_slots'] = 1
    # postgresql['max_wal_senders'] = 10
    # postgresql['wal_keep_segments'] = 10

    ##
    ## Disable automatic database migrations temporarily
    ## (until PostgreSQL is restarted and listening on the private address).
    ##
    gitlab_rails['auto_migrate'] = false 
    ```

8.  可选：如果要添加另一个**辅助**节点，则相关设置应如下所示：

    ```
    postgresql['md5_auth_cidr_addresses'] = ['<primary_node_ip>/32', '<secondary_node_ip>/32', '<another_secondary_node_ip>/32'] 
    ```

    您可能还需要编辑`wal_keep_segments`和`max_wal_senders`以匹配您的数据库复制要求. 有关更多信息，请查阅[PostgreSQL-复制文档](https://s0www0postgresql0org.icopy.site/docs/11/runtime-config-replication.html) .

9.  保存文件并重新配置 GitLab，以进行数据库侦听更改和要应用的复制插槽更改：

    ```
    gitlab-ctl reconfigure 
    ```

    重新启动 PostgreSQL 以使其更改生效：

    ```
    gitlab-ctl restart postgresql 
    ```

10.  现在，重新启动 PostgreSQL 并重新侦听私有地址，即可重新启用迁移.

    编辑`/etc/gitlab/gitlab.rb`并将配置**更改**为`true` ：

    ```
    gitlab_rails['auto_migrate'] = true 
    ```

    保存文件并重新配置 GitLab：

    ```
    gitlab-ctl reconfigure 
    ```

11.  现在，PostgreSQL 服务器已设置为接受远程连接，请运行`netstat -plnt | grep 5432` `netstat -plnt | grep 5432` ，以确保 PostgreSQL 在端口`5432`上侦听**主**服务器的私有地址.

12.  重新配置 GitLab 时会自动生成一个证书. 这将自动用于保护 PostgreSQL 流量免遭窃听，但是为了防止主动（中间人）攻击者， **辅助**节点需要证书的副本. 通过运行以下命令，在**主**节点上复制 PostgreSQL `server.crt`文件：

    ```
    cat ~gitlab-psql/data/server.crt 
    ```

    将输出复制到剪贴板或本地文件中. 设置**辅助**节点时将需要它！ 证书不是敏感数据.

### Step 2\. Configure the **secondary** server[](#step-2-configure-the-secondary-server "Permalink")

1.  SSH 到您的 GitLab **辅助**服务器并以 root 用户身份登录：

    ```
    sudo -i 
    ```

2.  停止应用程序服务器和 Sidekiq

    ```
    gitlab-ctl stop puma
    gitlab-ctl stop sidekiq 
    ```

    **注意：**此步骤很重要，因此在完全配置节点之前，我们不要尝试执行任何操作.
3.  [检查](../../raketasks/maintenance.html)与**主**节点的 PostgreSQL 服务器的[TCP 连接](../../raketasks/maintenance.html) ：

    ```
    gitlab-rake gitlab:tcp_check[<primary_node_ip>,5432] 
    ```

    **注意：**如果此步骤失败，则可能是您使用了错误的 IP 地址，或者防火墙可能阻止了对服务器的访问. 检查 IP 地址，并密切注意公用地址和专用地址之间的区别，并确保（如果存在防火墙）允许**次**节点连接到端口 5432 上的**主**节点.
4.  在**辅助**服务器上创建文件`server.crt` ，其中包含在**主**节点设置的最后一步中获得的内容：

    ```
    editor server.crt 
    ```

5.  在**辅助**节点上设置 PostgreSQL TLS 验证：

    安装`server.crt`文件：

    ```
    install \
       -D \
       -o gitlab-psql \
       -g gitlab-psql \
       -m 0400 \
       -T server.crt ~gitlab-psql/.postgresql/root.crt 
    ```

    现在，PostgreSQL 将仅在验证 TLS 连接时识别该确切证书. 只能由有权访问私钥的人复制证书，该私钥**仅存**在于**主**节点上.

6.  测试`gitlab-psql`用户可以连接到**主**节点的数据库（默认的 Omnibus 数据库名称为`gitlabhq_production` ）：

    ```
    sudo \
       -u gitlab-psql /opt/gitlab/embedded/bin/psql \
       --list \
       -U gitlab_replicator \
       -d "dbname=gitlabhq_production sslmode=verify-ca" \
       -W \
       -h <primary_node_ip> 
    ```

    出现提示时，输入您在第一步中为`gitlab_replicator`用户设置的密码. 如果所有方法均正常工作，则应该看到**主**节点数据库的列表.

    此处连接失败表示 TLS 配置不正确. 确保**主**节点上`~gitlab-psql/data/server.crt`的内容与**辅助**节点上`~gitlab-psql/.postgresql/root.crt`的内容匹配.

7.  配置 PostgreSQL 以启用 FDW 支持：

    此步骤类似于我们配置**主**实例的方式. 我们需要启用它，以启用 FDW 支持，即使使用单个节点也是如此.

    编辑`/etc/gitlab/gitlab.rb`并添加以下内容，将 IP 地址替换为适合您的网络配置的地址：

    ```
    ##
    ## Geo Secondary role
    ## - configure dependent flags automatically to enable Geo
    ##
    roles ['geo_secondary_role']

    ##
    ## Secondary address
    ## - replace '<secondary_node_ip>' with the public or VPC address of your Geo secondary node
    ##
    postgresql['listen_address'] = '<secondary_node_ip>'
    postgresql['md5_auth_cidr_addresses'] = ['<secondary_node_ip>/32']

    ##
    ## Database credentials password (defined previously in primary node)
    ## - replicate same values here as defined in primary node
    ##
    postgresql['sql_user_password'] = '<md5_hash_of_your_password>'
    gitlab_rails['db_password'] = '<your_password_here>'

    ##
    ## Enable FDW support for the Geo Tracking Database (improves performance)
    ##
    geo_secondary['db_fdw'] = true 
    ```

    对于外部 PostgreSQL 实例，请参见[其他说明](external_database.html) . 如果您使以前的**主**节点重新联机以用作**辅助**节点，则还需要删除`roles ['geo_primary_role']`或`geo_primary_role['enable'] = true` .

8.  重新配置 GitLab，以使更改生效：

    ```
    gitlab-ctl reconfigure 
    ```

9.  重新启动 PostgreSQL 以使 IP 更改生效并再次重新配置：

    ```
    gitlab-ctl restart postgresql
    gitlab-ctl reconfigure 
    ```

    最后的重新配置将提供 FDW 配置并启用它.

### Step 3\. Initiate the replication process[](#step-3-initiate-the-replication-process "Permalink")

在下面，我们提供了一个脚本，该脚本将**辅助**节点上的数据库连接到**主要**节点上的数据库，复制数据库，并创建流复制所需的文件.

使用的目录是在 Omnibus 中设置的默认目录. 如果更改了任何默认值，请根据需要配置它，替换目录和路径.

**警告：**确保在**辅助**服务器上运行此命令，因为它会在运行`pg_basebackup`之前删除所有 PostgreSQL 的数据.

1.  SSH 到您的 GitLab **辅助**服务器并以 root 用户身份登录：

    ```
    sudo -i 
    ```

2.  选择一个数据库友好名称，以供您的**辅助**节点用作复制插槽名称. 例如，如果您的域是`secondary.geo.example.com` ，则可以使用`secondary_example`作为插槽名称，如以下命令所示.

3.  执行以下命令以开始备份/还原并开始复制

    **警告：**每个 Geo **辅助**节点必须具有自己的唯一复制插槽名称. 在两个辅助节点之间使用相同的插槽名称将破坏 PostgreSQL 复制.

    ```
    gitlab-ctl replicate-geo-database \
       --slot-name=<secondary_node_name> \
       --host=<primary_node_ip> 
    ```

    **注意：**复制插槽名称只能包含小写字母，数字和下划线字符.

    出现提示时，输入第一步中为`gitlab_replicator`用户设置的*纯文本*密码.

    此命令还带有许多其他选项. 您可以使用`--help`列出所有内容，但是这里有一些提示：

    *   如果 PostgreSQL 在非标准端口上侦听，则还要添加`--port=` .
    *   如果数据库太大而无法在 30 分钟内传输，则需要增加超时，例如`--backup-timeout=3600`如果您希望初始复制花费一个小时以下的话.
    *   通过`--sslmode=disable`可以完全跳过 PostgreSQL TLS 身份验证（例如，您知道网络路径是安全的，或者您使用的是站点到站点 VPN）. 这**不是**通过公共互联网安全！
    *   您可以在[PostgreSQL 文档中](https://s0www0postgresql0org.icopy.site/docs/11/libpq-ssl.html)阅读有关每个`sslmode`更多详细信息； 上面的说明均经过精心编写，以确保既能防御被动的窃听者，又能防御主动的"中间人"攻击者.
    *   将`--slot-name`更改为要在**主**数据库上使用的复制插槽的名称. 该脚本将尝试自动创建复制插槽（如果不存在）.
    *   If you’re repurposing an old server into a Geo **secondary** node, you’ll need to add `--force` to the command line.
    *   如果不在生产机器中，则可以通过添加`--skip-backup`确保确实`--skip-backup`从而禁用备份步骤

复制过程现已完成.

## PgBouncer support (optional)[](#pgbouncer-support-optional "Permalink")

[PgBouncer](https://www.pgbouncer.org/)可以与 GitLab Geo 一起使用来合并 PostgreSQL 连接. 如果您在高可用性配置中使用 GitLab，且该群集的节点集群支持 Geo **主**节点，而另一个节点集群支持 Geo **辅助**节点，则建议使用 PgBouncer. 有关更多信息，请参见[Omnibus GitLab 的高可用性](../../postgresql/replication_and_failover.html) .

为了使 Geo **辅助**节点能够与数据库前面的 PgBouncer 一起正常使用，它将需要一个单独的只读用户才能使[PostgreSQL FDW 查询](https://s0www0postgresql0org.icopy.site/docs/11/postgres-fdw.html)起作用：

1.  在**主要的**地理数据库上，以管理员用户身份在控制台上输入 PostgreSQL. 如果使用的是 Omnibus 管理的数据库，请登录到运行 PostgreSQL 数据库的**主**节点（默认的 Omnibus 数据库名称为`gitlabhq_production` ）：

    ```
     sudo \
        -u gitlab-psql /opt/gitlab/embedded/bin/psql \
        -h /var/opt/gitlab/postgresql gitlabhq_production 
    ```

2.  然后创建只读用户：

    ```
    -- NOTE: Use the password defined earlier
    CREATE USER gitlab_geo_fdw WITH password 'mypassword';
    GRANT CONNECT ON DATABASE gitlabhq_production to gitlab_geo_fdw;
    GRANT USAGE ON SCHEMA public TO gitlab_geo_fdw;
    GRANT SELECT ON ALL TABLES IN SCHEMA public TO gitlab_geo_fdw;
    GRANT SELECT ON ALL SEQUENCES IN SCHEMA public TO gitlab_geo_fdw;

    -- Tables created by "gitlab" should be made read-only for "gitlab_geo_fdw"
    -- automatically.
    ALTER DEFAULT PRIVILEGES FOR USER gitlab IN SCHEMA public GRANT SELECT ON TABLES TO gitlab_geo_fdw;
    ALTER DEFAULT PRIVILEGES FOR USER gitlab IN SCHEMA public GRANT SELECT ON SEQUENCES TO gitlab_geo_fdw; 
    ```

3.  在**辅助**节点上，更改`/etc/gitlab/gitlab.rb` ：

    ```
    geo_postgresql['fdw_external_user'] = 'gitlab_geo_fdw' 
    ```

4.  保存文件并重新配置 GitLab 以应用更改：

    ```
    gitlab-ctl reconfigure 
    ```

## Troubleshooting[](#troubleshooting "Permalink")

阅读[故障排除文档](troubleshooting.html) .