나는 조립식 PC를 쓰고 있다. 조립식 PC를 구매하면 좋은 점은, 내가 원하는 맞춤형 사양을 비교적 저렴하게 구매할 수 있다는 것. 다만 단점은 PC가 맛이 갔을 때 해결은 내가 해야한다는 점이다.

 

* 내돈내산으로 구매했던, 다나와 PC 견적 사이트 -- [바로가기]

 

내 PC도 어쩌다 한 번씩 부팅이 잘 안 될 때가 있다. 대체로 원인은 RAM이 더러워져서 발생하는 경우가 많았다.

 

그럴 때 해결하는 법.

 

[방법1] 일단 RAM을 꺼냈다가 다시 끼워본다. 

 

- RAM을 반대로 끼울 때도 있다. 그래서 안 될 수도 있음

- RAM이 완전히 안 껴졌을 때가 있다. 그러면 안 됨

 

[출처] 동아일보

 

[방법2] RAM 끝을 확인해본다. 드럽다면 손으로 한 번 닦아준다. 그래도 안 되면 "깨끗한" 지우개로 한 번 지운다.

 

* 대신, 지우개 찌꺼기는 절대 부품 안에 들어가지 않도록 잘 제거해준다. 지우개 찌꺼기가 부품 안에 들어가는 경우가 있다. 그러면 정말 망한다고 한다.

 

 

[출처] 동아일보

 

이렇게 해서 한 번도 부팅이 안 된 적이 없었다. 

 

기본적인 상식일 수 있는데 나처럼 뻘짓하는 사람들을 위해 재미삼아 적어본다.

 

 

'Infra > Device' 카테고리의 다른 글

윈도우와 맥 모두 호환되는 키보드  (1) 2024.12.11

 

요즘 취미로 글쓰기 모임을 시작했다. 가볍게 릴레이로 글을 쓰는데 손맛이 좋은 키보드를 갖고 싶었다.

 

와중에 코딩도 해야해서 윈도우랑 맥이 호환되는 키보드를 찾았다.

 

엑토 레트로2 블루투스 키보드 B307 

 

옛날 타자기에 대한 로망을 갖고 있었는데 일단 비주얼에서 만족했다.

 

누를 때 소음이 좀 나는 편이라서 회사에서 쓰기는 그렇고, 집에서 쓰기 좋다.

 

PC뿐 아니라 블루투스로 핸드폰이나 태블릿을 연결할 수 있어서 유용하게 쓰고 있다.  

 

'Infra > Device' 카테고리의 다른 글

조립식 PC 부팅이 안 될 때, RAM 상태를 확인하기  (0) 2024.12.11

1. Prometheus란?

- 관련된 신화 : 신으로부터 불을 훔친 자로써, 형벌로 동생에게 판도라라는 여성을 보내 판도라의 상자 사건이 일어남

- 메트릭 수집, 시각화, 알림, 서비스 디스커버리 기능을 모두 제공하는 오픈 소스 모니터링 시스템이다.

- 프로메테우스로 모니터링을 하려면 모니터링 항목 수집을 위해 Exporter라고 하는 Agent가 수행되어야 한다.

   ex. node_exporter, mysql_exporter, postgre_exporter, redis_exporter, kafka_exporter.....

 

2. Dockerfile로 mysqld_exporter와 node_exporter가 포함된 MySQL 컨테이너 생성하기

- Prometheus에서 모니터링을 하려면 MySQL 컨테이너에 node_exporter와 mysqld_exporter를 같이 설치해줘야한다. 

- 기존의 percona에서는 두 exporter가 없었기 때문에 커스텀 image를 생성해줘야한다.

 

[1] custom_image 디렉토리 안에 dockerfile로 커스텀 image 생성 

FROM centos:7
COPY ["Percona-Server-client-57-5.7.31-34.1.el7.x86_64.rpm",\
      "Percona-Server-server-57-5.7.31-34.1.el7.x86_64.rpm", \
      "Percona-Server-shared-57-5.7.31-34.1.el7.x86_64.rpm", \
      "Percona-Server-shared-compat-57-5.7.31-34.1.el7.x86_64.rpm", \
      "node_exporter-1.7.0.linux-amd64.tar.gz", \
      "mysqld_exporter-0.15.1.linux-amd64.tar.gz", \
      "start_node_exporter.sh", \
      "start_mysqld_exporter.sh", \
      ".my.cnf","/home/opc/tmp/"]
USER root
RUN groupadd -g 1001 mysql
RUN useradd -u 1001 -r -g 1001 mysql
RUN yum install -y perl.x86_64 \
    libaio.x86_64 \
    numactl-libs.x86_64 \
    net-tools.x86_64 \
    sudo.x86_64 \
    openssl.x86_64
WORKDIR /home/opc/tmp/
RUN rpm -ivh Percona-Server-shared-57-5.7.31-34.1.el7.x86_64.rpm \
    Percona-Server-shared-compat-57-5.7.31-34.1.el7.x86_64.rpm \
    Percona-Server-client-57-5.7.31-34.1.el7.x86_64.rpm \
    Percona-Server-server-57-5.7.31-34.1.el7.x86_64.rpm
RUN mkdir -p /home/opc/opt/exporters/ && \
    tar -xzvf ./node_exporter-1.7.0.linux-amd64.tar.gz -C /home/opc/opt/exporters && \
    tar -xzvf ./mysqld_exporter-0.15.1.linux-amd64.tar.gz -C /home/opc/opt/exporters
