본문 바로가기
mysql

DRBD(+keepalived)를 이용한 MySQL HA 구성

by misankim 2023. 3. 23.

DRBD, keepalived를 이용한 MySQL HA 구성 관련 내용 공유합니다.

DRBD란

DRBD는 Distributed Replicated Block Device 의 약자로 Linux 플랫폼을위한 분산 복제 스토리지 시스템을 의미합니다. DRBD 설정을 통해 로컬 호스트에 있는 디스크와 네트워크 상에 있는 다른 호스트의 디스크를 RAID1(미러링)으로 묶은 것과 동일한 효과를 낼 수 있습니다.(네트워크 지연시간에 따라 복제 지연은 발생할 수 있음)

이번 구성에서는 DRBD 구성 및 지난번 HAPROXY HA 구성에 사용했던 HA 도구인 keepalived를 이용하여 MySQL 서버 장애 발생 시 자동으로 장애조치 가능하도록 설정해보록 하겠습니다.

테스트 환경

테스트 환경 구성은 아래와 같습니다.

웹서버 - 192.168.2.20
mysql1 - 192.168.2.30
mysql2 - 192.168.2.40
VIP - 192.168.2.100(keepalived를 이용한 ha 구성에 사용되는 virtual 아이피)

사전작업

각 서버의 호스트네임 세팅 후 DRBD 설정으로 동기화할 디스크를 파티셔닝합니다.

hostnamectl set-hostname mysql1
fdisk -l 
# 동기화할 데이터 디스크가 /dev/sdb 인 경우
fdisk /dev/sdb

DRBD 설치

yum install -y https://www.elrepo.org/elrepo-release-7.el7.elrepo.noarch.rpm
yum install -y kmod-drbd84 drbd84-utils

# 모듈 적재
modprobe drbd
lsmod |grep drbd

DRBD 설정(마스터/슬레이브 서버에서 모두 실행)

# 설정 파일 작성
vim /etc/drbd.d/mysql.res # 임의로 설정한 리소스의 이름.res 형식으로 작성하면 됩니다.

resource   mysql {
    startup {
        wfc-timeout 30;
        outdated-wfc-timeout 20;
        degr-wfc-timeout 30;
    }
    net {
        cram-hmac-alg sha1;
        shared-secret sync_disk;
    }

    on mysql1 {
        device /dev/drbd0;
        disk /dev/sdb; # 장치 이름은 환경에 따라 수정합니다.
        address 192.168.2.30:7789; # 아이피 주소 알맞게 수정합니다.
        meta-disk internal;
    }

    on mysql2 {
        device /dev/drbd0;
        disk /dev/sdb;
        address 192.168.2.40:7789;
        meta-disk internal;
    }
}

저장 후 닫기

# 메타데이터 작성(마스터/슬레이브 모두)
drbdadm create-md mysql
-> (확인하려면 yes 입력하라고 나오면 yes 입력)

# 데몬 실행 및 자동 실행 설정
systemctl start drbd && systemctl enable drbd

# 동기화 시작(마스터서버에서만) 
drbdadm primary --force mysql

# drbd 상태 확인
cat /proc/drbd

위의 상태 확인 명령어 "cat /proc/drbd" 입력 시 아래와 같이 초기 싱크가 진행되며 완료 시 가장 아래 스크린샷처럼 보여집니다. 테스트 진행한 데이터 디스크의 크기는 1GB로 디스크의 크기가 클수록 초기 동기화 시간은 길어집니다.

 

 

Primary/Secondary 라고 표시된 부분은 해당 drbd 호스트의 역할이 마스터(Primary)임을 나타냅니다. 슬레이브 서버에서 동일한 명령어로 상태를 확인해봅니다. 슬레이브 서버도 동기화가 완료되었으며, Secondary/Primary 라고 표시된 부분으로 해당 서버가 슬레이브(Secondary)서버임을 알 수 있습니다.

마운트 및 파일 작성 테스트

drbd로 동기화하고 있는 디스크는 마스터(Primary) 서버에서만 마운트할 수 있기 때문에 마스터 서버에서 마운트하여 파일 작성 테스트 해봅니다.

mkfs.ext4 /dev/drbd0
mkdir /data
mount /dev/drbd0 /data

cd /data
mkdir test_dir
touch test_file

아래와 같이 마운트 및 파일 쓰기가 정상적인 것을 확인할 수 있습니다.

 

이제 마스터 서버를 슬레이브로 변경하고 슬레이브를 마스터로 변경하여 마운트가 정상적으로 되는지 확인합니다.

