콘텐츠로 이동

MariaDB 10.11 Galera Cluster 구성 가이드 (폐쇄망)

Rocky Linux 9.6 환경에서 MariaDB 10.11 Galera Cluster 3중화를 구성하는 절차입니다. 단일 노드 설치는 MariaDB 오프라인 설치 가이드를 참조하세요.

전제 조건

  • Rocky Linux 9.6 서버 3대 (폐쇄망)
  • 각 서버에 mariadb-10.11.14-rocky9.6/ 디렉토리가 반입되어 있을 것
  • 일반 사용자 계정 (sudo 권한 필수)

클러스터 구성 정보

호스트명 역할 IP 비고
galera-cluster-1 Primary (Bootstrap) IP_1 최초 클러스터 시작
galera-cluster-2 Member IP_2
galera-cluster-3 Member IP_3
  • Cluster Name: my_galera_svc
  • SST Method: mariabackup

Phase 1: OS 및 네트워크 설정 (3대 공통)

1-1. 호스트 파일 등록

IP 확정 후 3대 서버 모두 동일하게 수정합니다.

sudo vi /etc/hosts
192.168.XXX.XX   galera-cluster-1
192.168.XXX.XX   galera-cluster-2
192.168.XXX.XX   galera-cluster-3

1-2. 호스트네임 변경

각 서버 번호에 맞게 실행합니다.

sudo hostnamectl set-hostname galera-cluster-1

1-3. SELinux Permissive 전환

sudo setenforce 0
sudo sed -i 's/^SELINUX=enforcing/SELINUX=permissive/' /etc/selinux/config

1-4. 방화벽 포트 오픈

sudo firewall-cmd --permanent --add-port={3306,4567,4568,4444}/tcp
sudo firewall-cmd --permanent --add-port=4567/udp
sudo firewall-cmd --reload
포트 프로토콜 용도
3306 TCP MySQL 클라이언트 접속
4567 TCP/UDP Galera 클러스터 통신 (gcomm)
4568 TCP IST (Incremental State Transfer)
4444 TCP SST (State Snapshot Transfer)

Phase 2: RPM 설치 (3대 공통)

2-1. 기본 모듈 비활성화

Rocky 9 내장 MariaDB와의 충돌을 방지합니다.

sudo dnf module disable mariadb -y --disablerepo=*

missing groups or modules: mariadb 오류가 나오면 충돌 위험이 없으므로 무시합니다.

2-2. 공통 의존성 설치

