pgpool2 를 이용한 이중화 셋팅 (k3s)

2025. 12. 26. 21:16·DB/Postgresql
반응형

얼마전에 DB 서버 2대에 patroni를 이용하여 이중화를 했다.

patroni는 서버를 모니터하면서 master 와 slave 를 관리해준다.

이제는 이 서버에 적절히 분배해 주면서 앞단에서 로드밸런서 역할도 하고 쿼리 종류에 따라 Write 는 master 로 Read 는 두 서버를 적절히 분산을... 하기위해 pgpool 을 적용했다.

 

쿼리를 분석해서 자동 분기를 해주는 솔루션은 pgpool 이 거의 유일하다고 한다.

개발자가 WAS 의 소스코드 레벨에서 ORM 등을 사용하여 두개의 역할을 나눠서 알아서 나눠서 호출하게 할수는 있지만 이미 만들어진 WAS서버에서 다시 고쳐서 쓰기는 번거롭다.

 

자동으로 해주는 솔루션을 찾다보니 pgpool 을 이용하게 되었다.

일전에 했다가..별로여서 안쓰고 있었는데 학습차원에서 다시 했고 k3s 에 적용했다.

 

결론적으로 굉장히 많은 시행 착오를 겪었다. 오늘하루를 다 썼는데...

그 기록을 남기려고 한다.

 

결론적으로 k3s 서버에 아래 두개의 파일을 만들었다.

귀찮아서 몇개를 합치긴 했다.

drwxr-xr-x 2 root root 4096 Dec 26 10:46 ./
drwxr-xr-x 7 root root 4096 Dec 26 02:38 ../
-rw-r--r-- 1 root root 5471 Dec 26 10:46 deployment.yaml
-rw-r--r-- 1 root root  378 Dec 26 06:33 service.yaml
root@k3s-node1:/k8s/apps/pgpool#

 

먼저 디플로이

root@k3s-node1:/k8s/apps/pgpool# cat deployment.yaml 
# ---------------------------------------------------------
# 1. ConfigMap 정의 (pool_hba.conf 설정)
# ---------------------------------------------------------
apiVersion: v1
kind: ConfigMap
metadata:
  name: pgpool-hba-config
  namespace: default
data:
  pool_hba.conf: |
    # 로컬 접속 허용
    local   all             all                                     trust
    # 외부 접속 허용 (md5 인증 사용)
    host    all             all             0.0.0.0/0               md5 

---
apiVersion: v1
kind: Secret
metadata:
  name: postgres-secrets
  namespace: default
type: Opaque
stringData:
  postgres-password: "비번"  # 실제 비밀번호로 변경
  replicator-password: "비번"   # 복제용 유저
---
apiVersion: v1
kind: Secret
metadata:
  name: pgpool-passwd
  namespace: default
type: Opaque
stringData:
  pool_passwd: |
    postgres:md~~~   # DB에 저장된 사용자의 암호화된 값
    rep_user:md~~~   # DB에 저장된 사용자의 암호화된 값
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: pgpool
  namespace: default