# 마스터를 슬레이브로 전환
umount /dev/drbd0
drbdadm secondary mysql

# 슬레이브를 마스터로 전환
drbdadm primary mysql

슬레이브를 마스터로 전환한 뒤,
mkdir /data
mount /dev/drbd0 /data

슬레이브 서버에서 drbd 상태 확인 및 파일 확인

 

drbd 설정은 정상적인 것으로 확인하였으니 다시 원래 마스터의 역할과 슬레이브 역할로 전환합니다.

mysql 설치

(마스터 슬레이브 서버 모두)
rpm -ivh http://dev.mysql.com/get/mysql-community-release-el7-5.noarch.rpm
yum install -y mysql-community-server

(마스터서버에서)
mount /dev/drbd0 /var/lib/mysql

rm -rf /var/lib/mysql/*

mysql_install_db
chown -R mysql.mysql /var/lib/mysql
systemctl start mysqld && systemctl enable mysqld

mysql_secure_installation

keepalived 설치 및 설정

# 설치
yum install -y keepalived
# 마스터 서버 설정 파일 작성
vim /etc/keepalived/keepalived.conf

vrrp_script my_chk {
    script       "/usr/local/bin/mysql_check.sh"
    interval 30
    fall 1
    rise 1
    weight 10
}

vrrp_instance VI_1 {
    state MASTER
    interface enp0s8
    virtual_router_id 51
    priority 100
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 1111
    }
    virtual_ipaddress {
        192.168.2.100
    }
    track_script {
      my_chk
    }
}
# 백업 서버 설정 파일 작성
vim /etc/keepalived/keepalived.conf

vrrp_script my_chk {
    script       "/usr/local/bin/mysql_check.sh"
    interval 30
    fall 1
    rise 1
    weight 10
}

vrrp_instance VI_1 {
    state BACKUP
    interface enp0s8
    virtual_router_id 51
    priority 99
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 1111
    }
    virtual_ipaddress {
        192.168.2.100
    }
    track_script {
      my_chk
    }
}
# mysql 헬스체크 및 장애조치 스크립트 작성(스크립트의 내용은 임의로 작성한 것이기 때문에 상황에 따라 적절히 수정할 것)
touch /usr/local/bin/mysql_check.sh
chmod 755 /usr/local/bin/mysql_check.sh

vim /usr/local/bin/mysql_check.sh

#!/bin/bash
STATUS=`cat /proc/drbd | grep "ro:" | awk '{ print $3 }' | awk -F: '{ print $2 }' | awk -F/ '{ print $1 }'`
VIP="192.168.2.100"
STATUS_LOG="/tmp/mysql_check_last_status.log"
LAST_STATUS=`cat $STATUS_LOG`

if [ "$STATUS" == "Primary" ] # 현재 drbd 상태가 마스터인 경우
then
        echo $STATUS > $STATUS_LOG
        mysqladmin -ucheck -pcheck status
        if [ "$?" == "0" ]
        then
                exit 0
        else # 헬스체크가 실패하는 경우 -> 마운트를 해제하고 슬레이브 상태로 전환
                systemctl stop mysqld
                sleep 5
                umount /dev/drbd0
                drbdadm secondary mysql
                exit 11
        fi
elif [ "$STATUS" == "Secondary" ] && [ "$LAST_STATUS" == "Secondary" ] # 현재 상태가 슬레이브이며, 지난번 스크립트가 실행되었을 때도 슬레이브였을 때
then
        echo $STATUS > $STATUS_LOG
        mysqladmin -ucheck -pcheck status -h $VIP
        if [ "$?" == "0" ]
        then
                exit 21
        else # 현재 (VIP를 가지고 있는) 마스터의 헬스체크가 실패하는 경우 자신이 마스터가 되어 디스크 마운트 및 mysql 데몬을 실행
                drbdadm primary mysql
                mount /dev/drbd0 /var/lib/mysql
                systemctl restart mysqld
                sleep 5 
                mysqladmin -ucheck -pcheck status
                if [ "$?" == "0" ]
                then
                        exit 0
                else
                        exit 22
                fi
        fi
else
        echo $STATUS > $STATUS_LOG
        exit 1
fi
# mysql 에서 접속 테스트 및 체크를 위한 유저 생성
create database status_check;
grant all privileges on status_check.* to 'check'@'localhost' identified by 'check';
grant all privileges on status_check.* to 'check'@'192.168.2.%' identified by 'check';
# keepalived 실행
systemctl start keepalived && systemctl enable keepalived
systemctl restart keepalived

keepalived 까지 정상적으로 세팅되었다면 아래와 같이 VIP를 통해 mysql 상태 체크가 가능해집니다. 마스터/슬레이브 서버 모두에서 접속 테스트 해봅니다.

웹서버 설정

웹서버에는 apache, php 를 이용하여 그누보드를 설치했습니다.

장애조치 테스트

keepalived 세팅에 따라 mysql 헬스체크 및 장애조치 스크립트는 30초 주기로 실행되며, 스크립트의 성공/실패 임계값은 1회입니다. 1) mysql 서버 자체가 다운되었을 때, 2) mysql 데몬만 다운되었을 때, 두 가지 경우를 가정하여 장애조치 테스트를 진행합니다.

1) mysql 서버 자체가 다운되었을 때

정상적으로 실행 중인 마스터 서버의 상태입니다.

 

 

마스터 서버를 종료 시키고 슬레이브 서버에서의 로그를 확인합니다. 마스터 서버를 종료한 시간은 약 10시 43분 40초입니다.

약 3~4초만에 keepalived에 의해 마스터 상태로 전환되어 VIP를 인계받았습니다.

keepalived에 설정한 mysql 상태 체크 스크립트에 의해 drbd 마스터 상태로 전환하여 디스크 마운트 및 mysqld 데몬 시작까지 총 40초 정도가 소요되었습니다.(서버 다운으로부터)

장애조치 완료된 슬레이브 서버의 상태입니다.

 

 

웹사이트 접속에도 문제가 없는 것을 확인할 수 있습니다.

2) mysql 데몬만 다운되었을 때

서버는 살아있지만 mysql 데몬만 죽었을 경우를 가정하여 테스트 진행합니다. 아래는 정상적인 상태 마스터 서버의 상태입니다.

이제 마스터 서버의 mysqld 데몬을 정지시키고 마스터 서버와 슬레이브 서버의 로그를 확인합니다. 마스터 서버의 mysqld 데몬을 정지시킨 시간은 11시 3분 16초입니다.

마스터 서버의 로그 확인 시 keepalived 스크립트에 의해 자신이 Primary 상태이나, mysql 상태 체크에 실패하기 때문에 마운트 해제 후 슬레이브 상태로 전환했음을 알 수 있습니다.

슬레이브 서버의 로그 확인 시 마스터(VIP)로부터 체크가 실패했기 때문에 drbd Primary 서버가 되어 디스크 마운트 및 mysqld 데몬 재시작이 된 것을 알 수 있습니다. 또한 스크립트 성공으로 keepalived 우선순위가 높아져 VIP를 인계 받은 것을 확인할 수 있습니다. 장애조치까지 소요된 시간은 30초입니다.(스크립트 실행 주기 및 스크립트 내용에 따라 달라질 수 있음)

장애조치가 완료된 슬레이브 서버(현재 마스터 역할)의 상태는 아래와 같이 확인됩니다.

웹사이트의 상태도 정상적인 것을 확인할 수 있습니다.

결론

DRBD, keepalived를 이용하여 MySQL을 HA 구성하는 방법을 알아보았습니다. MySQL은 보통 리플리케이션 설정을 통해 복제를 하지만 리플리케이션의 경우 비동기 복제이기 때문에 마스터에서 업데이트된 내역이 슬레이브에서 정상적으로 업데이트되었는지 확인을 진행하지 않습니다. (mysql 버전 5.5 이상 - semi-replication, mysql 버전 5.7 이상 - loss-less replication 기능을 지원하여 semi-sync 플러그인 활성화하여 리플리케이션으로 복제 시 릴레이로그가 정상적으로 전달되는 것까지는 체크하나, 릴레이로그를 정상적으로 mysql에 commit 하는지는 체크가 안된다고 합니다) 때문에 마스터 서버 장애 시 슬레이브 서버로 복구가 이뤄졌을 때, 데이터의 일관성을 백프로 보장하기 어렵다는 단점이 있습니다.

drbd 구성의 경우에도 mysql 기능과 별도로 디스크 자체를 네트워크를 이용하여 복제하는 것이기 때문에 네트워크 지연시간에 의해 마스터의 최종 데이터가 슬레이브로 복제되었는지 보장하기 어렵다는 단점이 있습니다. 다른 MySQL HA 방식과 장단점을 따져보고 상황에 적합한 HA 방식을 선택하는게 좋을 것으로 보입니다.

'mysql' 카테고리의 다른 글

ProxySQL 을 통한 MySQL 쿼리 라우팅 설정  (5) 2023.04.02