개발로 자기계발
article thumbnail
728x90

먼저, Docker가 설치되어 있어야 한다. 만약 Docker가 설치되지 않았다면 Docker 공식 사이트에서 설치할 수 있다.

Docker MySQL 이미지 찾기

docker search mysql

 

Docker MySQL 이미지 받기

docker pull ubuntu/mysql

 

네트워크 생성

Docker 컨테이너들이 서로 통신할 수 있도록 Docker 네트워크를 생성한다.

docker network create mysql-cluster

 

Master 컨테이너 생성

MySQL 마스터 역할을 하는 컨테이너를 생성한다.

docker run --name mysql-master -d --restart unless-stopped --network mysql-cluster -e MYSQL_ROOT_PASSWORD=root -e MYSQL_REPLICATION_USER=reluser -e MYSQL_REPLICATION_PASSWORD=reluser -p 3307:3306 ubuntu/mysql

MYSQL_ROOT_PASSWORD: MySQL 루트 계정의 비밀번호

MYSQL_REPLICATION_USER: 복제를 위한 사용자 계정 이름

MYSQL_REPLICATION_PASSWORD: 복제 사용자 비밀번호

-p 3307:3306: 3307 Port로 외부 접속 허용

--restart unless-stopped: 컨테이너가 충돌하거나 서버가 재부팅되면 자동으로 다시 시작

--network mysql-cluster: Docker 네트워크 안에서 컨테이너가 통신할 수 있게 설정

 

Slave 컨테이너 생성

Slave MySQL 컨테이너도 마찬가지로 생성한다.

docker run --name mysql-slave -d --restart unless-stopped --network mysql-cluster -e MYSQL_ROOT_PASSWORD=root -e MYSQL_REPLICATION_USER=reluser -e MYSQL_REPLICATION_PASSWORD=reluser -p 3308:3306 ubuntu/mysql

 

Master와 Slave의 Server ID 설정

MySQL 복제에서 Master와 Slave 서버는 각자 고유한 server_id를 가져야 한다. 두 서버의 server_id가 같으면 MySQL은 복제를 제대로 처리할 수 없기 때문에 복제 I/O 스레드가 중지된다.

vim 설치가 안되어있다면?

 

Master의 my.cnf 수정(파일 위치: /etc/mysql/my.cnf) - Ubuntu 기준

vi /etc/mysql/my.cnf

[mysqld]
id-file        = /var/run/mysqld/mysqld.pid
socket          = /var/run/mysqld/mysqld.sock
datadir         = /var/lib/mysql
secure-file-priv= NULL

# Master에 추가
server-id=1
log-bin=mysql-bin

log-bin=mysql-bin: MySQL이 바이너리 로그를 기록하도록 설정하고 바이너리 로그 파일의 이름 접두어(prefix)를 설정

 

Slave의 my.cnf 수정 (파일 위치: /etc/mysql/my.cnf) - Ubuntu 기준

vi /etc/mysql/my.cnf

[mysqld]
id-file        = /var/run/mysqld/mysqld.pid
socket          = /var/run/mysqld/mysqld.sock
datadir         = /var/lib/mysql
secure-file-priv= NULL

# Slave에 추가
server-id=2
log-bin=mysql-bin

 

둘 다 my.cnf를 수정했기에 MySQL을 재시작을 해줘야 한다.

docker restart mysql-master

docker restart mysql-slave

 

Master 설정

Master에 접속하여 복제에 필요한 설정을 진행한다.

docker exec -it mysql-master bash
mysql -uroot -p

MySQL에 접속한 후, 아래 명령어로 복제 로그 및 설정을 확인하고 복제 사용자 권한을 부여한다.

# 복제 사용자 권한 설정
CREATE USER 'reluser'@'%' IDENTIFIED BY 'reluser';
GRANT REPLICATION SLAVE ON *.* TO 'reluser'@'%';
FLUSH PRIVILEGES;

# 복제 데이터베이스 및 테이블 생성
create database reldb;
use reldb;
create table reltable (id int, primary key(id));
desc reltable;

exit

 

Master에서 DB dump 하기

Master의 현재 DB 상태를 slave에 그대로 반영하기 위해 dump 한다.

mysqldump -u root -p --all-databases > tmp/master_dump.sql

dump 한 파일을 내 로컬 PC(호스트 PC)로 복사해 온다.

# 마스터 컨테이너에서 로컬로 dump 파일 복사
docker cp mysql-master:tmp/master_dump.sql ./master_dump.sql

# 슬레이브 컨테이너로 복사
docker cp ./master_dump.sql mysql-slave:tmp/master_dump.sql

 

Slave로 데이터 복구

slave 컨테이너로 복사한 dump 파일로 복구한다.

(mysql 비밀번호는 slave 컨테이너를 실행할 때 설정한 'MYSQL_ROOT_PASSWORD' 입력)

