Kubernetes์—์„œ ๋…ผ๋ฆฌ์  ๋ณต์ œ ๊ตฌ์„ฑ

๋ฌธ์„œ ๋ฒ„์ „์„ ์„ ํƒํ•ฉ๋‹ˆ๋‹ค.

PostgreSQL์—์„œ ๋…ผ๋ฆฌ ๋ณต์ œ๋Š” ๊ฒŒ์‹œ์ž ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์—์„œ ๋ฐ์ดํ„ฐ ๋ณ€๊ฒฝ์‚ฌํ•ญ์„ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๋˜๋Š” ๊ธฐํƒ€ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ผ ์ˆ˜ ์žˆ๋Š” ํ•˜๋‚˜ ์ด์ƒ์˜ ๊ตฌ๋…์ž๋กœ ๋ณต์‚ฌํ•˜๋Š” ๋ฐฉ๋ฒ•์ž…๋‹ˆ๋‹ค. AlloyDB Omni Kubernetes ์—ฐ์‚ฐ์ž๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋งŒ๋“  ํด๋Ÿฌ์Šคํ„ฐ์—์„œ ๋…ผ๋ฆฌ์  ๋ณต์ œ๋ฅผ ์‚ฌ์šฉ ์„ค์ •ํ•˜๊ณ  ๊ตฌ์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ด ๋ฌธ์„œ์—์„œ๋Š” ๊ฒŒ์‹œ์ž ํด๋Ÿฌ์Šคํ„ฐ์™€ ๊ตฌ๋…์ž ํด๋Ÿฌ์Šคํ„ฐ๋ฅผ ๋งŒ๋“ค๊ณ  ๊ตฌ์„ฑํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ๋ณด์—ฌ์ฃผ๋Š” ์˜ˆ๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. ์ด ๋ฌธ์„œ๋ฅผ ์ฝ๊ธฐ ์ „์— AlloyDB Omni ๊ฐœ์š”๋ฅผ ์ˆ™์ง€ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. PostgreSQL ๋…ผ๋ฆฌ ๋ณต์ œ์˜ ์ œํ•œ์‚ฌํ•ญ๋„ ์•Œ์•„์•ผ ํ•ฉ๋‹ˆ๋‹ค.

์ด ํŽ˜์ด์ง€์˜ ์ฝ”๋“œ ์Šค๋‹ˆํŽซ์€ ๊ฐ’์„ ์ž์ฒด AlloyDB Omni ๋ฆฌ์†Œ์Šค์˜ ๊ฐ’์œผ๋กœ ๋Œ€์ฒดํ•˜์—ฌ ๋ชจ๋ธ๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ์˜ˆ์‹œ์ž…๋‹ˆ๋‹ค.

ํด๋Ÿฌ์Šคํ„ฐ ๋งŒ๋“ค๊ธฐ

  1. Kubernetes์— Omni Operator๋ฅผ ์„ค์น˜ํ•ฉ๋‹ˆ๋‹ค.

  2. ๊ฒŒ์‹œ์ž ํด๋Ÿฌ์Šคํ„ฐ๋ฅผ ๋งŒ๋“ญ๋‹ˆ๋‹ค.

    $ 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.5.4"
        resources:
          memory: 10Gi
          cpu: 1
          disks:
          - name: DataDisk
            size: 40Gi
    EOF
    
  3. ๊ตฌ๋…์ž ํด๋Ÿฌ์Šคํ„ฐ๋ฅผ ๋งŒ๋“ญ๋‹ˆ๋‹ค.

    $ 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.5.4"
        resources:
          memory: 10Gi
          cpu: 1
          disks:
          - name: DataDisk
            size: 40Gi
    EOF
    

๊ฒŒ์‹œ์ž ํด๋Ÿฌ์Šคํ„ฐ ๊ตฌ์„ฑ