spec:
  replicas: 1
  selector:
    matchLabels:
      app: pgpool
  template:
    metadata:
      labels:
        app: pgpool
    spec:
      # initContainer로 Secret 파일을 쓰기 가능한 공간(/config-work)으로 복사
      initContainers:
        - name: setup-config
          image: busybox
          # pool_passwd는 읽어야 하고, pool_hba.conf는 entrypoint가 수정해야 하므로 쓰기 권한도 필요함
          command: ['sh', '-c', 'cp /config-src/* /config-work/ && chmod 666 /config-work/*']
          volumeMounts:
            - name: pool-passwd-vol
              mountPath: /config-src/pool_passwd
              subPath: pool_passwd
            - name: pool-hba-vol
              mountPath: /config-src/pool_hba.conf
              subPath: pool_hba.conf
            - name: pgpool-config-work
              mountPath: /config-work

      containers:
        - name: pgpool
          image: docker.io/pgpool/pgpool:4.4.3
          volumeMounts:
            # 복사된 쓰기 가능한 볼륨을 마운트
            - mountPath: /opt/pgpool-II/etc/pool_passwd
              name: pgpool-config-work
              subPath: pool_passwd
            - mountPath: /opt/pgpool-II/etc/pool_hba.conf
              name: pgpool-config-work
              subPath: pool_hba.conf
          env:
            - name: PGPOOL_PARAMS_BACKEND_HOSTNAME0
              value: "10.34.1.111"
            - name: PGPOOL_PARAMS_BACKEND_PORT0
              value: "5432"
            - name: PGPOOL_PARAMS_BACKEND_WEIGHT0
              value: "1"
            - name: PGPOOL_PARAMS_BACKEND_FLAG0
              value: "ALLOW_TO_FAILOVER"

            - name: PGPOOL_PARAMS_BACKEND_HOSTNAME1
              value: "10.34.1.112"
            - name: PGPOOL_PARAMS_BACKEND_PORT1
              value: "5432"
            - name: PGPOOL_PARAMS_BACKEND_WEIGHT1
              value: "1"
            - name: PGPOOL_PARAMS_BACKEND_FLAG1
              value: "ALLOW_TO_FAILOVER"

            # ... (기타 설정) ...
            - name: PGPOOL_PARAMS_NUM_INIT_CHILDREN
              value: "100"
            - name: PGPOOL_PARAMS_MAX_POOL
              value: "4"
            - name: PGPOOL_PARAMS_LOAD_BALANCE_MODE
              value: "on"
            - name: PGPOOL_PARAMS_SR_CHECK_PERIOD
              value: "10"
            - name: PGPOOL_PARAMS_SR_CHECK_USER
              value: "rep_user"
            - name: PGPOOL_PARAMS_SR_CHECK_PASSWORD
              valueFrom:
                secretKeyRef:
                  name: postgres-secrets
                  key: replicator-password
            - name: PGPOOL_PARAMS_SR_CHECK_DATABASE
              value: "postgres"
            - name: PGPOOL_PARAMS_HEALTH_CHECK_PERIOD
              value: "10"
            - name: PGPOOL_PARAMS_HEALTH_CHECK_USER
              value: "postgres"
            - name: PGPOOL_PARAMS_HEALTH_CHECK_PASSWORD
              valueFrom:
                secretKeyRef:
                  name: postgres-secrets
                  key: postgres-password
            - name: PGPOOL_PARAMS_HEALTH_CHECK_DATABASE
              value: "postgres"

            # [해결책 2] 인증 방식을 다시 SCRAM으로 변경 (백엔드와 통일)
            - name: PGPOOL_PARAMS_ENABLE_POOL_HBA
              value: "on"
            - name: PGPOOL_PARAMS_PWD_ENC_METHOD
              value: "md5"
            - name: PGPOOL_PARAMS_POOL_PASSWD
              value: "/opt/pgpool-II/etc/pool_passwd"
            - name: PGPOOL_PARAMS_PORT
              value: "5432"

          ports:
            - name: postgresql
              containerPort: 5432
            - name: pcp
              containerPort: 9898

          # Liveness/Readiness 등 기존 설정 유지...
          livenessProbe:
            tcpSocket:
              port: 5432
            initialDelaySeconds: 60
          readinessProbe:
            tcpSocket:
              port: 5432
            initialDelaySeconds: 30

      volumes:
        # [해결책 1] 작업을 위한 빈 볼륨 생성
        - name: pgpool-config-work
          emptyDir: {}
        # 원본 Secret 연결
        - name: pool-passwd-vol
          secret:
            secretName: pgpool-passwd
        - name: pool-hba-vol
          configMap:
            name: pgpool-hba-config

 

다음은 k3s 서비스

root@k3s-node1:/k8s/apps/pgpool# cat service.yaml 
apiVersion: v1
kind: Service
metadata:
  name: pgpool-lb
  namespace: default
  annotations:
    metallb.universe.tf/allow-shared-ip: "shared-lb"