sudo dnf localinstall -y --disablerepo='*' --skip-broken common/rpms/*.rpm

2-3. DB 및 Galera 패키지 설치

sudo dnf localinstall -y --disablerepo='*' --skip-broken db/rpms/*.rpm

2-4. 서비스 등록 (시작하지 않음)

sudo systemctl enable mariadb

2-5. 데이터 디렉토리 구성 (경로 변경 시)

기본 경로(/var/lib/mysql)를 사용한다면 이 단계는 건너뜁니다.

# 디렉토리 생성
sudo mkdir -p /app/mariadb_data

# 소유권 설정 (mysql 계정은 RPM 설치 시 자동 생성)
sudo chown -R mysql:mysql /app/mariadb_data
sudo chmod 750 /app/mariadb_data

# DB 초기화 (커스텀 경로에는 시스템 테이블이 없으므로 필수)
sudo mysql_install_db --user=mysql --datadir=/app/mariadb_data

Phase 3: Galera 설정 파일 작성 (3대 공통)

/etc/my.cnf.d/01-galera.cnf 파일을 생성합니다. 서버마다 wsrep_node_addresswsrep_node_name 값을 변경해야 합니다.

sudo vi /etc/my.cnf.d/01-galera.cnf
[mariadb]
# --- 기본 설정 ---
# 데이터 경로를 옮길 때만 사용
# datadir=/app/mariadb_data
bind-address=0.0.0.0
default_storage_engine=InnoDB
binlog_format=ROW
innodb_autoinc_lock_mode=2

# --- 튜닝 ---
lower_case_table_names=1
max_connections=1000
sql_mode="STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION"

# --- Galera Provider ---
wsrep_on=ON
wsrep_provider=/usr/lib64/galera-4/libgalera_smm.so

# --- 클러스터 공통 (3대 동일) ---
wsrep_cluster_name="my_galera_svc"
wsrep_cluster_address="gcomm://IP_1,IP_2,IP_3"

# --- 노드별 고유 설정 (서버마다 수정!) ---
wsrep_node_address="본인_서버_IP"
wsrep_node_name="galera-cluster-X"

# --- 동기화 ---
wsrep_sst_method=mariabackup

서버별 변경 요약:

서버 wsrep_node_address wsrep_node_name
1번 IP_1 galera-cluster-1
2번 IP_2 galera-cluster-2
3번 IP_3 galera-cluster-3

Phase 4: 클러스터 기동 (순서 준수)

4-1. galera-cluster-1 (Bootstrap)

반드시 1번 서버에서 가장 먼저 실행합니다.

sudo galera_new_cluster

# 클러스터 사이즈 확인 (1이어야 함)
sudo mariadb -u root -e "SHOW STATUS LIKE 'wsrep_cluster_size';"

4-2. galera-cluster-2

sudo systemctl start mariadb

# 클러스터 사이즈 확인 (2로 증가)
sudo mariadb -u root -e "SHOW STATUS LIKE 'wsrep_cluster_size';"

4-3. galera-cluster-3

sudo systemctl start mariadb

# 최종 확인 (3이어야 함)
sudo mariadb -u root -e "SHOW STATUS LIKE 'wsrep_cluster_size';"

Phase 5: 검증

5-1. 복제 테스트

1번 노드에서 DB를 생성하고 3번 노드에서 확인합니다.

# Node 1
sudo mariadb -u root -e "CREATE DATABASE galera_test_db;"

# Node 3
sudo mariadb -u root -e "SHOW DATABASES;"

galera_test_db가 보이면 3중화 성공입니다.

5-2. K8s 노드 연결 (필요 시)

다른 노드의 K8s에서 접속해야 할 경우 IP 허용 규칙을 추가합니다.

-- 전용 계정 생성 ('20.%'는 20.x.x.x 대역 전체 허용)
CREATE USER 'k8s_app_user'@'20.%' IDENTIFIED BY 'K8s_Passw0rd!';
GRANT ALL PRIVILEGES ON *.* TO 'k8s_app_user'@'20.%';
FLUSH PRIVILEGES;

K8s에서 연결 확인:

# 임시 파드 생성
kubectl run tmp-shell --rm -it \
  --image=docker.io/library/busybox:latest \
  --image-pull-policy=Never \
  --restart=Never -- sh

# 파드 내부에서 연결 테스트
telnet <IP_1> 3306

Phase 6: 장애 복구 (Full Crash Recovery)

모든 노드가 비정상 종료되어 서비스가 전면 중단된 경우의 복구 절차입니다.

본 가이드는 /app/mariadb_data 경로를 기준으로 작성되었습니다. 실제 서버의 데이터 경로가 다를 수 있으므로 명령어 실행 전 반드시 확인하세요.

6-1. 복구 논리

  • 최신 트랜잭션 판별: 모든 노드가 다운된 경우, 가장 최신 트랜잭션(seqno)을 보유한 노드를 찾아 Primary로 승격시켜야 데이터 유실 및 전체 동기화(SST)를 방지할 수 있습니다.
  • 커스텀 경로 스캔: 데이터가 커스텀 경로에 저장된 경우, --datadir 옵션을 반드시 명시해야 합니다.

6-2. 복구 절차

1단계: Primary 노드 판별

3대 서버 모두에서 MariaDB 프로세스가 없는지 확인한 후 트랜잭션 번호를 추출합니다.

# 잔여 프로세스 확인
ps -ef | grep mysql

# 복구 위치(seqno) 추출
sudo /usr/sbin/mariadbd --wsrep-recover --datadir=/app/mariadb_data

로그 마지막의 Recovered position: UUID:seqno 값 중 seqno가 가장 큰 노드를 Primary로 선정합니다. 숫자가 같다면 grastate.datsafe_to_bootstrap: 1인 노드를 선택합니다.

2단계: Primary 노드 부트스트랩

# grastate.dat에서 safe_to_bootstrap: 1로 변경
sudo vi /app/mariadb_data/grastate.dat

# 클러스터 초기화 (Primary 노드에서만)
sudo galera_new_cluster

# 검증 (Size = 1)
sudo mariadb -u root -e "SHOW STATUS LIKE 'wsrep_cluster_size';"

3단계: 나머지 노드 합류

나머지 노드에서 하나씩 서비스를 시작합니다.

sudo systemctl start mariadb

# 최종 검증 (Size = 3)
sudo mariadb -u root -e "SHOW STATUS LIKE 'wsrep_cluster_size';"

4단계: K8s 애플리케이션 파드 정상화

DB 접속 실패로 CrashLoopBackOff 상태인 파드들을 재시작합니다.

kubectl rollout restart deployment --all -n [네임스페이스]

6-3. 복구 체크리스트

완료 분류 점검 대상 및 명령어 기준 / 비고
[ ] 사전 조사 ps -ef \| grep mysql 3대 모두 잔여 프로세스 없음
[ ] 상태 추출 --wsrep-recover --datadir=[경로] 3대 중 seqno 최고값 판별 완료
[ ] 부트스트랩 Primary: sudo galera_new_cluster wsrep_cluster_size = 1
[ ] 노드 합류 나머지: sudo systemctl start mariadb wsrep_cluster_size = 3
[ ] 파드 복구 kubectl rollout restart deployment 앱 파드 Running 확인

관련 문서


부록: RHEL 9 트러블슈팅

커스텀 경로(/app/mariadb_data) 사용 시 RHEL 9 보안 정책으로 인해 발생할 수 있는 이슈입니다.

A-1. Systemd 보안 정책 충돌 (Read-only file system)

증상: galera_new_cluster 실행 시 Errcode: 30 "Read-only file system" 발생

원인: RHEL 9의 ProtectSystem=full 정책이 시스템 경로에 대한 쓰기를 차단

해결:

# Override 디렉토리 생성 및 설정 작성
sudo mkdir -p /etc/systemd/system/mariadb.service.d

sudo tee /etc/systemd/system/mariadb.service.d/override.conf <<'EOF'
[Service]
ProtectSystem=off
ProtectHome=off
PrivateTmp=false
ReadWritePaths=/app/mariadb_data
EOF

# 설정 반영
sudo systemctl daemon-reload
sudo systemctl restart mariadb

A-2. SELinux 권한 차단

증상: 파일 시스템 권한이 올바름에도 Permission Denied 발생 또는 서비스 시작 실패

원인: 커스텀 경로에 mysqld_db_t 보안 컨텍스트가 없음

해결:

# MariaDB 데이터 컨텍스트 부여
sudo semanage fcontext -a -t mysqld_db_t "/app/mariadb_data(/.*)?"

# 실제 파일 시스템에 적용
sudo restorecon -R -v /app/mariadb_data

# 정책 확인
ls -Zd /app/mariadb_data

A-3. HA(VIP) 구성 시 주의사항 (데이터 파손 방지)

Keepalived 등으로 VIP를 구성할 때 주의할 점입니다.

  • Shared-Nothing 원칙 준수: Galera Cluster는 각 노드가 독립적인 스토리지를 가져야 합니다. 동일한 SAN/iSCSI 디스크를 여러 노드에 동시 마운트하면 파일 시스템 메타데이터가 파손되어 OS가 디스크를 Read-only로 잠급니다.
  • 해결책: 반드시 노드별 로컬 디스크 또는 독립적인 볼륨을 사용하세요. 클러스터 파일 시스템(GFS2 등)은 Galera 환경에서 권장되지 않습니다.
  • Failover 점검: VIP 할당 직후 DB가 멈춘다면, HA 솔루션이 노드를 격리(Fencing)하고 있지 않은지 확인하세요.