1. Proxy Layer란
- Proxy Layer : 대리층
- ProxySQL : C++로 짜여진 오픈 소스 Proxy 프로그램으로 총 4개의 database schema를 가지며, Proxy를 컨트롤하고 모니터링할 수 있게 한다.
- Proxy Layer를 두는 이유 :
앞서서 Orchestra 설정을 해두면 Master(db001)이 샷다운 되더라도 Slave(db002)이 자동으로 Master로 승격되어 고가용성, 곧 시스템이 지속될 수 있도록 할 수 있었다. 하지만, Application 입장에서는, Application의 자체 설정에 따라 기존의 Master(db001)을 계속해서 바라볼 수 있다. 이를 해결하기 위해 중간층인 Proxy Layer를 둘 수 있는데, MySql은 Proxy 프로그램으로 ProxySQL을 사용할 수 있다.
Ex. Spring Boot application-yml에서 Master를 db001로 설정해둔 경우
--> db001이 샷다운 되고 db002이 자동으로 Master가 되어도
--> Spring Boot는 여전히 db001를 Master로 인식하고 있다.
2. Docker로 Proxy SQL 생성하기
[1] proxy 디렉토리 생성 및 권한 부여
- ProxySQL 컨테이너도 MySQL 컨테이너와 마찬가지로 호스트 볼륨에 컨테이너 파일이 마운트될 수 있게 해줘야한다.
- 따라서, data 정보가 담길 data 디렉토리와 설정 정보가 담길 conf 티렉토리를 호스트에 생성해준다.
mkdir -p db/proxysql/data db/proxysql/conf
chmod 777 db/proxysql/data db/proxysql/conf
cd db/proxysql/conf
[2] proxysql.cnf 생성 후 권한을 644로 부여
- conf 디렉토리에서 proxysql 설정 파일을 만들어준다.
- mysql의 경우 my.cnf로 설정을 작성한다면, proxysql은 proxysql.cnf로 설정을 작성한다.
vi proxysql.cnf
chmod 644 proxysql.cnf
datadir="/var/lib/proxysql"
admin_variables=
{
admin_credentials="admin:admin;radmin:radmin"
mysql_ifaces="0.0.0.0:6032"
}
mysql_variables=
{
threads=4
max_connections=2048
default_query_delay=0
default_query_timeout=36000000
have_compress=true
poll_timeout=2000
interfaces="0.0.0.0:6033"
default_schema="information_schema"
stacksize=1048576
server_version="5.5.30"
connect_timeout_server=3000
monitor_username="monitor"
monitor_password="monitor"
monitor_history=600000
monitor_connect_interval=60000
monitor_ping_interval=10000
monitor_read_only_interval=1500
monitor_read_only_timeout=500
ping_interval_server_msec=120000
ping_timeout_server=500
commands_stats=true
sessions_sort=true
connect_retries_on_failure=10
}
[3] docker로 ProxySql 생성
- proxysql 이름을 가지며 호스트명은 proxysql이고, proxysql을 네트워크 alias로 하여 브릿지를 연결한다.
- 호스트 16032 port에서 컨테이너의 6033 port로 연결되며,
- [1]에서 생성한 호스트의 data, conf로 proxysql의 data파일들과 conf 파일을 영속적으로 연결해준다.
docker run -it --name proxysql -h proxysql \
--net mybridge --net-alias=proxysql \
-p 16032:6032 -p 16033:6033 \
-v /home/opc/db/proxysql/data:/var/lib/proxysql \
-v /home/opc/db/proxysql/conf/proxysql.cnf:/etc/proxysql.cnf \
-d proxysql/proxysql
- Docker 생성 확인
docker ps --format "table {{.ID}}\t{{.Names}}\{{.Status}}"
[4] ProxySQL 접속(호스트에서 접속하는 것으로, 이 경우 호스트에 mysql 있어야함)
- 여기서 살짝 헤맸는데, 호스트에서 ProxySQL에 직접적으로 접속하기 위해서는 먼저 호스트 OS안에 mysql이 별도로 설치가 되어 있어야 한다. (나는 없었어서 아래 명령어가 에러가 남..)
- MySQL을 설치하고, 아래 명령어를 입력하면 ProxySQL에 접속이 가능하다.
mysql -h127.0.0.1 -P16032 -uradmin -pradmin --prompt "ProxySQL Admin>"
3. Proxy Layer 테스트해보기
[1] 먼저 Master 컨테이너 db001에서 테스트 데이버테이스와, 어플리케이션용 user, proxysql용 모니터링 user를 생성한다.
docker exec -it -uroot db001 /bin/bash
mysql -uroot -p
mysql > create user 'appuser'@'%' identified by 'apppass';
mysql > create database testdb default character set utf8;
mysql > grant select, insert, update, delete on testdb.* to 'appuser'@'%'
mysql > create user 'monitor'@'%' identified by 'monitor';
mysql > grant REPLICATION CLIENT on *.* to 'monitor'@'%';
mysql > flush privileges;
[2] proxy에서 hostgroup에 db 서버 정보 입력
- proxysql에서 현재 상태와 맞게 쓰기그룹, 읽기 그룹을 형성하고,
쓰기그룹/읽기그룹을 나누는 기준을 global의 " read_only "로 잡아둔다. (Slave는 global=read_only임)
mysql -h127.0.0.1 -P16032 -uradmin -pradmin --prompt "ProxySQL Admin>"
# 쓰기 그룹(10)
INSERT INTO mysql_servers(hostgroup_id, hostname, port)
VALUES(10, 'db001', 3306);
# 읽기 그룹(20)
INSERT INTO mysql_servers(hostgroup_id, hostname, port)
VALUES(20, 'db001', 3306);
INSERT INTO mysql_servers(hostgroup_id, hostname, port)
VALUES(20, 'db002', 3306);
INSERT INTO mysql_servers(hostgroup_id, hostname, port)
VALUES(20, 'db003', 3306);
# 호스트 그룹 설정
# VALUES(쓰기,읽기,쓰기/읽기 구분 기준, '')
INSERT INTO mysql_replication_hostgroups
VALUES(10, 20, 'read_only', '');
# 로드
LOAD MYSQL SERVERS TO RUNTIME;
# 설정 영구적인 저장
SAVE MYSQL SERVERS TO DISK;
[3] proxy에서 어플리케이션 user 정보 입력
- Application에서 user:appuser, password:apppass로 ProxySQL에 접속을 요청하면,
- ProxySQL은 아래에서 설정한 default_hostgroup=10번그룹과 연결을 시도한다.
- 10번은 쓰기그룹이며 Master를 의미하는데, 이는 시스템 상황에 따라 db001 또는 db002로 변경될 수 있다.
(이때, 구분 기준은 앞서 말했듯 read_only=응/아니 를 기준으로 한다.)
INSERT INTO mysql_users(username, password, default_hostgroup, transaction_persistent)
VALUES('appuser', 'apppass', 10, 0);
LOAD MYSQL USERS TO RUNTIME;
SAVE MYSQL USERS TO DISK;
[4] proxy에서 쿼리 룰 정보 입력
- 각 호스트 그룹별로 쿼리룰을 설정해준다.
- 기본적으로 모든 쿼리는 [3]에서 설정한 default_hostgroup 인 10번으로 가도록 되어 있는데,
아래와 같이 쿼리룰을 설정하면 Select/Update시에 10번으로, Select시에 20번으로 가게된다.
- **쿼리룰 순서가 중요. 반드시 순서대로 해주어야 한다.
INSERT INTO mysql_query_rules(rule_id, active, match_pattern, destination_hostgroup)
VALUES(1, 1, '^SELECT.*FOR UPDATE$', 10);
INSERT INTO mysql_query_rules(rule_id, active, match_pattern, destination_hostgroup)
VALUES(2, 1, '^SELECT', 20);
LOAD MYSQL QUERY RULES TO RUNTIME;
SAVE MYSQL QUERY RULES TO DISK;
[5] 호스트 os 에서 연결 테스트 쉘스크립트 실행
vi app_test_conn.sh
sh app_test_conn.sh
- app_test_conn.sh : hostip주소는 hostname -i로 확인할 수 있는 공인 ip주소를 작성해줘야한다.
# !/bin/bash
while true;
do
mysql -uappuser -papppass -h{hostip 주소} -P16033 -N -e "select@@hostname,now()" 2>&1| grep -v "Warning"
sleep 1
done
[5] 호스트 os 에서 insert 테스트 쉘스크립트 실행
vi app_test_insert.sh
sh app_test_insert.sh
#!/bin/bash
while true;
do
mysql -uappuser -papppass -h{{공인ip}} -P16033 -N -e "INSERT INTO testdb.insert_test VALUES ('$(hostname)', NOW())" 2>&1 | grep -v "Warning"
sleep 1
done
[6] 장애 테스트 만들기
세 개의 shell를 연 상태에서 아래와 같이 작업을 수행한다.
(1) sh app_test_insert.sh 로 insert를 지속적으로 실행한다.
(2) slave인 db002에서 읽기를 계속해서 해준다.
(3) docker stop db001로 master db를 stop 시킨다.
그리고 결과를 확인하면, db001에서 insert를 하다가, db002에서 insert를 하는 걸 볼 수 있다.
[출처] 인프런 - 따라하며 배우는 MySQL on Docker
[참고]
'Infra > Docker' 카테고리의 다른 글
[Docker] Prometheus와 Grafana를 통해 실시간 로그 확인 (1) | 2024.01.09 |
---|---|
[Docker] Orchestra를 통해 High Availability(HA) 구축하기 (1) | 2024.01.08 |
[Docker] 브리지를 통해 컨테이너 통신 (1) | 2024.01.08 |
[Docker] Master-Slave Replication 구성 (0) | 2023.12.31 |
[Docker] 호스트OS에 log, config 연결 (+my.cnf) (1) | 2023.12.29 |