WORKDIR /home/opc/opt/exporters/
RUN mkdir -p node_exporter && \
    mkdir -p mysqld_exporter && \
    mv node_exporter-1.7.0.linux-amd64 node_exporter && \
    mv mysqld_exporter-0.15.1.linux-amd64 mysqld_exporter && \
    mv /home/opc/tmp/start_node_exporter.sh /home/opc/opt/exporters/node_exporter/ && \
    mv /home/opc/tmp/start_mysqld_exporter.sh /home/opc/opt/exporters/mysqld_exporter/ && \
    mv /home/opc/tmp/.my.cnf /home/opc/opt/exporters/mysqld_exporter/ && \
    chmod o+x node_exporter/start_node_exporter.sh && \
    chmod o+x mysqld_exporter/start_mysqld_exporter.sh && \
    rm -rf /home/opc/tmp/*.rpm && \
    /usr/bin/install -m 0775 -o mysql -g mysql -d /var/lib/mysql \
    /var/run/mysqld /docker-entrypoint-initdb.d
VOLUME ["/var/lib/mysql", "/var/log/mysql","/etc/percona-server.conf.d"]
COPY ps-entry.sh /home/opc/tmp/docker-entrypoint.sh
RUN chmod +x /home/opc/tmp/docker-entrypoint.sh
ENTRYPOINT ["/home/opc/tmp/docker-entrypoint.sh"]
USER mysql
EXPOSE 3306
CMD ["mysqld"]

 

[2] 링크를 통해 설치 파일 다운로드
https://docs.percona.com/percona-server/5.7/installation/yum_repo.html#installing-from-the-percona-yum-repository
https://www.percona.com/downloads/Percona-Server-5.7/Percona-Server-5.7.31-34/binary/redhat/7/x86_64/Percona-Server-5.7.31-34-r2e68637-el7-x86_64-bundle.tar
https://prometheus.io/download/#node_exporter

 

[3] mysqld_exporter 설정 파일 추가 및 mysqld/node_exporter 실행 쉘스크립트 작성

- mysqld_exporter 설정 파일

vi .my.cnf
[client]
host=localhost
user=exporter
password=exporter123

- node_exporter와 mysqld_exporter 실행 쉘스크립트

#vi start node_exporter.sh
nohup /opt/exporters/node_exporter/node_exporter &

#vi start_mysqld_exporter.sh
nohup /opt/exporters/mysqld_exporter/mysqld_exporter
--config.my-cnf="/opt/exporters/mysqld_exporter/.my.cnf" &


[4] 모두 하나의 디렉토리 안에 넣었는지 확인

tree -a


[5] 이미지 생성

docker build -t mysql57:0.0 ./
docker images


[6] 컨테이너 실행 

docker run -it --name mydb \
-e MYSQL_ROOT_PASSWORD="root" -d mysql57:0.0

 

3. Customer Image로 컨테이너 생성 및 Prometheus 컨테이너 구성

[1] 기존의 컨테이너를 모두 정지 및 삭제

# rm -f 를 쓰면 stop과 동시에 삭제
[root@dev opc]# docker rm -f db001 db002 db003
db001
db002
db003

 

[2] 호스트에서 사용자 그룹(GID)을 생성하고, 사용자(UID)를 생성한다.

- groupadd를 통해 mysql이라는 사용자 그룹을 생성한다(이때, GID는 1001)

- useradd를 통해 mysql이라는 사용자를 생성한다.(이때, UID도 1001)

- chown 에서 -R은 하위 디렉토리까지 권한을 준다는 의미이며, mysql:mysql은 소유자:그룹형식을 의미한다. 

groupadd -g 1001 mysql
useradd -u 1001 -r -g 1001 mysql
chown -R mysql:mysql /db/db001 /db/db002 /db/db003

 

[3] Mysql 컨테이너 세대를 다시 생성 

docker run -it --name db001 -h db001 -p 3306:3306 \
--net mybridge --net-alias=db001 \
-v /db/db001/data:/var/lib/mysql \
-v /db/db001/log:/var/log/mysql \
-v /db/db001/conf:/etc/percona-server.conf.d \
-e MYSQL_ROOT_PASSWORD="root" -d mysql57:0.0

docker run -it --name db002 -h db002 -p 3307:3306 \
--net mybridge --net-alias=db002 \
-v /db/db002/data:/var/lib/mysql \
-v /db/db002/log:/var/log/mysql \
-v /db/db002/conf:/etc/percona-server.conf.d \
-e MYSQL_ROOT_PASSWORD="root" -d mysql57:0.0

docker run -it --name db003 -h db003 -p 3308:3306 \
--net mybridge --net-alias=db003 \
-v /db/db003/data:/var/lib/mysql \
-v /db/db003/log:/var/log/mysql \
-v /db/db003/conf:/etc/percona-server.conf.d \
-e MYSQL_ROOT_PASSWORD="root" -d mysql57:0.0

 

[4] Prometheus가 사용할 디렉토리와 Computer 디렉토리 생성

mkdir -p /db/prom001 /db/prom001/data /db/prom001/conf
chmod 777 /db/prom001 /db/prom001/data /db/prom001/conf

 

[5] 프로메테우스 컨테이너 실행

(1) 설정 파일 구성

cd /db/prom001/conf
vi prometheus.yml

- 각 컨테이너별로 node_exporter와 mysqld_exporter 잡과 연결 정보를 등록한다.

- node_exporter는 주로 9100을 디폴트로 사용하고, mysqld_exporter는 주로 9104을 디폴트로 사용한다.

global:
  scrape_interval:     5s
  evaluation_interval: 5s

scrape_configs:
- job_name: linux_db001
  static_configs:
    - targets: ['db001:9100']
      labels:
        alias: db001
- job_name: mysql_db001
  static_configs:
    - targets: ['db001:9104']
      labels:
        alias: db001
- job_name: linux_db002
  static_configs:
    - targets: ['db002:9100']
      labels:
        alias: db002
- job_name: mysql_db002
  static_configs:
    - targets: ['db002:9104']
      labels:
        alias: db002
- job_name: linux_db003
  static_configs:
    - targets: ['db003:9100']
      labels:
        alias: db003
- job_name: mysql_db003
  static_configs:
    - targets: ['db003:9104']
      labels:
        alias: db003

 

(2) Docker로 Prometheus Container 실행 

docker run -it --name prom001 -h prom001 -p 9090:9090 \
--net mybridge --net-alias=prom001 \
-v /db/prom001/data:/data \
-v /db/prom001/conf:/etc/prometheus \
-d prom/prometheus-linux-amd64

 

(3) Prometheus 설정

- Master MySQL 컨테이너에서 아래와 같이 프로메테우스용 user 생성

docker exec -it -uroot db001 /bin/bash
mysql -uroot -p

mysql > create user 'exporter'@'localhost' identified by 'exporter123' with MAX_USER_CONNECTIONS 3;
mysql > grant PROCESS, REPLICATION CLIENT, SELECT ON *.* TO 'exporter'@'localhost';

- 호스트에서 각각의 exporter 시작 쉘스크립트 실행

docker exec db001 sh /opt/exporters/node_exporter/start_node_exporter.sh

docker exec db001 sh /opt/exporters/mysqld_exporter/start_mysqld_exporter.sh

docker exec db002 sh /opt/exporters/node_exporter/start_node_exporter.sh

docker exec db002 sh /opt/exporters/mysqld_exporter/start_mysqld_exporter.sh

docker exec db003 sh /opt/exporters/node_exporter/start_node_exporter.sh

docker exec db003 sh /opt/exporters/mysqld_exporter/start_mysqld_exporter.sh

 

[6] Prometheus 웹 콘솔 접속

- 아래 주소로 접속을 하면 된다.

http://{{호스트id}}:9090/graph

- "up"이라는 쿼리를 쓰면 각 컨테이너별 exporter를 확인할 수 있다.

 

3. Grafana Container 실행 및 Dashboard만들기

[1] Docker로 Granfana Container 실행

docker run -it --name grafana -h grafana -p 13000:3000 \
--net mybridge --net-alias=grafana \
-d grafana/grafana

 

[2] http://{{host ip}}:13000/ 으로 그라파나 접속

- default 접속 : admin/admin

 

[3] Grafana 구성

- Connections > Data Sources > [Add Data Source] 에서 Prometheus를 선택한다.

- 접속 URL에 프로메테우스 컨테이너 정보 http://prom001:9090 입력 후 저장 및 테스트

 

[4] Dashboard 추가

- Dashboard 유형에는 여러가지가 있는데, 그 중 

- 아래 링크에서 MYSQL_Overview.json의 json 정보를 복사한 후

https://github.com/percona/grafana-dashboards/tree/master/dashboards 

- 프로메테우스의 [+] > Import dashboard 를 통해 로그 후 임포트 

 

[참고]
https://www.lesstif.com/lpt/linux-chown-93127453.html
https://yjkim97.tistory.com/53

https://gurumee92.tistory.com/220

 

 

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로 인식하고 있다.

출처:https://dkswnkk.tistory.com/729

 

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

[참고]

https://notemusic.tistory.com/55

https://dkswnkk.tistory.com/729

1. 고가용성이란?

- 가용성 = Uptime / (uptime + downtime)

- 고가용성 = 바람직한 정도로 긴 시간 동안 지속적인 운영이 가능한 시스템 또는 컴포넌트 

- 고가용성의 시스템을 구축한다는 건 = 서비스가 다운되는 타임을 최소화하는 시스템을 구축한다는 것

 

2. HA 수동 설정 

[1] Orchestra를 Docker로 생성하기

- Orchestra는 MySQL용 복제 토폴로지 관리자로서, 고가용성 및 복제 관리 툴을 말한다.
- GUI/CLI/API를 통해서 상태를 확인하고 작업을 수행할 수 있다.

docker run -it --name orchestrator -h orchestrator \
--net mybridge --net-alias=orchestrator \
-p 3000:3000 -d openarkcode/orchestrator:latest

 

[2] 도커 컨테이너의 ip 주소 찾기

docker inspect --format '{{.NetworkSettings.Networks.mybridge.IPAddress}}' db001

 

[3] Master에서 Orchestrator에 접속할 수 있는 User 생성

create user orc_client_user@`172.%` identified by 'orc_client_password';
GRANT SUPER, PROCESS, REPLICATION SLAVE, RELOAD ON *.* TO orc_client_user@`172.%`;

 

[4] Orchestrator 접속

- https://{{호스트ip}}:3000/web/clusters 로 접속한다.
- clusters > discover 에 들어가서, 마스터 컨테이너명(db001) : 포트(3306) 를 입력한다.

 

- clusters > dashboard에 들어가면 master가 떠있고 master를 누르면 아래처럼 연결된 slave가 나타난다.

 

3. HA 테스트 진행하기

- read/write 모두 가능한 마스터인 db001가 갑자기 샷다운 된다고 하면

docker stop db001

- master는 리커버리가 필요한 상태가 되며 slave들은 master와 연결이 끊어짐에 따라 read가 불가능해진다. 

-  이때, Recovory를 눌러 db002를 마스터로 직접 승격해주면 db002가 master가 되며 db003이 slave로 붙는걸 볼 수 있다.

- db001를 db002의 slave로 들어가도록 하려면 db001를 재실행한 후, read_only 상태로 변경, db001의 master를 db002로 설정해준다.

docker start db001

docker exec -it -uroot db001 /bin/bash
mysql -uroot -p

mysql> set global read_only=1;
Query OK, 0 rows affected (0.01 sec)

mysql> change master to master_host='db002', \
    -> master_user='repl', master_password='repl', \
    -> master_auto_position=1;
Query OK, 0 rows affected, 2 warnings (0.31 sec)

mysql> start slave;
Query OK, 0 rows affected (0.00 sec)

 

4. HA 자동화(Auto Failover) 하기

[1] Orchestra의 orchestrator.conf.json 파일을 통해 설정 수정하기

[root@dev opc]# docker exec -it orchestrator /bin/bash
bash-4.4# cd /etc/
bash-4.4# vi orchestrator.conf.json

- 아래와 같이 모든 컨테이너에 대해서 Master로 회복이 가능하되, 컨테이너 호스트이름이 db003일 때는 Master로 승격이 되지 않도록 하면, db001/db002는 Master로 회복이 되지만 db003는 Master로 회복이 될 수 없다.

[AS-IS]  [TO-BE]
 "RecoverMasterClusterFilters": [
    "_master_pattern_"
  ],
...
 "PromotionIgnoreHostnameFilters": [],
"RecoverMasterClusterFilters": [
    "*"
  ],
...
 "PromotionIgnoreHostnameFilters": ["db003"],

 

[2] Orchestra를 재실행하여 설정을 초기화한다.

docker restart orchestrator

 

[3] HA 자동화 테스트 해보기 

- 먼저, Audit > Recovery 에서 Failure 상태를 Acknowlege 해준다. (안해주면 정상적인 테스트가 되지 않는다)

- 아까와 마찬가지로 Master인 db002를 stop 시켜 샷다운 상태를 만든다.
- recovery를 누르지 않았으나 db001이 master로 승격된 후 db003이 slave로 붙은 걸 볼 수 있다. 

 

 

[출처] 따라하며 배우는 MySQL on Docker

[참고]

https://velog.io/@makeitcloud/%EB%9E%80-Availability-High-Availability-%EB%9E%80

https://dkswnkk.tistory.com/727

https://jhdatabase.tistory.com/entry/MySQL-Orchestrator-%EA%B5%AC%EC%B6%95-part-1

1. 브리지 생성


[1] 도커 네트워크 확인 & 브리지 생성

[root@dev opc]# docker network ls
NETWORK ID     NAME      DRIVER    SCOPE
697ad12cd5fa   bridge    bridge    local
d955f1181bf5   host      host      local
30e9346c2d17   none      null      local
[root@dev opc]# docker network create --driver bridge mybridge



[2] data,log 삭제하고 도커 컨테이너 재생성  

docker run -it --name db001 -p 3306:3306 -h db001 \
--net mybridge --net-alias=db001 \
-v /home/opc/db/db001/data:/var/lib/mysql \
-v /home/opc/db/db001/log:/var/log/mysql \
-v /home/opc/db/db001/conf:/etc/percona-server.conf.d \
-e MYSQL_ROOT_PASSWORD="root" -d percona:5.7.30 

docker run -it --name db002 -p 3307:3306 -h db002 \
--net mybridge --net-alias=db002 \
-v /home/opc/db/db002/data:/var/lib/mysql \
-v /home/opc/db/db002/log:/var/log/mysql \
-v /home/opc/db/db002/conf:/etc/percona-server.conf.d \
-e MYSQL_ROOT_PASSWORD="root" -d percona:5.7.30 

docker run -it --name db003 -p 3308:3306 -h db003 \
--net mybridge --net-alias=db003 \
-v /home/opc/db/db003/data:/var/lib/mysql \
-v /home/opc/db/db003/log:/var/log/mysql \
-v /home/opc/db/db003/conf:/etc/percona-server.conf.d \
-e MYSQL_ROOT_PASSWORD="root" -d percona:5.7.30

  

[3] master에서 user 생성 

mysql> CREATE USER 'repl'@'%' IDENTIFIED BY 'repl';
Query OK, 0 rows affected (0.01 sec)

mysql> GRANT REPLICATION SLAVE ON *.* TO 'repl'@'%';
Query OK, 0 rows affected (0.01 sec)



[4] ping 날려보기 

[root@db001 /]# ping db001
PING db001 (172.18.0.2) 56(84) bytes of data.
64 bytes from db001 (172.18.0.2): icmp_seq=1 ttl=64 time=0.047 ms
64 bytes from db001 (172.18.0.2): icmp_seq=2 ttl=64 time=0.043 ms
64 bytes from db001 (172.18.0.2): icmp_seq=3 ttl=64 time=0.044 ms
64 bytes from db001 (172.18.0.2): icmp_seq=4 ttl=64 time=0.044 ms
64 bytes from db001 (172.18.0.2): icmp_seq=5 ttl=64 time=0.043 ms
^C
--- db001 ping statistics ---
5 packets transmitted, 5 received, 0% packet loss, time 3999ms
rtt min/avg/max/mdev = 0.043/0.044/0.047/0.004 ms
[root@db001 /]#
[root@db001 /]# ping db002
PING db002 (172.18.0.3) 56(84) bytes of data.
64 bytes from db002.mybridge (172.18.0.3): icmp_seq=1 ttl=64 time=0.170 ms
64 bytes from db002.mybridge (172.18.0.3): icmp_seq=2 ttl=64 time=0.073 ms
64 bytes from db002.mybridge (172.18.0.3): icmp_seq=3 ttl=64 time=0.078 ms
^C
--- db002 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2000ms
rtt min/avg/max/mdev = 0.073/0.107/0.170/0.044 ms
[root@db001 /]#
[root@db001 /]# ping db003
PING db003 (172.18.0.4) 56(84) bytes of data.
64 bytes from db003.mybridge (172.18.0.4): icmp_seq=1 ttl=64 time=0.102 ms
64 bytes from db003.mybridge (172.18.0.4): icmp_seq=2 ttl=64 time=0.076 ms
64 bytes from db003.mybridge (172.18.0.4): icmp_seq=3 ttl=64 time=0.080 ms
^C


[5] slave 에 master 세팅

mysql> reset master;
Query OK, 0 rows affected (0.02 sec)

mysql> CHANGE MASTER TO MASTER_HOST='db001', \
    MASTER_USER='repl', MASTER_PASSWORD='repl', \
    MASTER_AUTO_POSITION=1;
Query OK, 0 rows affected, 2 warnings (0.02 sec)

mysql> start slave;
Query OK, 0 rows affected (0.01 sec)

mysql> show slave status\G;

>> 결과 

*************************** 1. row ***************************
               Slave_IO_State: Waiting for master to send event
                  Master_Host: db001
                  Master_User: repl
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: mysql-bin.000003
          Read_Master_Log_Pos: 635
               Relay_Log_File: db002-relay-bin.000003
                Relay_Log_Pos: 848
        Relay_Master_Log_File: mysql-bin.000003
             Slave_IO_Running: Yes
            Slave_SQL_Running: Yes
              Replicate_Do_DB:
          Replicate_Ignore_DB:
           Replicate_Do_Table:
       Replicate_Ignore_Table:
      Replicate_Wild_Do_Table:
  Replicate_Wild_Ignore_Table:
                   Last_Errno: 0
                   Last_Error:
                 Skip_Counter: 0
          Exec_Master_Log_Pos: 635
              Relay_Log_Space: 2927711
              Until_Condition: None
               Until_Log_File:
                Until_Log_Pos: 0
           Master_SSL_Allowed: No
           Master_SSL_CA_File:
           Master_SSL_CA_Path:
              Master_SSL_Cert:
            Master_SSL_Cipher:
               Master_SSL_Key:
        Seconds_Behind_Master: 0
Master_SSL_Verify_Server_Cert: No
                Last_IO_Errno: 0
                Last_IO_Error:
               Last_SQL_Errno: 0
               Last_SQL_Error:
  Replicate_Ignore_Server_Ids:
             Master_Server_Id: 100
                  Master_UUID: edab089d-a7d1-11ee-85d6-0242ac120002
             Master_Info_File: /var/lib/mysql/master.info
                    SQL_Delay: 0
          SQL_Remaining_Delay: NULL
      Slave_SQL_Running_State: Slave has read all relay log; waiting for more updates
           Master_Retry_Count: 86400
                  Master_Bind:
      Last_IO_Error_Timestamp:
     Last_SQL_Error_Timestamp:
               Master_SSL_Crl:
           Master_SSL_Crlpath:
           Retrieved_Gtid_Set: edab089d-a7d1-11ee-85d6-0242ac120002:1-7
            Executed_Gtid_Set: edab089d-a7d1-11ee-85d6-0242ac120002:1-7
                Auto_Position: 1
         Replicate_Rewrite_DB:
                 Channel_Name:
           Master_TLS_Version:
1 row in set (0.01 sec)


 

출처

인프런 - 따라하며 배우는 MySQL on Docker 를 보고 정리해보았습니다.

 

Master/Slave 구조를 사용하는 이유

서버에 트래픽이 몰려들 때 해결하는 방법으로,

컴퓨터 성능을 1) Scale-up 하거나, 컴퓨터를 여러대 두는 2) Scale-out이 있다. 

DB로 다수의 트랜잭션이 몰리면 race condition이 발생할 수 있다.

 

Replication(복제)으로 Master/Slave 구조를 형성하면 DB에 가해지는 부하를 분산하여 이러한 race condition을 미연에 방지할 수 있다. 일반적으로 Master에서 write(쓰기)를 하도록 하고, Slave에서는 read(읽기)를 하도록 하여, 부하를 분산한다. 

 

MySQL에서 Master/Slave가 동작하는 방식은 아래와 같다.

[1] Insert/Update/Delete 트랜잭션이 들어오면 Master에서 이를 처리하고 Binary Log에 변경사항을 기록한다.

[2] Master Thread가 비동기로 Binary Log를 읽어 Slave 서버로 전송한다.

[3] Slave의 I/O Thread는 [2]에서 전달한 Binary Log를 Relay Log에 저장한다.

[4] Slave의 SQL Thread는 [3]에서 저장한 Relay Log를 읽어 Storage engine에 최종 적용한다. 

출처:서버 분산 처리 환경에서 MySQL을 MasterSlave로 이중화하기(링크하단참조)

 

Binary Log는 my.cnf에서는 binlog라는 명칭으로 사용되는데,

MySQL에서 발생하는 모든 변경사항을 담고 있는 로그 파일을 말한다. 

MySQL의 디폴트 설정값에서는 이 Binary Log가 비활성화 되어 있기 때문에 my.cnf에 binlog를 활성화해주어야한다.

my.cnf에서 binlog 설정과 관련된 내용은 아래와 같다.

# Master에서 binlog 설정을 꼭 해주어야 binlog 내용을 replica에 전달할 수 있다.

[mysqld]
log_bin=mysql-bin      #binlog의 파일명을 mysql-bin으로 시작하게 설정
binlog_format=ROW      #binlog의 포맷을 row로 설정 (자세한 세팅은 앞선 블로그 내용 참고)
log_slave_updates=ON   #slave업데이트 여부 
expire_logs_days=90    #로그 저장 시간 (지정하지 않으면 로그가 계속 쌓인다)

 

 

Docker를 통해 Master/Slave 서버 구축하기

[1] 호스트 OS에서 Master와 Slave my.cnf 파일 설정하기 

db/db001, db/db002, db/db003 경로를 각각 만든 후에, 각 경로에 data, log, conf 디렉토리를 만들고, 권한을 777 준뒤,

conf 디렉토리에 my.cnf 파일을 각각 만들어 주었다. 

 

Master인 db001의 my.cnf 파일은 아래와 같다. 

[mysqld]
server-id=100              <-- server-id는 master, slave가 달라야한다.              
report_host=db001                
basedir=/var/lib/mysql            
datadir=/var/lib/mysql            
socket=/var/lib/mysql/mysql.sock   
log_bin=mysql-bin          <-- master에 log_bin 설정은 필수!
binlog_format=ROW                 
log-error=/var/log/mysql/mysql.log             
gtid_mode=ON                       
enforce-gtid-consistency=true               
symbolic-links=0
pid-file=/var/run/mysqld/mysqld.pid 
expire_logs_days=90       <-- log는 최대 90일만

[mysqld_safe]
socket=/var/lib/mysql/mysql.sock
pid-file=/var/run/mysqld/mysqld.pid
nice=0

 

Slave의 my.cnf 파일은 아래와 같다.

[mysqld]
server-id=300                        <-- slave id는 master와 달라야한다.
report_host=db003                
basedir=/var/lib/mysql            
datadir=/var/lib/mysql            
socket=/var/lib/mysql/mysql.sock   
log_bin=mysql-bin          
binlog_format=ROW                 
log-error=/var/log/mysql/mysql.log             
gtid_mode=ON                       
enforce-gtid-consistency=true     
log_slave_updates=ON                  <-- relay log 정보를 slave bin log에도 저장          
symbolic-links=0
pid-file=/var/run/mysqld/mysqld.pid 
expire_logs_days=90

[mysqld_safe]
socket=/var/lib/mysql/mysql.sock
pid-file=/var/run/mysqld/mysqld.pid
nice=0

 

[2] Docker를 통해 Master, Slave MySQL 서버를 각각 생성하기 ([1]의 my.cnf 파일 경로 마운트)
Master는 미리 만들어둬서, Slave를 두개 더 만들어줬다.

[root@dev opc]# docker run -it --name db002 -p 3307:3306 -h db002 -v /home/opc/db/db002/dat    a:/var/lib/mysql -v /home/opc/db/db002/log:/var/log/mysql -v /home/opc/db/db002/conf:/etc/percona-server.conf.d -e MYSQL_ROOT_PASSWORD="root" -d percona:5.7.30
[root@dev opc]# docker run -it --name db003 -p 3308:3306 -h db003 -v /home/opc/db/db003/dat    a:/var/lib/mysql -v /home/opc/db/db003/log:/var/log/mysql -v /home/opc/db/db003/conf:/etc/percona-server.conf.d -e MYSQL_ROOT_PASSWORD="root" -d percona:5.7.30

 

[3] Master 컨테이너에서 Replication User생성하기

Docker를 통해 Master 컨테이너의 MySQL에 접속한 뒤,

[root@dev opc]# docker exec -it -uroot db001 /bin/bash
[root@db001 /]# mysql -uroot -p

Slave에서 Master MySQL에 접속할 수 있도록 User를 하나 생성한 뒤, Replication 권한을 줬다.

mysql> CREATE USER 'repl'@'%' IDENTIFIED BY 'repl';
Query OK, 0 rows affected (0.01 sec)

mysql> GRANT REPLICATION SLAVE ON *.* TO 'repl'@'%';
Query OK, 0 rows affected (0.01 sec)

그리고 ifconfig를 통해 Master의 ip주소를 확인했다. 

ifconfig

 

[4] Slave 컨테이너에서 Master 지정하기 

Slave 컨테이너의 MySQL에 접속하는 방법은 동일하다.(위 참조)

[3]에서 확인한 Master MySQL의 ip/user 정보를 통해 master를 지정해준다. 

mysql> reset master;
Query OK, 0 rows affected (0.04 sec)

mysql> CHANGE MASTER TO MASTER_HOST='{{Master의 ip주소}}', \
    -> MASTER_USER='repl', MASTER_PASSWORD='repl', \
    -> MASTER_AUTO_POSITION=1;
Query OK, 0 rows affected, 2 warnings (0.02 sec)

그리고 slave를 시작한 후, 상태를 확인하면 Master가 제대로 지정된 걸 확인할 수 있었다.

start slave;

show slave status\G;
# 결과에 아래 내용이 있다면 slave 적용 완료됨 
Slave_IO_Running: Yes
Slave_SQL_Running: Yes

 

[5] 테스트해보기

Master, Slave에 동일명의 database와 테이블을 생성한 뒤, Master에서 insert 작업 후, Slave에서 확인한다.

 

[참고]

- 서버 분산 처리 환경에서 MySQL을 MasterSlave로 이중화하기

- https://jupiny.com/2017/11/07/docker-mysql-replicaiton/

 

 

호스트 OS에 log/config를 연결하기 위한 순서

[1] 호스트 OS에서 log,conf 파일 경로를 먼저 생성
[2] mysql 기본 설정 파일(my.cnf)을 호스트 OS의 conf 경로에 저장
     * 주의 ) 이 때, my.cnf 파일의 설정값은 컨테이너를 기준으로 한다.
       예를 들어, basedir=/var/lib/mysql 로 설정한다면, 이는 컨테이너의 /var/lib/mysql 경로를 의미한다. 
[3] 컨테이너를 재생성하며 -v 옵션을 통해 호스트 OS의 log/conf 경로와 컨테이너 log/conf 경로를 연결
     * my.cnf 에서 설정했던 log 경로가 곧 컨테이너 log 경로이다. 
       컨테이너 conf 경로는 my.cnf이 저장되는 아무 경로로 설정하면 된다.

 

호스트 OS에 log/conf 파일 경로 생성

기존 컨테이너는 삭제하고, 새로 data, log, config 를 저장할 경로를 생성한뒤 각 경로에 권한을 777로 설정했다.

# 경로 생성
mkdir db/db001/data db/db001/log db/db001/conf

# 권한 설정 
chmod 777 db/db001/data db/db001/log db/db001/conf

 

 

호스트 OS의 config 경로에 MySQL 기본 설정 파일 생성 - my.~~

MySQL에서는 기본 설정값을 my로 시작하는 파일에 담아 둔다. 

- 유닉스 계열 : my.cnf

- 윈도우 : my.ini

Docker 컨테이너에서 아래의 명령어를 치고 디폴트로 잡힌 my.cnf 파일 경로를 확인했다. 

docker exec db001 mysql --help

/etc/my.cnf부터 /etc/mysql/my.cnf, /usr/etc/mysql... 경로들 중에서 어딘가에 my.cnf이 있다는 거다.

(내 컨테이너 안에서는 확인해보니 /etc/my.cnf 경로에 my.cnf 파일이 담겨 있었다.)

Default options are read from the following files in the given order:
/etc/my.cnf /etc/mysql/my.cnf /usr/etc/my.cnf ~/.my.cnf

docker container 또한 앞서 말했듯 일종의 게스트 OS로 자신만의 분할 공간을 가지고 있기에,
docker container 내의 파일을 열어보기 위해서는 docker container의 쉘을 열어줘야 한다.
Unix 계열의 OS의 경우, sh/bash/zbash 의 쉘 종류들이 존재하는데, 그 중 bash를 사용하면 된다.
docker를 exec로 실행할 때, /bin/bash를 붙이면 해당 Container의 bash쉘을 실행시키겠다는 뜻이다.

[root@sideproject opc]# docker exec -it -uroot db001 /bin/bash


(mysql container의 mysql를 다이렉트로 실행하기 위해서는 docker exec -it {컨테이너명} mysql -uroot -p를 쓴다)

사이드로 빠진 얘기는 차치하고, 다시 /etc/my.cnf의 my.cnf 파일을 확인해보면 아래와 같다.

[root@db001 /]# cat /etc/my.cnf
#
# The Percona Server 5.7 configuration file.
#
#
# * IMPORTANT: Additional settings that can override those from this file!
#   The files must end with '.cnf', otherwise they'll be ignored.
#   Please make any edits and changes to the appropriate sectional files
#   included below.
#
!includedir /etc/my.cnf.d/
!includedir /etc/percona-server.conf.d/

해석하면, 

* 중요 : 이 파일을 통해 추가적인 세팅들을 덮어쓸 수 있다!
  파일들은 항상 .cnf 확장자로 끝나야 하며, 그렇지 않으면 무시된다.
  아래 경로들에 있는 부분 섹션 파일들과 같이 적절한 방식으로 작성해두어라.
!includedir /etc/my.cnf.d/
!includedir /etc/percona-server.conf.d/

하라는 대로 하기 위해서, 제시된 경로들을 확인해보니 파일이 딱 하나 있었다.

mysql 또한 하나의 소프트웨어 프로그램이기 때문에 client와 server가 존재하며,

my.cnf에 쓰는 mysql이 client 프로그램이고, mysqld가 server(=데몬) 프로그램을 의미했다.

아래의 mysqld는 그 중 서버 프로그램(이자 데몬 프로그램)을 말한다. 

# /etc/my.cnf.d/docker.cnf 파일 
# mysql의 background 설정
[mysqld]
skip-host-cache
skip-name-resolve

 

my.cnf 파일 구성하기

 

[ 시작 전에 - mysql의 동작 방식에 대해 간단히 살펴보기 ] 

mysql은 내부적으로 클라이언트 프로그램(mysql), 서버 프로그램(mysqld)를 두며,
socket을 통해 클라이언트-서버 간 양방향 통신을 한다.
이 때, socker 통신 방식으로 크게 두 가지의 방식을 사용한다. 
1) TCP/IP 통신 : 서버-클라이언트가 다른 컴퓨터에 있을 때 사용 
2) Unix Domain Socker 통신 : 서버-클라이언트가 같은 컴퓨터에 있을 때 mysql.sock 파일을 통해 통신
mysql를 로컬 컴퓨터에서 docker로 생성해줬기 때문에 지금 내 경우 mysql은 2)과 같이 socket 통신을 한다.
이 때 mysql.socket이 위치한 경로는 디폴트로 /var/lib/mysql/mysql.sock 이다.

mysql의 Replication(복제방식)은 여러가지가 있으며, 그 중 Async Replication은 Binary Log를 활용해 Replica를 형성한다.
Slave에서는 상위(ex.Master)로부터 로그를 받아 relay log에 저장하는데, 만약 log_slave_updates 파라미터가 활성화(ON)되어 있다면 이 로그를 자신의 binlog에도 함께 기록한다.

출처:https://hoing.io/archives/3111

정말 아름답게도 my.cnf 파일의 모든 옵션을 정리해준 블로그글이 있었다(갓),
그 중에 당장 필요한 것만 뽑았는데 세밀한 옵션 설정이 필요하다면 나중에 또 이분의 글을 참고하면 도움이 될 것 같다.

https://youngsam.net/entry/mysql-mycnf-%EB%82%B4%EC%9A%A9-%EC%84%A4%EB%AA%85-%EC%A0%95%EB%A6%AC

 

영삼넷 :: mysql my.cnf 내용 설명 정리

my.cnf : The file has system variables for DB environment. location of MariaDB SW in this docoment : /engn001/mysvc01/mariadb-10.0.26 location of my.cnf in this document: /engn001/mysvc01/MARIASVC/my.cnf my.cnf sample $ vi /engn001/mysvc01/MARIASVC/my.cnf

youngsam.net

# Mysql 서버 옵션
[mysqld]
server-id=1                        # 서버 id값/master,slave들이 서로 달라야함
report_host=db001                  # 호스트명
basedir=/var/lib/mysql             # 기본 경로 
datadir=/var/lib/mysql             # 데이터 저장 위치
socket=/var/lib/mysql/mysql.sock   # 소켓 파일 경로 
log_bin=mysql-bin                  # binlog(서버 내 모든 변경 내역) mysql-bin.0001 형식으로 저장
binlog_format=ROW                  # binlog 저장 방식 - statement/row/mixed 
                                # row : binary / statement : sql query / mixed : statement+row
log-error=/var/log/mysql/mysql.log # 에러 로그 경로                  
gtid_mode=ON                       # 트랜잭션 고유 식별자 ON
enforce-gtid-consistency=true      # gtid on할 때 DDL명령어 안되는 것 강제 해제
log_slave_updates                  # Slave라면 ON으로 자신의 binlog에 로그 저장
symbolic-links=0 # Disabling symbolic-links is recommended to prevent assorted security risks
pid-file=/var/run/mysqld/mysqld.pid # 프로세스 id 파일 경로 설정 (꼭 mysqld_safe에도 넣어야함)

# Mysqld_safe : mysqld를 감시하는 데몬으로, mysqld_safe가 mysqld를 실행한다.
[mysqld_safe]
socket=/var/lib/mysql/mysql.sock
pid-file=/var/run/mysqld/mysqld.pid
nice=0

conf 디렉토리에 my.cnf파일을 vi로 넣어두었다.  또 권한을 644(rw-r-r) 로 두었다. 

vi my.cnf

// rw-r-r 로 권한 설정
chmod 644 my.cnf

이제, 컨테이너를 재생성 해준다. 

 

컨테이너 재생성 및 실행 

# 컨테이너 생성
docker run -i -t --name db001 -h db001 -p 3306:3306 \ 
-v /home/opc/db/db001/data:/var/lib/mysql \ 
-v /home/opc/db/db001/log:/var/log/mysql \ 
-v /home/opc/db/db001/conf:/etc/percona-server.conf.d \       <--- 설정 파일 
-e MYSQL_ROOT_PASSWORD="root" -d percona:5.7.30

# 참고) 오라이클 클라우드를 쓰면 /home/opc/ 를 입력해줘야 처음 사용자 접속 경로에서 내려간다.

 

이 상태에서, /db/db001/log 로 가면, 아래와 같이 mysql.log가 잘 들어간 걸 볼 수 있었다.

[root@sideproject log]# ll
total 8
-rw-r-----. 1 polkitd input 4133 Dec 29 11:57 mysql.log

 

[참고]

인프런 > 따라하며 배우는 MySQL on Docker 를 듣고 정리한 내용

https://hoing.io/archives/3111

https://kihyun-log.tistory.com/entry/MySQL-binlog-format
https://antamis.tistory.com/9

https://velog.io/@inhwa1025/MySQL-%EC%84%A4%EC%A0%95-%ED%8C%8C%EC%9D%BC-my.cnf-%EC%98%B5%EC%85%98-%EC%A2%85%EB%A5%98

Docker와 VM의 차이

* VM : Virtual Machine 가상 머신으로, 분할 공간의 가상 환경을 제공한다.

* 호스트 OS : 서버 OS 

* 게스트 OS : VM이 서버 OS위에 올리는 가상 OS

* 하이퍼바이저 : 게스트 OS를 구동하고 모니터링하는 소프트웨어
  -> 유형 1 : Native/Bare-Metal 하이퍼바이저, 호스트 OS 없이 게스트 OS들만 존재
     ex. VMware의 ESXi, Citrix의 Xen, Microsoft의 Hyper-V
  -> 유형 2 : Hosted 하이퍼바이저, 호스트 OS 위에 게스트 OS들을 둔다. 
     ex. VmWare의 Workstation, Oracle의 VirtualBox

 

출처:https://velog.io/@kdaeyeop/%EB%8F%84%EC%BB%A4-Docker-%EC%99%80-VM%EC%9D%98-%EC%B0%A8%EC%9D%B4

 

가상 머신(VM)의 경우, 하이퍼바이저를 통해 호스트 OS 위에 게스트 OS들을 두거나, 호스트 OS 없이 게스트 OS들을 사용할 수 있도록 분할된 가상 환경을 제공한다. 이 경우, 각각의 분할된 OS 마다 자원을 할당해주어야 한다.
도커(Docker)의 경우, 이와 달리 하나의 호스트 OS 의 커널을 각각의 컨테이너가 공유하는 형태를 띈다. 


Docker의 컨테이너가 독립된 공간을 가질 수 있는 이유

Docker는 기본적으로 리눅스를 기반으로 만들어진 오픈 소스 프로그램이다. 
리눅스 커널의 Cgroup은 프로세스들이 쓸 수 있는 사용량을 제한하며, Name space는 각 프로세스가 볼 수 있는 범위를 제한한다. (자세한 내용은 아래 참고 링크 확인) 도커는 이러한 리눅스의 특성을 활용해 Container를 구성했고, 각 Container는 따라서 마치 게스트 OS와 같이 독립된 공간을 가질 수 있다. 



리눅스에서 Docker 설치하기 

나는 윈도우를 쓰고 있지만 도커는 Linux 기반이기에...

오라클 클라우드 리눅스 OS에 접속해 아래와 같이 Docker를 설치해줬다. 

yum install -y yum-utils
yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
yum install -y docker-ce
systemctl start docker
docker --version

 

OS가 리눅스가 아니면 홈페이지를 통해 Docker를 다운받을 수도 있었다.

https://www.docker.com/get-started/

 

Docker를 통해 컨테이너 생성

docker run -i -t --name [db이름] -e MYSQL_ROOT_PASSWORD="비밀번호" -d persona:5.7.30
// -it : 컨테이너에 쉘로 접속하기 위한 옵션
// --name : 컨테이너 이름 할당 
// -e : 환경변수 세팅 
// -d : 백그라운드로 컨테이너 실행

 

> Docker는 image만 있다면 어디서든지 컨테이너 생성이 가능하다.

> 컨테이너는 가상 머신과 마찬가지로 가상 IP 주소를 할당 받으며, 기본적으로 172.17.0.x의 IP를 순차적으로 할당한다. 

docker run -it --name network_test ubuntu:14.04

  * 위와 같이 -p 옵션이 없이 docker를 실행하면, 이 컨테이너는 외부에서 접속을 할 수 없고, 호스트에서만 접속이 가능하다.
> 따라서, 외부에서 접근을 할 수 있도록 하려면 이 컨테이너에 -p 옵션을 두고 {호스트port}:{도커port} 로 연결하거나, {외부IP:port}:{도커port} 로 연결하도록 해야한다.

docker run -it --name network_test -p {ip:port}:{port} ubuntu:14.04

 

원격으로 MySQL Container 접속하기

호스트의 3306 포트에서 컨테이너의 3306 포트로 연결하여, 호스트에서 컨테이너의 mysql를 접속할 수 있게 한다면,
아래와 같이 코드를 작성하면 된다. 

-- docker container 생성
docker run -it --name db001 -e MYSQL_ROOT_PASSWORD="root" -p 3306:3306 -d percona:5.7.30

-- percona에서 mysql 이미지를 다운로드한다.
https://docs.percona.com/percona-server/8.0/yum-download-rpm.html

 

> 이제 호스트OS 3306에서 컨테이너 3306로 MySQL 접속이 가능하게 됐다.  

> 하지만 위의 경우, 컨테이너를 삭제하면 컨테이너 계층의 mysql 데이터 또한 삭제되게 된다. mysql 처럼 데이터의 영속성이 중요한 경우 이와 같이 컨테이너-영속성 데이터가 종속관계가 되어서는 안된다.

  * mysql의 데이터는 기본적으로 /var/lib/mysql 경로에 저장하는데,
    Docker 컨테이너 안의 /var/lib/mysql 에 데이터가 저장되어, 컨테이너를 삭제하면 /var/lib/mysql 데이터가 유실된다. 
> 이를 막기 위한 방법은, 컨테이너와 독립적으로 데이터를 저장하는 것이다. 이때, 볼륨이라는 개념을 이해해야하는데, 볼륨은 운영체제에서 논리 드라이브(local drive)라고도 불리는 것으로, SSD와 같은 물리 드라이브와 달리 논리적으로만 존재하는 드라이브를 말한다. 대표적으로 C드라이브가 이 볼륨에 해당된다.
> 볼륨을 컴퓨터가 사용할 수 있도록 적용하는 과정을 마운트라고 하는데, 컨테이너가 삭제되더라도 데이터를 유지하기 위해서는, 호스트 OS로부터 컨테이너로 볼륨를 마운트해야 한다. 

> 볼륨을 마운트하는 방법은 크게 세가지가 있다.
   1) 호스트와 볼륨을 공유하는 방법   

   2) 볼륨 컨테이너를 활용하는 방법
   3) 도커가 관리하는 볼륨을 사용하는 방법 

출처 :&nbsp; 3. Docker Volume (tistory.com)

 

Docker Volume

1. 호스트와 볼륨 공유
-v 옵션을 통해 호스트 OS의 특정 디렉토리와 컨테이너의 특정 디렉토리를 공유할 수 있다. 

// 먼저 호스트에 디렉토를 생성한다.
mkdir -p /db/db001/data

// 호스트 디렉토리의 권한을 수정한다.
chmod 777 /db <-- /db 하위 폴더까지 권한 수정

// -v {호스트디렉토리}:{컨테이너디렉토리}
docker run -it --name db001 -p 3306:3306 \
-v /db/db001/data:/var/lib/mysql \
-e MYSQL_ROOT_PASSWORD="root" -d percona:5.7.30

 

2. 도커 볼륨 

이건 percona 사이트에서 권장하는 방식이기도 한데,
* percona에서 권장하는 docker를 통한 mysql 설치 https://docs.percona.com/percona-server/8.0/quickstart-docker.html

 

먼저 docker volume create로 볼륨을 생성한다.

docker volume create --name {볼륨 이름}


그리고 나서 volume ls로 볼륨을 조회하면 아래와 같이 볼륨 내역이 나타난다.

[root@sideproject opc]# docker volume ls
DRIVER    VOLUME NAME
local     ec9de5f4574d28879fead241b36addffc99ae8390048546c07ac2067265e8e56
local     mysqlVolume
local     myvol

이후 docker run과 함께 -v 옵션에 {호스트의 volume 이름}:{컨테이너 경로}를 넣어주면 Container안의 /var/lib/mysql 경로와 호스트의 /var/lib/docker/volumes/{볼륨이름}/_data와 마운트를 해준다. 

docker run -it --name db001 -p 3306:3306 \
-v myvolume:/var/lib/mysql\
-e MYSQL_ROOT_PASSWORD="root" -d percona:5.7.30

// 옵션 설명 
// --name : 컨테이너 이름 
// -d : detached container (백그라운드에서 동작한다)
// -e : 환경설정
// --volume : 영속적인 데이터베이스 스토리지 생성

아래의 명령어를 통해 확인해보니, /var/lib/docker/volumes의 하위로 호스트 경로가 생성되는 걸 볼 수 있었다. 

[root@sideproject opc]# docker inspect --type volume mysqlVolume
[
    {
        "CreatedAt": "2023-12-28T13:48:57Z",
        "Driver": "local",
        "Labels": null,
        "Mountpoint": "/var/lib/docker/volumes/mysqlVolume/_data",
        "Name": "mysqlVolume",
        "Options": null,
        "Scope": "local"
    }
]

이제 도커로 mysql에 접속을 해본다. 접속이 잘된다.

docker exec -it psmysql mysql -uroot -p

호스트에서 cd로 /var/lib/docker/volumes/{볼륨이름}/_data로 가니 mysql 데이터가 나타난다.

[root@sideproject _data]# ll
total 96708
-rw-r-----. 1 1001 1001       56 Dec 28 14:45 auto.cnf
-rw-r-----. 1 1001 1001      180 Dec 28 14:46 binlog.000001
-rw-r-----. 1 1001 1001       16 Dec 28 14:46 binlog.index
-rw-------. 1 1001 1001     1705 Dec 28 14:45 ca-key.pem
-rw-r--r--. 1 1001 1001     1120 Dec 28 14:45 ca.pem
-rw-r--r--. 1 1001 1001     1120 Dec 28 14:45 client-cert.pem
-rw-------. 1 1001 1001     1705 Dec 28 14:45 client-key.pem
-rw-r-----. 1 1001 1001   196608 Dec 28 14:46 #ib_16384_0.dblwr
-rw-r-----. 1 1001 1001  8585216 Dec 28 14:45 #ib_16384_1.dblwr
-rw-r-----. 1 1001 1001     5625 Dec 28 14:46 ib_buffer_pool
-rw-r-----. 1 1001 1001 12582912 Dec 28 14:46 ibdata1
-rw-r-----. 1 1001 1001 12582912 Dec 28 14:46 ibtmp1
drwxr-x---. 2 1001 1001     4096 Dec 28 14:46 #innodb_redo
drwxr-x---. 2 1001 1001      187 Dec 28 14:46 #innodb_temp
drwxr-x---. 2 1001 1001      143 Dec 28 14:45 mysql
-rw-r-----. 1 1001 1001 31457280 Dec 28 14:46 mysql.ibd
drwxr-x---. 2 1001 1001     8192 Dec 28 14:45 performance_schema
-rw-------. 1 1001 1001     1705 Dec 28 14:45 private_key.pem
-rw-r--r--. 1 1001 1001      452 Dec 28 14:45 public_key.pem
-rw-r--r--. 1 1001 1001     1120 Dec 28 14:45 server-cert.pem
-rw-------. 1 1001 1001     1705 Dec 28 14:45 server-key.pem
drwxr-x---. 2 1001 1001       28 Dec 28 14:46 sys
-rw-r-----. 1 1001 1001 16777216 Dec 28 14:46 undo_001
-rw-r-----. 1 1001 1001 16777216 Dec 28 14:46 undo_002

 

3. 묵시적인 볼륨 생성

-v 옵션으로 컨테이너 경로만 적어주고 볼륨명은 설정하지 않을 수도 있다.

이 경우, ddab0e38151fcbf21f049846c07c081c8c7b111ace4217afed91cd9014e81ab4 와 같이 볼륨명이 자동으로 생성된다. 호스트 경로에 위 볼륨명이 같이 붙기 때문에 경로가 엄청 길어져서 별로 권장되지는 않는 방식이다.

docker run -it -p 3306:3306 \
--name mysqlVolumeAuto \
-v /db/db001/data3 \
-e MYSQL_ROOT_PASSWORD="root" -d percona:5.7.30

 

 

[정리해보기] Docker 명령어 모음

// 컨테이너 풀
docker pull ubuntu:16.04

// 포어그라운드 실행
docker run -i -t ubuntu:16.04 bin/bash

// 이름 할당 
docker run -i -t --name my_ubuntu ubuntu:16.04 /bin/bash

// 컨테이너 포트 포워딩 
docker run -i -t --name my_ubuntu -p 80:80 /bin/bash

// 데몬으로 실행 
docker run -d -p 80:80 nginx 

// 컨테이너 종료 
exit

// 컨테이너 나오기
Ctrl + P,Q

// 컨테이너 목록 확인 
docker ps -a(모두확인)

// 컨테이너 중지 
docker stop my_ubuntu

// 컨테이너 중지 및 삭제 
docker rm -f my_ubuntu 

// 컨테이너 종료 시 자동 삭제 
docker run -i -t --rm my_ubuntu ubuntu:16.04

// 이미지 목록 
docker images

// 이미지 삭제 
dockr rmi ubuntu:16.04

[출처 : https://dongle94.github.io/docker/docker-basic-use/ ]

 

 

 

참고 
https://developer-cheol.tistory.com/29
3. Docker Volume (tistory.com)
https://selog.tistory.com/entry/%EA%B0%80%EC%83%81%ED%99%94-%EA%B0%80%EC%83%81%EB%A8%B8%EC%8B%A0VM%EA%B3%BC-%ED%95%98%EC%9D%B4%ED%8D%BC%EB%B0%94%EC%9D%B4%EC%A0%80-%EC%89%BD%EA%B2%8C-%EC%9D%B4%ED%95%B4%ED%95%98%EA%B8%B0
https://velog.io/@whattsup_kim/Linux-Kernel-%EC%BB%A8%ED%85%8C%EC%9D%B4%EB%84%88%EB%A5%BC-%EC%9C%84%ED%95%9C-%EB%A6%AC%EB%88%85%EC%8A%A4%EC%9D%98-%ED%94%84%EB%A1%9C%EC%84%B8%EC%8A%A4-%EA%B2%A9%EB%A6%AC-%EA%B8%B0%EB%8A%A5-cgroup-namespace-union-mount
https://velog.io/@kdaeyeop/%EB%8F%84%EC%BB%A4-Docker-%EC%99%80-VM%EC%9D%98-%EC%B0%A8%EC%9D%B4

https://dongle94.github.io/docker/docker-basic-use/

WSL를 통해서 리눅스를 접속 후 Docker를 사용해보려 하는데

이래저래 설정할게 많아 짜증이 나 그냥 클라우드를 써보기로 했다. 

 

AWS는 프리티어 기간이 지나면 비용이 발생하는데, 

사이드프로젝트를 하는데 비용을 내는게 싫어서 무료 클라우드를 찾아봤다.

클라우드 서버는 AWS, Azure, Redhat... 다양하게 있었는데 그 중에서 평생 무료로 쓸 수 있는

오라클 클라우드를 쓰기로 했다.

 

오라클 클라우드에서 무료 인스턴스를 생성하는 방법은 어렵지 않았다.

아래 유투브를 따라하면서 CentOS 인스턴스를 하나 만들어줬다. 

https://www.youtube.com/watch?v=AgJgEnQv6cw

 

+ Recent posts