๊ฒŒ์‹œ์ž ํด๋Ÿฌ์Šคํ„ฐ๋ฅผ ๊ตฌ์„ฑํ•˜๊ณ  ํ…Œ์ด๋ธ”์„ ๋งŒ๋“ญ๋‹ˆ๋‹ค. ์„ ํƒ์ ์œผ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ํ…Œ์ŠคํŠธ๋กœ ๊ฒŒ์‹œํ•˜์—ฌ ๊ตฌ๋…์ž์—๊ฒŒ ๋ณต์ œ๋˜๋Š”์ง€ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

  1. wal_level ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ logical๋กœ ์—…๋ฐ์ดํŠธํ•ฉ๋‹ˆ๋‹ค.

    $ kubectl patch dbclusters.al publisher  -p '{"spec":{"primarySpec":{"parameters":{"wal_level":"logical"}}}}' --type=merge
    
  2. ํ•„์š”ํ•œ ํฌ๋“œ๋ฅผ ์ฐพ์Šต๋‹ˆ๋‹ค.

    $ 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. ๊ฒŒ์‹œ์ž ํด๋Ÿฌ์Šคํ„ฐ์˜ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ํฌ๋“œ์— ๋กœ๊ทธ์ธํ•ฉ๋‹ˆ๋‹ค.

    NAME                                          READY   STATUS    RESTARTS   AGE
    al-2bce-publisher-0                           3/3     Running   0          36m
    $ kubectl exec -ti al-2bce-publisher-0  -- /bin/bash
    
  4. customer๋ผ๋Š” ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋ฅผ ๋งŒ๋“ญ๋‹ˆ๋‹ค.

    CREATE DATABASE customer;
    
  5. ์„ ํƒ์‚ฌํ•ญ: ํ…Œ์ŠคํŠธ ๋ชฉ์ ์œผ๋กœ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ํ…Œ์ด๋ธ”์„ ์ถ”๊ฐ€ํ•˜๊ณ  ๋ฐ์ดํ„ฐ๋ฅผ ์‚ฝ์ž…ํ•ฉ๋‹ˆ๋‹ค. ์ด ๋ฐ์ดํ„ฐ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๊ฒŒ์‹œ์ž์—์„œ ๊ตฌ๋…์ž๋กœ์˜ ๋ฐ์ดํ„ฐ ๋ณต์ œ๋ฅผ ๊ด€์ฐฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

    $ 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. ๋ณต์ œ ๋ฐ ๊ถŒํ•œ ๋ถ€์—ฌ๋ฅผ ์œ„ํ•œ ์‚ฌ์šฉ์ž logicalreplica๋ฅผ ๋งŒ๋“ญ๋‹ˆ๋‹ค.

    CREATE USER logicalreplica WITH REPLICATION LOGIN PASSWORD '123';
    
  7. ๊ถŒํ•œ ๋ถ€์—ฌ ์ด ์˜ˆ์‹œ์—์„œ๋Š” ๊ณต๊ฐœ ์Šคํ‚ค๋งˆ๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

    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. customer ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ๊ฒŒ์‹œ๋ฅผ ๋งŒ๋“ญ๋‹ˆ๋‹ค.

    CREATE PUBLICATION pub_customer;
    ALTER PUBLICATION pub_customer ADD TABLE company;
    

๊ตฌ๋…์ž ํด๋Ÿฌ์Šคํ„ฐ ๊ตฌ์„ฑ