spec:
  type: LoadBalancer
  selector:
    app: pgpool
  ports:
  - name: postgresql
    port: 5432
    targetPort: 5432
    protocol: TCP
  - name: pcp
    port: 9898
    targetPort: 9898
    protocol: TCP
  sessionAffinity: None

service 에서 shared-lb 는 하나의 아이피로 포트만 다르게 여러 서비스를 하기 위해서 사용중이다.

metallb 를 이용하여 vip를 사용했는데 계속 해서 ip를 늘려갈수는 없으니까...

사내에서 여유있는 ip 대역을 가지고 있다면 상관 없겠지만 클라우드 상에서 아이피를 늘리것은 다 돈이다.

그래서 최대한 아이피를 안 늘리는 상황으로 만들어 보았다.

 

결과적으로 위와 같이 해서 vip 10.34.1.150 5432 포트로 연결 성공 하였다.

하나하나 설명은 나도 모르니 패스...

 

가장 애를 먹었던 부분은 인증부분이다.

 

client -> pgpool -> db서버

이렇게 인증을 한다고 하는데

client -> pgpool 을 통과한것 같은데 계속 해서 backend (DB를 말한다.) 에 인증이 안된다는 오류를 오늘 하루종일 보았다.

GPT 에 질문을 몇번을 했는지 모르겠다.

 

SELECT concat(usename, ':', passwd) FROM pg_shadow WHERE usename IN ('postgres', 'rep_user');

 

이런식으로 DB에서 패스워드를 추출하여 상단 deployment.yaml 에 셋팅을 하게 되는데

postgres:SCRAM-SHA-256$4096:w1r3Sp4OL+LMrDdcp~~~
rep_user:SCRAM-SHA-256$4096:ngIDzkc8gUxBd6/vE~~~

 

처음에는 이런식으로 값이 나왔다. SCRAM 인증방식이고

두대의 서버 pg_hba 설정 파일에도

# IPv4 local connections:
host    all             all             127.0.0.1/32            scram-sha-256
# IPv6 local connections:
host    all             all             ::1/128                 scram-sha-256
# Allow replication connections from localhost, by a user with the
# replication privilege.
local   replication     all                                     peer
host    replication     all             127.0.0.1/32            scram-sha-256
host    replication     all             ::1/128                 scram-sha-256

이렇게 되어 있었다.

 

그런데 아무리 해도 안되더라...

그래서 인증방식을 md5 로 바꿨다.

-- 1. 현재 세션의 암호화 방식을 md5로 강제 설정
SET password_encryption = 'md5';

-- 2. postgres 유저 비밀번호 재설정 (다시 MD5로 해시됨)
-- (기존 비밀번호 '비번'를 그대로 입력)
ALTER USER postgres WITH PASSWORD '비번';

-- 3. rep_user 유저 비밀번호 재설정
ALTER USER rep_user WITH PASSWORD '비번';

-- 4. 확인 (rolpassword가 'md5...' 로 시작해야 성공)
SELECT rolname, rolpassword FROM pg_authid WHERE rolname IN ('postgres', 'rep_user');

 

그러면 실제 값도 바뀌어져 있다.

postgres:md5~~
rep_user:md5~~

그리고 최종적으로 상단의 설정으로 바꿨다.

 

처음엔 ... 이렇게 해도 안되던데... db서버를 모두 재부팅 해봤는데 적용되었다.

gpt 물어보면 재부팅을 안하고 리로드만 해도 된다고 하는데 리로드를 몇번이나 해봤는지 모르겠다.

 

이렇게 2개의 서버와 pgpool 연결된 1개의 서버를 확인할수 있다.

그러면 로드밸런스가 잘 되는지 확인 해볼까?

for i in {1..10}; do
  kubectl exec deployment/pgpool -- sh -c "export PGPASSWORD='비번'; psql -h 127.0.0.1 -U postgres -d postgres -c 'SELECT inet_server_addr(), pg_is_in_recovery();'"
  sleep 1
