Configura la replicación lógica en Kubernetes

En PostgreSQL, la replicación lógica es un método para copiar cambios de datos de una base de datos del publicador a uno o más suscriptores, que pueden ser bases de datos o otras aplicaciones. Puedes habilitar y configurar la replicación lógica en los clústeres que creas con el operador de Kubernetes de AlloyDB Omni.

En este documento, se proporcionan ejemplos que muestran cómo crear y configurar un clúster de publicador y uno de suscriptor. Antes de leer este documento, debes familiarizarte con la descripción general de AlloyDB Omni. También debes tener en cuenta las limitaciones de la replicación lógica de PostgreSQL.

Los fragmentos de código de esta página son ejemplos que puedes usar como modelos y reemplazar los valores por los de tus recursos de AlloyDB Omni.

Crea los clústeres

  1. Instala el operador Omni en Kubernetes.

  2. Crea un clúster de publicador.

    $ cat << EOF | kubectl apply -f -
    apiVersion: v1
    kind: Secret
    metadata:
      name: db-pw-publisher
    type: Opaque
    data:
      publisher: "b2RzcGFzc3dvcmQ=" # Password is odspassword
    ---
    apiVersion: alloydbomni.dbadmin.goog/v1
    kind: DBCluster
    metadata:
      name: publisher
    spec:
      primarySpec:
        adminUser:
          passwordRef:
            name: db-pw-publisher
        databaseVersion: "15.7.0"
        resources:
          memory: 10Gi
          cpu: 1
          disks:
          - name: DataDisk
            size: 40Gi
    EOF
    
  3. Crea un clúster de suscriptores.

    $ cat << EOF | kubectl apply -f -
    apiVersion: v1
    kind: Secret
    metadata:
      name: db-pw-subscriber
    type: Opaque
    data:
      subscriber: "b2RzcGFzc3dvcmQ=" # Password is odspassword
    ---
    apiVersion: alloydbomni.dbadmin.goog/v1
    kind: DBCluster
    metadata:
      name: subscriber
    spec:
      primarySpec:
        adminUser:
          passwordRef:
            name: db-pw-subscriber
        databaseVersion: "15.7.0"
        resources:
          memory: 10Gi
          cpu: 1
          disks:
          - name: DataDisk
            size: 40Gi
    EOF
    

Configura el clúster de publicador