๊ฒŒ์‹œ์ž ํด๋Ÿฌ์Šคํ„ฐ์—์„œ ๋ฐ์ดํ„ฐ ์—…๋ฐ์ดํŠธ๋ฅผ ์ˆ˜์‹ ํ•˜๋„๋ก ๊ตฌ๋…์ž ํด๋Ÿฌ์Šคํ„ฐ๋ฅผ ์‚ฌ์šฉ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค.

  1. ๊ตฌ๋…์ž ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์—์„œ wal_level ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ logical๋กœ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค.

    $ kubectl patch dbclusters.al subscriber  -p '{"spec":{"primarySpec":{"parameters":{"wal_level":"logical"}}}}' --type=merge
    
  2. ํ•„์š”ํ•œ ํฌ๋“œ๋ฅผ ์ฐพ์Šต๋‹ˆ๋‹ค.

    $ 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. ๊ตฌ๋…์ž ํด๋Ÿฌ์Šคํ„ฐ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ํฌ๋“œ์— ๋กœ๊ทธ์ธํ•ฉ๋‹ˆ๋‹ค.

    $ 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. 10.116.14.190๊ณผ ๊ฐ™์€ ๊ฒŒ์‹œ์ž ํฌ๋“œ์˜ IP ์ฃผ์†Œ๋ฅผ ์ฐพ์Šต๋‹ˆ๋‹ค.

    $ 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. ๊ฒŒ์‹œ์ž ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์˜ ๊ฒŒ์‹œ๋œ ๋ฐ์ดํ„ฐ ์ดˆ๊ธฐ ์‚ฌ๋ณธ์œผ๋กœ ๊ฒŒ์‹œ์ž์—์„œ ์Šคํ‚ค๋งˆ ๋ฐฑ์—…์„ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค. ๋…ผ๋ฆฌ์  ๋ณต์ œ๋Š” DDL ๋ณต์ œ๋ฅผ ์ง€์›ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๋…ผ๋ฆฌ์  ๋ณต์ œ๊ฐ€ ์‹œ์ž‘๋˜๊ธฐ ์ „์— ๋ณต์ œํ•˜๋ ค๋Š” ์Šคํ‚ค๋งˆ ๋˜๋Š” ํ…Œ์ด๋ธ”์ด ๋Œ€์ƒ(๊ตฌ๋…์ž ํด๋Ÿฌ์Šคํ„ฐ)์— ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

    postgres@al-3513-subscriber-0:/$ pg_dump -h 10.116.14.190 -U postgres --create --schema-only customer > /tmp/customer.schema-only.sql
    
  6. ๊ตฌ๋…์ž ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ๋ฐฑ์—…์„ ์ ์šฉํ•ฉ๋‹ˆ๋‹ค.

    postgres@al-3513-subscriber-0:/$ psql -h localhost -U postgres < /tmp/customer.schema-only.sql
    
  7. ์„ ํƒ์‚ฌํ•ญ: ํ…Œ์ด๋ธ”์— ๋ฐ์ดํ„ฐ๊ฐ€ ์—†๋Š”์ง€ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค.

    # There is no data in table company
    customer=# select * from company;
    id | name | age | salary
    ----+------+-----+--------
    (0 rows)
    
  8. ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค 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. ์„ ํƒ์‚ฌํ•ญ: ๊ฒŒ์‹œ์ž ํด๋Ÿฌ์Šคํ„ฐ์—์„œ ๋ณต์ œ๋ฅผ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค.

    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. ๊ฒŒ์‹œ์ž ํด๋Ÿฌ์Šคํ„ฐ์—์„œ ํ…Œ์ด๋ธ”์— ํ–‰์„ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค.

    # 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. ๊ตฌ๋…์ž ํด๋Ÿฌ์Šคํ„ฐ์—์„œ ๊ฒŒ์‹œ์ž ํด๋Ÿฌ์Šคํ„ฐ์˜ ํ…Œ์ด๋ธ”์— ์ถ”๊ฐ€๋œ ํ–‰์ด ๊ตฌ๋…์ž ํด๋Ÿฌ์Šคํ„ฐ์˜ ํ…Œ์ด๋ธ”์— ๋ณต์ œ๋˜์—ˆ๋Š”์ง€ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค.

    # 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)
    

์ถ”๊ฐ€ ํ…Œ์ด๋ธ” ์ˆ˜๋™์œผ๋กœ ๋งŒ๋“ค๊ธฐ

๋…ผ๋ฆฌ์  ๋ณต์ œ๋Š” pglogical์˜ replicate_ddl_command์™€ ๋‹ฌ๋ฆฌ DDL ๋ณ€๊ฒฝ์‚ฌํ•ญ์„ ์ž๋™์œผ๋กœ ๋™๊ธฐํ™”ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์˜คํ”ˆ์†Œ์Šค ๋„๊ตฌ pgl_ddl_deploy์—์„œ ์†”๋ฃจ์…˜์„ ์ œ๊ณตํ•˜์ง€๋งŒ ๊ตฌ๋…์ž์—์„œ DDL ๋ช…๋ น์–ด๋ฅผ ์ˆ˜๋™์œผ๋กœ ์‹คํ–‰ํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.

  1. ์ด๋ฅผ ์‚ดํŽด๋ณด๊ธฐ ์œ„ํ•ด ๊ฒŒ์‹œ์ž ํด๋Ÿฌ์Šคํ„ฐ์˜ customer ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— finance๋ผ๋Š” ์ƒˆ ํ…Œ์ด๋ธ”์„ ๋งŒ๋“ญ๋‹ˆ๋‹ค.

    # 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. ๊ฒŒ์‹œ์ž ํด๋Ÿฌ์Šคํ„ฐ์— ์ƒˆ ํ…Œ์ด๋ธ”์ด ์ถ”๊ฐ€๋˜๋ฉด ๊ตฌ๋…์ž์—์„œ DDL(ํ…Œ์ด๋ธ” ์ƒ์„ฑ)์„ ์ˆ˜๋™์œผ๋กœ ์ ์šฉํ•œ ๋‹ค์Œ ๊ตฌ๋…์ž ํด๋Ÿฌ์Šคํ„ฐ์—์„œ ๋‹ค์Œ์„ ์‹คํ–‰ํ•˜์—ฌ ๋ณต์ œ๋ฅผ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค.

    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)
    

๋‹ค์Œ ๋‹จ๊ณ„