docker exec -it mysql-slave bash
mysql -u root -p < /tmp/master_dump.sql

다시 mysql에 접속하였을 때 Master와 동일하게 구성이 되었다면 정상적으로 복구된 것이다.

mysql -uroot -p
show databases;

 

Master 상태 확인

이제 Slave에서 Master와의 연결이 필요한데, 그전에 MASTER_LOG_FILE과 MASTER_LOG_POS의 값들을 알아야 한다. 이유는 Slave가 Master의 Binary Log에서 정확한 위치에서부터 복제를 시작할 수 있도록 하기 위해서다.

 

MASTER_LOG_FILE: 마스터 서버의 Binary Log 파일 이름

MASTER_LOG_POS: Binary Log 파일 내에서 Slave가 읽기 시작할 정확한 위치

# 다시 Master로 접속
docker exec -it mysql-master bash

mysql -uroot -p
show master status;

 

Slave 설정

위 값들을 알아냈다면 이젠 MySQL 복제(레플리카) 설정에서 Slave와 Master가 연결을 설정해줘야 한다.

# 다시 Slave로 접속
docker exec -it mysql-slave bash

mysql -uroot -p
CHANGE MASTER TO MASTER_HOST='172.18.0.2', MASTER_USER='reluser',
MASTER_PASSWORD='reluser', MASTER_LOG_FILE='mysql-bin.000001',  
MASTER_LOG_POS=1265;

START SLAVE;

SHOW VARIABLES LIKE 'read_only'; -- OFF

읽기 전용으로 변경
SET GLOBAL read_only = 1;

MASTER_HOST='172.18.0.2': 데이터를 복제할 Master 호스트 이름 또는 IP 주소를 지정(Master의 IP 주소는 더보기에 나와있는 명령어로 알 수 있다.)

더보기
docker inspect -f '{{range.NetworkSettings.Networks}}{{.IPAddress}}{{end}}' mysql-master

MASTER_USER='reluser': Master 서버에서 Slave 복제를 허용하는 사용자 이름을 지정

MASTER_PASSWORD='reluser': MASTER_USER로 지정된 사용자의 비밀번호

MASTER_LOG_FILE='mysql-bin.000002': Master 서버의 Binary Log 파일 이름을 지정

MASTER_LOG_POS=1265: Master 서버의 Binary Log 파일에서 Slave가 복제를 시작할 정확한 위치(byte offset)를 지정

 

Slave 상태 확인

다른 특별한 오류가 없었다면 Slave가 정상적으로 복제를 시작했는지 확인한다.

SHOW SLAVE STATUS\G;

비밀번호 에러가 났다면?

더보기

만약 비밀번호 에러가 났다면 Slave가 MySQL 마스터에 연결할 때 mysql_native_password 인증 방식을 사용하도록 변경하거나 보안 연결(TLS)을 활성화해야 한다. 복잡하기 때문에 기본적으로 인증 방식을 바꾸는 방법이 더 간단하다.

Last_IO_Error: Error connecting to source 'reluser@172.18.0.2:3306'. This was attempt 1/86400, with a delay of 60 seconds between attempts. Message: Authentication plugin 'caching_sha2_password' reported error: Authentication requires secure connection.

 

1. 마스터 서버에 접속하여 reluser의 인증 방식을 mysql_native_password로 변경한다.

docker exec -it mysql-master bash

mysql -uroot -p

 

2. reluser 사용자의 비밀번호를 변경하면서 인증 방식을 명시한다.

ALTER USER 'reluser'@'%' IDENTIFIED WITH mysql_native_password BY 'reluser';
FLUSH PRIVILEGES;

# File과 Position 재확인
show master status;

 

3. 그리고 다시 Slave 서버에 접속

docker exec -it mysql-slave bash

mysql -uroot -p

 

4. 슬레이브 재설정

STOP SLAVE;
RESET SLAVE ALL;

CHANGE MASTER TO MASTER_HOST='172.18.0.2', MASTER_USER='reluser',
MASTER_PASSWORD='reluser', MASTER_LOG_FILE='mysql-bin.000001',  
MASTER_LOG_POS=1717;

START SLAVE;

 

5. 복제가 제대로 설정되었는지 확인

SHOW SLAVE STATUS\G;

 

복제 테스트

Master DB에 데이터를 삽입하고 Slave DB에서 동일한 데이터가 복제되는지 확인한다.

# 마스터에서 데이터 삽입
USE reldb;
INSERT INTO reltable (id) VALUES (1);
SELECT * FROM reltable;

 

# 슬레이브에서 데이터 확인
USE reldb;
SELECT * FROM reltable;
728x90
SMALL
profile

개발로 자기계발

@김잠봉

틀린부분이나 조언이 있다면 언제든 환영입니다:-)