Configura el clúster del publicador y crea una tabla. De manera opcional, puedes publicar los datos como una prueba para asegurarte de que se repliquen en el suscriptor.

  1. Actualiza el parámetro wal_level a logical.

    $ kubectl patch dbclusters.al publisher  -p '{"spec":{"primarySpec":{"parameters":{"wal_level":"logical"}}}}' --type=merge
    
  2. Busca el pod que necesitas.

    $ kubectl get pod -l "alloydbomni.internal.dbadmin.goog/dbcluster=publisher, alloydbomni.internal.dbadmin.goog/task-type=database, dbs.internal.dbadmin.goog/ha-role=Primary"
    
  3. Accede al pod de base de datos del clúster del publicador.

    NAME                                          READY   STATUS    RESTARTS   AGE
    al-2bce-publisher-0                           3/3     Running   0          36m
    $ kubectl exec -ti al-2bce-publisher-0  -- /bin/bash
    
  4. Crea una base de datos llamada customer.

    CREATE DATABASE customer;
    
  5. Opcional: Para fines de prueba, agrega una tabla a la base de datos y, luego, inserta algunos datos. Puedes usar estos datos para observar la replicación de datos del publicador al suscriptor.

    $ psql -h localhost -U postgres customer
    customer=# CREATE TABLE COMPANY(
    customer(#    ID INT PRIMARY KEY     NOT NULL,
    customer(#    NAME           TEXT    NOT NULL,
    customer(#    AGE            INT     NOT NULL,
    customer(#    SALARY         REAL
    customer(# );
    CREATE TABLE
    customer=# INSERT INTO COMPANY (ID,NAME,AGE,SALARY) VALUES
    customer-# (1, 'Quinn', 25, 65000.00),
    customer-# (2, 'Kim', 22, 72250.00),
    customer-# (3, 'Bola', 31, 53000.00),
    customer-# (4, 'Sasha', 33, 105000.00),
    customer-# (5, 'Yuri', 27, 85000.00);
    INSERT 0 5
    customer=# \dt
              List of relations
    Schema |  Name   | Type  |  Owner
    --------+---------+-------+----------
    public | company | table | postgres
    (1 row)
    
    customer=# select * from company;
    id | name  | age | salary
    ----+-------+-----+--------
      1 | Quinn  |  25 |  65000
      2 | Kim  |  22 |  72250
      3 | Bola   |  31 |  53000
      4 | Sasha |  33 | 105000
      5 | Yuri |  27 |  85000
    (5 rows)
    
  6. Crea un usuario logicalreplica para la replicación y para otorgarle permisos.

    CREATE USER logicalreplica WITH REPLICATION LOGIN PASSWORD '123';
    
  7. Otorgar permisos En este ejemplo, se usa un esquema público.

    GRANT SELECT ON ALL TABLES IN SCHEMA public TO logicalreplica;
    GRANT USAGE ON SCHEMA public TO logicalreplica;
    ALTER DEFAULT PRIVILEGES IN SCHEMA public
        GRANT SELECT ON TABLES TO logicalreplica;
    
  8. Crea una publicación en la base de datos de customer.

    CREATE PUBLICATION pub_customer;
    ALTER PUBLICATION pub_customer ADD TABLE company;
    

Configura el clúster de suscriptores

Habilita el clúster de suscriptores para que reciba actualizaciones de datos del clúster de publicador.

  1. Establece el parámetro wal_level en logical en la base de datos de suscriptores.

    $ kubectl patch dbclusters.al subscriber  -p '{"spec":{"primarySpec":{"parameters":{"wal_level":"logical"}}}}' --type=merge
    
  2. Busca el pod que necesitas.

    $ kubectl get pod -l "alloydbomni.internal.dbadmin.goog/dbcluster=subscriber, alloydbomni.internal.dbadmin.goog/task-type=database, dbs.internal.dbadmin.goog/ha-role=Primary"
    
  3. Accede al pod de la base de datos del clúster de suscriptores.

    $ kubectl get pod
    NAME                                          READY   STATUS    RESTARTS   AGE
    al-2bce-publisher-0                           3/3     Running   0          20h
    
    $ kubectl exec -ti al-3513-subscriber-0  -- /bin/bash
    Defaulted container "database" out of: database, logrotate-agent, memoryagent, dbinit (init)
    postgres@al-3513-subscriber-0:/$
    
  4. Busca la dirección IP del pod del publicador, como 10.116.14.190.

    $ kubectl get service
    NAME                     TYPE           CLUSTER-IP      EXTERNAL-IP    PORT(S)          AGE
    al-publisher-rw-ilb      ClusterIP      10.116.14.190   <none>         5432/TCP         21h
    
  5. Crea una copia de seguridad del esquema del publicador como una copia inicial de los datos publicados en la base de datos del publicador. La replicación lógica no admite la replicación de DDL. Un esquema o una tabla que planeas replicar debe existir en el destino (clúster de suscriptores) antes de que comience la replicación lógica.

    postgres@al-3513-subscriber-0:/$ pg_dump -h 10.116.14.190 -U postgres --create --schema-only customer > /tmp/customer.schema-only.sql
    
  6. Aplica la copia de seguridad en la base de datos de suscriptores.

    postgres@al-3513-subscriber-0:/$ psql -h localhost -U postgres < /tmp/customer.schema-only.sql
    
  7. Opcional: Verifica que no haya datos en la tabla.

    # There is no data in table company
    customer=# select * from company;
    id | name | age | salary
    ----+------+-----+--------
    (0 rows)
    
  8. Crea una suscripción para la base de datos customer.

    postgres@al-3513-subscriber-0:/$ psql -h localhost -U postgres customer
    customer=# CREATE SUBSCRIPTION sub_customer CONNECTION 'host=10.116.14.190 port=5432 user=logicalreplica dbname=customer password=123' PUBLICATION pub_customer;
    
  9. Opcional: Verifica la replicación en el clúster de suscriptores.

    postgres@al-3513-subscriber-0:/$ psql -h localhost -U postgres customer
    customer=# select * from public.company;
    id | name  | age | salary
    ----+-------+-----+--------
      1 | Quinn |  25 |  65000
      2 | Kim   |  22 |  72250
      3 | Bola  |  31 |  53000
      4 | Sasha |  33 | 105000
      5 | Yuri  |  27 |  85000
    (5 rows)
    
  10. En el clúster del publicador, agrega una fila a la tabla.

    # On the publisher database
    $ kubectl exec -ti al-2bce-publisher-0  -- /bin/bash
    Defaulted container "database" out of: database, logrotate-agent, memoryagent, dbinit (init)
    postgres@al-2bce-publisher-0:/$ psql -h localhost -U postgres customer
    customer=# insert into company(id, name, age, salary) values (6, 'Alex', 39, 100000);
    
  11. En el clúster de suscriptores, verifica que la fila agregada a la tabla en el clúster de publicador se haya replicado en la tabla del clúster de suscriptores.

    # On the subscriber database, data is synced.
    postgres@al-3513-subscriber-0:/$ psql -h localhost -U postgres customer
    customer=# select * from company;
    id | name  | age | salary
    ----+-------+-----+--------
      1 | Quinn |  25 |  65000
      2 | Kim   |  22 |  72250
      3 | Bola  |  31 |  53000
      4 | Sasha |  33 | 105000
      5 | Yuri  |  27 |  85000
      6 | Alex  |  39 | 100000
    (6 rows)
    

Crea tablas adicionales de forma manual

La replicación lógica no sincroniza automáticamente los cambios de DDL, a diferencia de replicate_ddl_command en pglogical. Si bien la herramienta de código abierto pgl_ddl_deploy ofrece una solución, también puedes ejecutar comandos DDL de forma manual en el suscriptor.

  1. Para ilustrar esto, crea una tabla nueva llamada finance en la base de datos customer en el clúster del publicador.

    # On the publisher database
    $ kubectl exec -ti al-2bce-publisher-0  -- /bin/bash
    Defaulted container "database" out of: database, logrotate-agent, memoryagent, dbinit (init)
    postgres@al-2bce-publisher-0:/$ psql -h localhost -U postgres customer
    customer=# create table finance (row text);
    CREATE TABLE
    customer=# insert into finance values ('critical data');
    INSERT 0 1
    customer=# ALTER PUBLICATION pub_customer ADD TABLE finance;
    ALTER PUBLICATION
    
  2. Cuando se agrega una tabla nueva al clúster del publicador, aplicas manualmente el DDL (creación de tablas) en el suscriptor y, luego, verificas la replicación ejecutando lo siguiente en el clúster del suscriptor.

    postgres@al-3513-subscriber-0:/$ psql -h localhost -U postgres customer
    customer=# create table finance (row text);
    CREATE TABLE
    customer=# ALTER SUBSCRIPTION sub_customer REFRESH PUBLICATION;
    ALTER SUBSCRIPTION
    customer=# select * from finance;
          row
    ---------------
    critical data
    (1 row)
    

¿Qué sigue?