kjh00n의 기록저장소

Project B에 MHA + SSL 구축하기 본문

파이널 프로젝트

Project B에 MHA + SSL 구축하기

kjh00n 2025. 2. 18. 12:14

[기본 망]


[서버 구성]

MHA Manager Rocky Linux9 + MySQL8 + OpenSSL 3.3.2 50.50.50.10
MHA Master Rocky Linux9 + MySQL8 + OpenSSL 3.3.2 50.50.50.20
MHA Slave1 Rocky Linux9 + MySQL8 + OpenSSL 3.3.2 50.50.50.30
MHA Slave2 Rocky Linux9 + MySQL8 + OpenSSL 3.3.2 50.50.50.40
MHA Firewall Rocky Linux9 50.50.50.254
60.60.60.60

 

[SSL 먼저 적용] (모든 서버)

vim /etc/ssh/sshd_config

Port 22	주석 해제하기
PermitRootLogin yes 추가하기

systemctl restart sshd
yum -y install mysql-server

systemctl enable mysqld

systemctl start mysqld

systemctl start firewalld
firewall-cmd --add-port=3306/tcp --permanent
firewall-cmd --add-port=22/tcp --permanent
firewall-cmd --reload
firewall-cmd --list-ports

MHA 유저 생성 (모든 서버)

useradd -g mysql -d /home/mhauser -m -s /bin/bash mhauser

passwd mhauser
mhauser

chown -R mhauser:mysql /mha

MHA 모니터링과 Failover 수행을 위해 각각의 서버들이 서로 간에 비밀번호 없이 SSH 접속할 수 있어야 함  (모든 서버)

visudo

# 맨 밑줄에 추가
mhauser ALL = (ALL) NOPASSWD:/sbin/ifconfig
mhauser  ALL=(ALL)       ALL                 → mhauser에서 sudo를 사용하기 위함

[Master Server]

인증서, 인증키 생성 (mhauser에서 실행)

mkdir -p /etc/mysql/ssl

openssl req -x509 -newkey rsa:2048 -keyout /etc/mysql/ssl/server-key.pem -out /etc/mysql/ssl/server-cert.pem -days 365 -nodes

openssl dhparam -out /etc/mysql/ssl/dhparam.pem 2048