done

 

노드1번에서 이렇게 해봤더니 10번이 모두 1번 서버로 나온다... 뭔가 이상하다.

root@k3s-node1:/k8s/apps/pgpool# kubectl exec -it deployment/pgpool -- psql -h 127.0.0.1 -U postgres -c "show pool_nodes;"
Defaulted container "pgpool" out of: pgpool, setup-config (init)
Password for user postgres: 
 node_id |  hostname   | port | status | pg_status | lb_weight |  role   | pg_role | select_cnt | load_balance_node | replication_delay | replication_state | replication_sync_state | last_status_change  
---------+-------------+------+--------+-----------+-----------+---------+---------+------------+-------------------+-------------------+-------------------+------------------------+---------------------
 0       | 10.34.1.111 | 5432 | up     | up        | 0.500000  | primary | primary | 312        | false             | 0                 |                   |                        | 2025-12-26 10:52:34
 1       | 10.34.1.112 | 5432 | up     | up        | 0.500000  | standby | standby | 72         | true              | 0                 |                   |                        | 2025-12-26 10:52:34
(2 rows)

root@k3s-node1:/k8s/apps/pgpool#

 

둘다 up 이고 모두 정상이라고 GPT는 말하긴 한다...

그런데 계속 한쪽으로만 나온다.

 

검색을 해보니

PGPOOL_PARAMS_STATEMENT_LEVEL_LOAD_BALANCE 이 옵션을 켜라고 한다.

 

해봤다...

정말 두 서버를 왔다갔다 하더라...

 

 

그런데 좀 더 검색을 해보니 pgpool 이 한번 접속한 사용자는 동일하게 한쪽으로 보낸다고 한다.

세션방식이라서..근데 위 옵션을 ON으로 하면 요청 올때마다 로드밸런싱을 한다고 하네..

 

결국 나 혼자 하니까 그랬던 것..

반응형

'DB > Postgresql' 카테고리의 다른 글

(연습) postgresql 이중화 (Failover)  (0) 2025.12.07
(연습) postgreSQL 이중화 (consul, patroni)  (0) 2025.12.07
pgpool 4.1.4 auto fail-over, fail-back  (2) 2021.06.20
pgpool II 4.1.4 load balance  (0) 2021.06.19
postgresql replication 수동 fail-over / fail-back  (0) 2021.06.19
'DB/Postgresql' 카테고리의 다른 글
  • (연습) postgresql 이중화 (Failover)
  • (연습) postgreSQL 이중화 (consul, patroni)
  • pgpool 4.1.4 auto fail-over, fail-back
  • pgpool II 4.1.4 load balance
GG.Lab
GG.Lab
GG.Lab
    반응형
  • GG.Lab
    GG.Lab
    GG.Lab
  • 전체
    오늘
    어제
    • 분류 전체보기 (51) N
      • APP (25)
        • 함쓰가계부 (22)
        • 랭킹구구단 (3)
      • 인프라 (18)
        • Docker (1)
        • Proxmox (4)
        • Kubernetes (8)
        • Network (3)
        • Cloudflare (2)
      • DB (8) N
        • Postgresql (8) N
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
    • 함쓰 메뉴얼
    • 함쓰 카페
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    Proxmox
    함쓰가계부
    PostgreSQL
    pfsense
    연인가계부
    문자자동인식
    플러터
    external-svc
    자작앱
    Kubernetes
    K8s
    Flutter
    해외통화지원
    postgresql이중화
    구구단
    공유가계부
    함쓰
    커플가계부
    쿠버네티스
    sms인식가계부
    부부가계부
    k3s외부서비스
    traefik
    문자자동인식가계부
    함께쓰는가계부
    patroni
    앱출시
    가계부편의기능
    k3s
    해외통화가계부
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.5
GG.Lab
pgpool2 를 이용한 이중화 셋팅 (k3s)
상단으로

티스토리툴바