1. 설계 개요
프로덕션 환경에서 MySQL 클러스터는 높은 가용성, 확장성, 관리 용이성 및 낮은 비용을 요구합니다. 이 글에서는 실무에서 자주 사용되는 MySQL Active-Active 복제 아키텍처를 소개합니다. 핵심 아이디어는 MySQL 복제 기술을 사용하여 두 대의 MySQL 서버가 서로를 Master로 인식하고, 동시에 상대방의 Slave 역할을 수행하도록 구성하는 것입니다. 이를 통해 고가용성 환경에서 데이터 동기화를 실현하며, Keepalived를 이용해 자동 장애 조치(Failover)를 구현합니다. 이 아키텍처에서는 두 서버가 상호 복제 관계를 가지지만, 특정 시점에는 하나의 서버만 읽기/쓰기를 수행하고 다른 서버는 읽기 전용으로 동작하여 데이터 일관성을 보장합니다.
아래 다이어그램과 같이 DB1과 DB2는 서로 Master-Slave 관계를 형성하여 데이터가 항상 동기화되도록 합니다. 또한, 두 서버에는 고가용성 소프트웨어인 Keepalived가 설치됩니다. 정상 상황에서는 웹 서버가 DB1에서만 데이터를 읽고 쓰며, DB2는 DB1로부터 데이터를 동기화하는 역할을 합니다. Keepalived는 외부 연결을 제공하는 가상 IP(VIP)를 유지 관리하고, MySQL 데이터베이스의 상태를 모니터링합니다. DB1에 장애가 발생하거나 MySQL이 비정상적으로 동작하면 VIP와 MySQL 서비스가 자동으로 DB2로 전환되어 웹 서버가 지속적으로 데이터를 읽고 쓸 수 있습니다. 이 전환은 빠르게 이루어지며 프런트엔드 웹 서버에는 투명하게 처리됩니다.
2. Active-Active 복제 설정
이 섹션은 생략합니다.
3. Keepalived를 이용한 MySQL 이중화 고가용성 설정
3.1 Keepalived 설치
참고: 상세 설치는 "기업 웹 클러스터 - Keepalived" 문서를 참고하세요.
wget https://www.keepalived.org/software/keepalived-2.0.1.tar.gz
tar -xf keepalived-2.0.1.tar.gz -C /usr/local/src/
mkdir -p /data/keepalived
yum install openssl-devel gcc gcc-c++ make
cd /usr/local/src/keepalived-2.0.1
./configure --prefix=/data/keepalived/
make && make install
서비스 시작 스크립트 및 설정 파일을 표준 위치에 복사합니다:
cd /usr/local/src/keepalived-2.0.1/keepalived/etc
cp -R init /data/keepalived/
cp -R init /data/keepalived/etc/
cp -R init.d /data/keepalived/etc/
mkdir /etc/keepalived
cp /data/keepalived/etc/keepalived/keepalived.conf /etc/keepalived/
cp /data/keepalived/sbin/keepalived /usr/sbin/
cp /data/keepalived/etc/init.d/keepalived /etc/init.d/
cp /data/keepalived/etc/sysconfig/keepalived /etc/sysconfig/
Keepalived를 시작하고 프로세스를 확인합니다:
/etc/init.d/keepalived start
ps -ef | grep keepalived
# 출력 예시:
# root 14858 1 0 12:07 ? 00:00:00 /data/keepalived/sbin/keepalived -D
# root 14859 14858 0 12:07 ? 00:00:00 /data/keepalived/sbin/keepalived -D
# root 14860 14858 0 12:07 ? 00:00:00 /data/keepalived/sbin/keepalived -D
3.2 Keepalived 설정
ser01 (Master 우선 순위):
# /etc/keepalived/keepalived.conf
global_defs {
notification_email {
acassen@firewall.loc
failover@firewall.loc
sysadmin@firewall.loc
}
notification_email_from Alexandre.Cassen@firewall.loc
smtp_server 192.168.200.1
smtp_connect_timeout 30
router_id HA_MYSQL01
}
vrrp_script check_mysqld {
script "/etc/keepalived/check_mysqld.sh"
interval 2
}
vrrp_instance HA_1 {
state MASTER
interface eth0
virtual_router_id 51
priority 150
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
192.168.42.201
}
track_script {
check_mysqld
}
}
ser02 (Backup):
# /etc/keepalived/keepalived.conf
global_defs {
notification_email {
acassen@firewall.loc
failover@firewall.loc
sysadmin@firewall.loc
}
notification_email_from Alexandre.Cassen@firewall.loc
smtp_server 192.168.200.1
smtp_connect_timeout 30
router_id HA_MYSQL01
}
vrrp_script check_mysqld {
script "/etc/keepalived/check_mysqld.sh"
interval 2
}
vrrp_instance HA_1 {
state BACKUP
interface eth0
virtual_router_id 51
priority 100
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
192.168.42.201
}
track_script {
check_mysqld
}
}
MySQL 상태 체크 스크립트:
# /etc/keepalived/check_mysqld.sh
#!/bin/bash
USER="root"
PASS="Cloudbu@123"
/usr/local/mysql/bin/mysql -u$USER -p$PASS -e "show status;" > /dev/null 2>&1
if [ $? -eq 0 ]; then
MYSQL_STATUS=0
else
MYSQL_STATUS=1
fi
exit $MYSQL_STATUS
chmod +x /etc/keepalived/check_mysqld.sh
3.3 비선점 모드 (Non-preemptive Mode)
데이터베이스 환경에서는 잦은 장애 조치를 피하는 것이 좋습니다. 따라서 VIP가 불필요하게 이동하지 않도록 비선점 모드를 설정합니다.
ser01 (우선 순위 150, 비선점 활성화):
# /etc/keepalived/keepalived.conf
global_defs {
notification_email {
acassen@firewall.loc
failover@firewall.loc
sysadmin@firewall.loc
}
notification_email_from Alexandre.Cassen@firewall.loc
smtp_server 192.168.200.1
smtp_connect_timeout 30
router_id HA_MYSQL01
}
vrrp_script check_mysqld {
script "/etc/keepalived/check_mysqld.sh"
interval 2
}
vrrp_instance HA_1 {
state BACKUP
interface eth0
virtual_router_id 51
priority 150
advert_int 1
nopreempt
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
192.168.42.201
}
track_script {
check_mysqld
}
}
ser02 (우선 순위 100, 비선점 미사용):
# /etc/keepalived/keepalived.conf
global_defs {
notification_email {
acassen@firewall.loc
failover@firewall.loc
sysadmin@firewall.loc
}
notification_email_from Alexandre.Cassen@firewall.loc
smtp_server 192.168.200.1
smtp_connect_timeout 30
router_id HA_MYSQL01
}
vrrp_script check_mysqld {
script "/etc/keepalived/check_mysqld.sh"
interval 2
}
vrrp_instance HA_1 {
state BACKUP
interface eth0
virtual_router_id 51
priority 100
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
192.168.42.201
}
track_script {
check_mysqld
}
}
우선 순위가 더 높은 ser01에 nopreempt를 설정하면 장애 복구 후에도 VIP가 ser02에 남아 불필요한 전환을 방지합니다. 이는 MySQL 고가용성 시나리오에서 매우 실용적입니다.
4. 테스트 계정 구성 및 검증
4.1 계정 생성 및 권한 부여
mysql> CREATE USER 'keepalived'@'%' IDENTIFIED BY 'Cloudbu@123';
mysql> ALTER USER 'keepalived'@'%' IDENTIFIED WITH mysql_native_password BY 'Cloudbu@123';
mysql> FLUSH PRIVILEGES;
4.2 결과 검증
VIP (192.168.42.201)를 통해 연결 테스트를 수행합니다.
mysql -h192.168.42.201 -ukeepalived -pCloudbu@123
- ser01에 장애가 발생하면 ser02가 읽기/쓰기를 정상적으로 처리합니다.
- ser01이 복구되면 데이터 동기화가 이루어지지만, VIP는 ser02에 계속 유지됩니다(비선점 모드).
- ser02에 장애가 발생하면 VIP가 ser01로 이동합니다.