chmod 600 /etc/mysql/ssl/*
chown mysql:mysql /etc/mysql/ssl/*
vim /etc/my.cnf.d/mysql-server.cnf

[mysqld]
datadir=/var/lib/mysql
socket=/var/lib/mysql/mysql.sock
log-error=/var/log/mysql/mysqld.log
pid-file=/run/mysqld/mysqld.pid

↓ 밑에 내용 추가
server_id=1
log-bin=mysql-bin
ssl-ca=/etc/mysql/ssl/server-cert.pem
ssl-cert=/etc/mysql/ssl/server-cert.pem
ssl-key=/etc/mysql/ssl/server-key.pem
ssl-cipher=TLS_AES_256_GCM_SHA384:ECDHE-RSA-AES256-GCM-SHA384


systemctl restart mysqld
1. 슬레이브 서버에서 실행
mkdir -p /etc/mysql/ssl

2. 마스터 서버에서 실행 (Master의 인증키, 인증서 Slave에게 복사) (root계정으로 실행)
scp /etc/mysql/ssl/* root@50.50.50.30:/etc/mysql/ssl/
scp /etc/mysql/ssl/* root@50.50.50.40:/etc/mysql/ssl/

3. 슬레이브 서버에서 실행
chmod 600 /etc/mysql/ssl/*
chown mysql:mysql /etc/mysql/ssl/*



※의문점
master와 slave1,2가 mysql에 접속해있는 상태로 replcheck하면 살아있는 서버가 없다면서 에러를 출력

master와 slave1,2가 mysql 접속을 해제(실행은 하고있음)상태로 replcheck하면 정상작동함

아니 뭔데 도대체...

[Slave Server1,2]

Slave1

[mysqld]
datadir=/var/lib/mysql
socket=/var/lib/mysql/mysql.sock
log-error=/var/log/mysql/mysqld.log
pid-file=/run/mysqld/mysqld.pid

↓ 밑에 내용 추가
server_id=2
log-bin=mysql-bin
read_only=1
relay_log_purge=0
ssl-ca=/etc/mysql/ssl/server-cert.pem
ssl-cert=/etc/mysql/ssl/server-cert.pem
ssl-key=/etc/mysql/ssl/server-key.pem
ssl-cipher=TLS_AES_256_GCM_SHA384:ECDHE-RSA-AES256-GCM-SHA384
(↑ Master가 죽어서 Slave가 새로운 Master로 승격되었을 때 사용할 SSL)

systemctl restart mysqld
Slave2

[mysqld]
datadir=/var/lib/mysql
socket=/var/lib/mysql/mysql.sock
log-error=/var/log/mysql/mysqld.log
pid-file=/run/mysqld/mysqld.pid

↓ 밑에 내용 추가
server_id=3
log-bin=mysql-bin
read_only=1
relay_log_purge=0
ssl-ca=/etc/mysql/ssl/server-cert.pem
ssl-cert=/etc/mysql/ssl/server-cert.pem
ssl-key=/etc/mysql/ssl/server-key.pem
ssl-cipher=TLS_AES_256_GCM_SHA384:ECDHE-RSA-AES256-GCM-SHA384
(↑ Master가 죽어서 Slave가 새로운 Master로 승격되었을 때 사용할 SSL)

systemctl restart mysqld
mysql 접속

CHANGE MASTER TO
MASTER_HOST='50.50.50.20',
MASTER_USER='repl',
MASTER_PASSWORD='repl',
MASTER_LOG_FILE='mysql-bin.000001',
MASTER_LOG_POS=857,
MASTER_SSL=1,
MASTER_SSL_CA='/etc/mysql/ssl/server-cert.pem',
MASTER_SSL_CERT='/etc/mysql/ssl/server-cert.pem',
MASTER_SSL_KEY='/etc/mysql/ssl/server-key.pem';

start slave;

[Wireshark]

↓ Master와 Slave1이 서로 암호화를 통해 통신하고 있음

↓ Master와 Slave2가 서로 암호화를 통해 통신하고 있음

[MHA 구성하기]

[모든 서버] (MHA에 필요한 패키지 설치)

1. CPAN을 사용하기 위한 Perl 패키지 설치
(perl-CPAN-2.29-3.el9.noarch)
# Perl의 CPAN (Comprehensive Perl Archive Network) 모듈을 관리할 수 있게 해주는 패키지를 설치합니다.
yum -y install perl-CPAN  

2. 시스템 패키지 업데이트 (커널 포함) (필수!!!!!!!!!!)
# 시스템 전체 패키지 업데이트, 여기에는 커널도 포함되어 최신 버전으로 업데이트합니다.
dnf update -y  

3. Git 설치 (소스 코드 관리 도구)
(git-core-2.43.5-2.el9_5.x86_64)
# Git을 설치하여 소스 코드 관리 및 버전 관리를 할 수 있습니다.
yum -y install git-core 

4. Perl 개발 관련 패키지 설치
(perl-devel-5.32.1-481.el9.x86_64)
# Perl 모듈을 개발하는 데 필요한 도구들을 설치합니다. 예: 컴파일러, 헤더 파일 등
yum -y install perl-devel

5. MariaDB와 연결을 위한 Perl DBI 드라이버 설치
(perl-DBD-MySQL-4.050-13.el9.x86_64)
# Perl에서 MySQL(MariaDB)과 연결할 수 있게 해주는 DBI 드라이버 설치
yum -y install perl-DBD-MySQL

6. CPAN에서 Perl 모듈 설치 (Config::Tiny)
(Config::Tiny 2.30)
# Perl 설정 파일을 쉽게 읽고 쓸 수 있도록 도와주는 모듈 설치
cpan install Config::Tiny

7. CPAN에서 Perl 모듈 설치 (Log::Dispatch)
(Log::Dispatch 2.71)
# Perl 애플리케이션의 로그를 다양한 방식으로 처리하고 출력할 수 있도록 하는 모듈 설치
cpan install Log::Dispatch

8. CPAN에서 Perl 모듈 설치 (Parallel::ForkManager)
(Parallel::ForkManager 2.03)
# Perl에서 병렬 프로세스를 관리하고, 동시에 여러 작업을 처리할 수 있게 해주는 모듈 설치
cpan install Parallel::ForkManager

9. CPAN에서 Perl 모듈 설치 (Module::Install)
(Module::Install 1.21)
# Perl 모듈의 설치와 빌드를 쉽게 할 수 있도록 도와주는 도구 설치
cpan install Module::Install

0. mha 계정 생성 (Master)

create user 'mha'@'%' identified by 'mha';
grant all privileges on *.* to 'mha'@'%';
flush privileges;

1. MHA 프로그램이 사용할 디렉토리 생성 (모든 서버)

mkdir /mha

2. MHA Node 설치 (모든 서버)

mkdir /source

cd /source

git clone https://github.com/yoshinorim/mha4mysql-node.git
cd /source/mha4mysql-node
perl Makefile.PL
make
make install

3. MHA Manager 설치 (Manager)

cd /source

git clone https://github.com/yoshinorim/mha4mysql-manager.git

cd /source/mha4mysql-manager
perl Makefile.PL
make
make install

4. 각 서버에서 다른 서버들에게 공개키를 줘야 함.

(MHA Manager -> Master DB, Slave DB / Master DB -> Slave DB, MHA Manager / Slave DB -> MasterDB, MHA Manager)

키 생성 :
	(모든 Server에서)
	su - mhauser
	ssh-keygen -t rsa [엔터 3번]

키 복사 :
	(Manager Server에서)
	ssh-copy-id -i ~/.ssh/id_rsa.pub mhauser@50.50.50.20
	ssh-copy-id -i ~/.ssh/id_rsa.pub mhauser@50.50.50.30
	ssh-copy-id -i ~/.ssh/id_rsa.pub mhauser@50.50.50.40
    
	(Master Server에서)
	ssh-copy-id -i ~/.ssh/id_rsa.pub mhauser@50.50.50.10
	ssh-copy-id -i ~/.ssh/id_rsa.pub mhauser@50.50.50.30
	ssh-copy-id -i ~/.ssh/id_rsa.pub mhauser@50.50.50.40
    
	(Slave Server1에서)
	ssh-copy-id -i ~/.ssh/id_rsa.pub mhauser@50.50.50.10
	ssh-copy-id -i ~/.ssh/id_rsa.pub mhauser@50.50.50.20
	ssh-copy-id -i ~/.ssh/id_rsa.pub mhauser@50.50.50.40
    
	(Slave Server1에서)
	ssh-copy-id -i ~/.ssh/id_rsa.pub mhauser@50.50.50.10
	ssh-copy-id -i ~/.ssh/id_rsa.pub mhauser@50.50.50.20
	ssh-copy-id -i ~/.ssh/id_rsa.pub mhauser@50.50.50.30

연결 테스트 :
	ssh 50.50.50.10
	ssh 50.50.50.20
	ssh 50.50.50.30
	ssh 50.50.50.40

5. 파일의 내용이 변경되지 않도록 권한 수정 (모든 서버)

su - mhauser
cd .ssh
chmod 600 authorized_keys

6. MHA Manager 명령어 커스텀마이징 (Manager)

su - mhauser (mhauser로 전환하고 실행할 것)

sudo vim .bash_profile 에 아래 내용 추가

set -o vi
alias sshcheck='/usr/local/bin/masterha_check_ssh --conf=/etc/mha.cnf'
alias replcheck='/usr/local/bin/masterha_check_repl --conf=/etc/mha.cnf'
alias start='/usr/local/bin/masterha_manager --conf=/etc/mha.cnf &'
alias stop='/usr/local/bin/masterha_stop --conf=/etc/mha.cnf'
alias status='/usr/local/bin/masterha_check_status --conf=/etc/mha.cnf'
alias log='tail -f /mha/manager.log'

저장 후
source .bash_profile

7. MHA 사용할 config 파일 생성 (Manager)

cp -p /source/mha4mysql-manager/samples/conf/app1.cnf /etc/mha.cnf

[server default]
user=mha                      # MHA 관리자 사용자 계정 (일반적으로 MHA 관리용 사용자)
password=mha                  # MHA 관리자의 비밀번호 (위에서 지정된 사용자 'mha'의 비밀번호)

ssh_user=mhauser               # MHA에서 사용할 SSH 접속 사용자 (서버에 SSH로 연결할 때 사용되는 사용자)
                               # 일반적으로, MHA 관리용 사용자와 연결이 설정됩니다.

repl_user=repl                 # 복제에 사용될 MySQL 사용자 계정 (슬레이브가 마스터로부터 데이터를 복제할 때 사용)
repl_password=repl             # 복제 사용자의 비밀번호 (위에서 지정된 `repl` 사용자의 비밀번호)

manager_workdir=/mha           # MHA Manager가 작업을 수행하는 디렉터리 경로 (MHA Manager 로그 및 상태 파일이 저장되는 경로)
manager_log=/mha/manager.log   # MHA Manager 로그 파일 경로

remote_workdir=/mha           # 원격 서버에서 MHA Manager가 작업을 수행할 디렉터리 경로

master_binlog_dir=/var/lib/mysql  # 마스터 서버에서 Binary Log 파일이 위치한 경로 (복제와 관련된 로그 파일)


[server1]
hostname=50.50.50.20           # 서버1의 IP 주소 또는 호스트네임 (서버1은 주로 슬레이브나 후보 마스터로 설정될 수 있음)
port=3306                      # 서버1에서 MySQL의 포트 번호 (기본 MySQL 포트)
candidate_master=1             # 서버1이 마스터로 승격될 후보인지 여부 (1: 승격 가능, 0: 승격 불가)
                               # 이 설정이 1인 서버는 장애 발생 시 새로운 마스터 후보로 승격될 수 있습니다.

[server2]
hostname=50.50.50.30           # 서버2의 IP 주소 또는 호스트네임 (서버2는 마스터 또는 후보 마스터로 설정될 수 있음)
port=3306                      # 서버2에서 MySQL의 포트 번호 (기본 MySQL 포트)
candidate_master=1             # 서버2가 마스터로 승격될 후보인지 여부 (1: 승격 가능, 0: 승격 불가)
                               # 이 설정이 1인 서버도 장애 발생 시 새로운 마스터 후보로 승격될 수 있습니다.                             
[server3]
hostname=50.50.50.40
port=3306
candidate_master=1

8. [Slave IP ↔ Master IP 변경 스크립트 설정] (Manager) 

이 스크립트는 마스터 서버의 장애 발생 시 슬레이브 서버를 새로운 마스터로 승격시키는 과정에서 슬레이브 서버의 IP가 새로운 마스터의 IP로 전환될 수 있도록 돕는 역할을 합니다.

mkdir /mha/scripts

cp -p /source/mha4mysql-manager-0.57/samples/scripts/master_ip_online_change /mha/scripts/master_ip_online_change

vim /mha/scripts/master_ip_online_change 수정

150, 151, 152, 245, 246, 247, 248 라인에 주석 추가

:set number
:150

    149       ## Drop application user so that nobody can connect. Disabling per-session binlog beforehand
    150       # $orig_master_handler->disable_log_bin_local();
    151       # print current_time_us() . " Drpping app user on the orig master..\n";
    152       # FIXME_xxx_drop_app_user($orig_master_handler);

:245

    244       ## Creating an app user on the new master
    245       # print current_time_us() . " Creating app user on the new master..\n";
    246       # FIXME_xxx_create_app_user($new_master_handler);
    247       # $new_master_handler->enable_log_bin_local();
    248       # $new_master_handler->disconnect();

9. [Failover 스크립트 설정] (Manager) 

위 스크립트와의 차이점

cp -p /source/mha4mysql-manager-0.57/samples/scripts/master_ip_failover /mha/scripts/

vim /mha/scripts/master_ip_failover 수정

87, 88, 89, 90, 93 라인 주석 처리

:set number
:87

     86       ## Creating an app user on the new master
     87       # print "Creating app user on the new master..\n";
     88       # FIXME_xxx_create_user( $new_master_handler->{dbh} );
     89       # $new_master_handler->enable_log_bin_local();
     90       # $new_master_handler->disconnect();
     91
     92       ## Update master ip on the catalog database, etc
     93       # FIXME_xxx;

10. 스크립트 적용했으니 mha.cnf 파일 수정 (manager)

[server default]
user=mha
password=mha

ssh_user=mhauser

repl_user=repl
repl_password=repl

manager_workdir=/mha
manager_log=/mha/manager.log
remote_workdir=/mha

master_binlog_dir=/var/lib/mysql

↓ 밑에 2개 추가해주기
master_ip_online_change_script=/mha/scripts/master_ip_online_change
master_ip_failover_script=/mha/scripts/master_ip_failover

[server1]
hostname=50.50.50.20
candidate_master=1

[server2]
hostname=50.50.50.30
candidate_master=1

[server3]
hostname=50.50.50.40
candidate_master=1

11. 실행 (Manager)

→ MHA 실행시킴

→ 현재 상태를 출력 (Master는 50.50.50.20)

→ Master를 정지시킴

→ tail -f /mha/manager.log

→ Master를 중지시키고 Manager에서 출력된 Failover Report임

→ 50.50.50.30이 Master로 승격됨

→ 새로 승격된 Master는 SSL을 사용중이고 설정한 암호화 통신을 사용중임

→ 처음에 read_only를 ON으로 설정해놨는데 Master로 승격됐을때 자동으로 OFF로 변경

→ Slave2는 여전히 초기에 설정한대로 read_only가 ON으로 설정되어 있음

→ Slave2는 Master가 (전)Slave1이였던 (현)Master로 설정되어있음

→ 여전히 새로운 Master와 Slave2는 암호화 통신을 진행중임