도커,쿠버네티스를활용한컨테이너개발실전입문3

김지용·2022년 9월 7일
0

독서

목록 보기
10/11
post-thumbnail

오래된 구문이라 오류가 발생해서 흐름만 이해함
컨테이너 오케스트레이션을 통해서 서비스를 구성하는 여러 컨테이너로 분산 시킨다는 것을 이해하면 될듯하다. 도커 스웜단계에서도 견고한 시스템 내구성을 가진 구성이 되는데 컨테이너 오케스트레이션의 표준이 되는 쿠버네티스가 기대된다.

128p~

MySQL
마스터 - 슬레이브 구조로 구성
INSERT, UPDATE, DELETE 쿼리는 마스터 DB에 전달, SELECT 쿼리는 슬레이브 DB로부터 읽어오게 해 역할을 완전히 분리한다. 그리고 마스터 컨테이너에는 레플리카를 하나만 둔다.

API
API는 TODO앱에서 각 엔트리에 대한 기본적인 조작을 제공하는 RESTful API다.
API 서비스에 전달된 INSERT, UPDATE, DELETE 쿼리는 마스터 DB에 전달
, SELECT 쿼리는 슬레이브 DB에서 수행된다.

웹 UI
웹서비스에서 직접 MYSQL에 접속하지 않고 API를 경유한다.

Nginx
애플리케이션 프론트엔드 서버 및 API 앞단에 리버스 프록시 역할을 할 Nginx 배치
이 Nginx는 캐싱, 백엔드에 대한 유연한 라우팅, 접근 로그 생성 등의 역할도 겸한다.

다음 명령어를 통해 스웜클러스터에 노드 4개가 존재하는지 체크하기

docker container exec -it manager docker node ls

스웜 클러스터에 TODO 앱 구축
MySQL

  • mysql_master
  • mysql_slave
    Application
  • app_nginx
  • app_api
    Frontend
  • frontend_nginx
  • frontend_web

이전 장의 예저처럼 overlay 네트워크를 미리 갖춘다. 이를 통해 TODO 앱을 구성하는 각 서비스는 이 todoapp 네트워크에 속하게 될 것이다.

docker container exec -it manager docker network create --driver=overlay --attachable todoapp

개발을 시작하기 앞서 개발을 진행할 순서를 정리하면

  • 데이터 스토어 역할을 할 MySQL 서비스를 마스터-슬레이브 구조로 구축
  • MySQL과 데이터를 주고받을 API 구현
  • Nginx를 웹 애플리케이션과 API 사이에서 리버스 프록시 역할을 하도록 설정
  • API를 사용해 서버 사이드 렌더링을 수행할 웹 애플리케이션 구현
  • 프론트엔드 쪽에 리버스 프록시(Nginx) 배치

mysqld.conf

[mysqld]
character-set-server = utf8mb4
collation-server = utf8mb4_general_ci
pid-file	= /var/run/mysqld/mysqld.pid
socket		= /var/run/mysqld/mysqld.sock
datadir		= /var/lib/mysql
#log-error	= /var/log/mysql/error.log
# By default we only accept connections from localhost
#bind-address	= 127.0.0.1
# Disabling symbolic-links is recommended to prevent assorted security risks
symbolic-links=0
relay-log=mysqld-relay-bin 
relay-log-index=mysqld-relay-bin 

log-bin=/var/log/mysql/mysql-bin.log

log-bin
레플리케이션 사용을 위해 바이너리 로그가 필요한 설정이다.

server-id
server-id 값은 MySQL 서버를 식별하기 위한 유일값이다. 마스터-슬레이브로 구성된 스택 안에서 중복이 없도록 설정해야한다.

ex)
server-id = 1

위의 값은 모든 서버에서 중복되지 않아야 한다. 그러므로 tododb 이미지의 mysqld.cnf에 이 값을 기재해서는 안 된다.
MySQL 컨테이너를 실행하는 시점에 값을 결정하고 log-bin 설정 아래에 추가한다.

server-id 값을 파일에 추가하기 위해 tododb/add-server-id.sh파일에 다음과 같은 스크립트 작성

#!/bin/bash -e
OCTETS=(`hostname -i | tr -s '.' ' '`)

MYSQL_SERVER_ID=`expr ${OCTETS[2]} \* 256 + ${OCTETS[3]}`
echo "server-id=$MYSQL_SERVER_ID" >> /etc/mysql/mysql.conf.d/mysqld.cnf

이 스크립트는 컨테이너 IP 주소에서 3, 4번째 옥텟 값을 뽑아 서버 간에 중복되지 않는 server-id값을 설정한다. 컨테이너를 실행하는 시점에 이 스크립트를 실행하면 중복되지 않는 server-id 값을 mysqld.cnf 파일 뒤에 추가할 수 있다.

git clone https://github.com/gihyodocker/tododb

레플리케이션 설정
마스터와 슬레이브 간 레플리케이션 설정을 준비하고, 슬레이브 컨테이너가 실행될 때 자동으로 레플리카로 설정되게 한다.
[prepare.sh]

#!/bin/bash -e

# (1) 환경 변수로 마스터와 슬레이브 지정
if [ ! -z "$MYSQL_MASTER" ]; then
  echo "this container is master"
  exit 0
fi

echo "prepare as slave"

# (2) 슬레이브에서 마스터와 통신 가능 여부 확인
if [ -z "$MYSQL_MASTER_HOST" ]; then
  echo "mysql_master_host is not specified" 1>&2
  exit 1
fi

while :
do
  if mysql -h $MYSQL_MASTER_HOST -u root -p$MYSQL_ROOT_PASSWORD -e "quit" > /dev/null 2>&1 ; then
    echo "MySQL master is ready!"
    break
  else
    echo "MySQL master is not ready"
  fi
  sleep 3
done

# (3) 마스터에 레플리케이션용 사용자 생성 및 권한 부여
IP=`hostname -i`
IFS='.'
set -- $IP
SOURCE_IP="$1.$2.%.%"
mysql -h $MYSQL_MASTER_HOST -u root -p$MYSQL_ROOT_PASSWORD -e "CREATE USER IF NOT EXISTS '$MYSQL_REPL_USER'@'$SOURCE_IP' IDENTIFIED BY '$MYSQL_REPL_PASSWORD';"
mysql -h $MYSQL_MASTER_HOST -u root -p$MYSQL_ROOT_PASSWORD -e "GRANT REPLICATION SLAVE ON *.* TO '$MYSQL_REPL_USER'@'$SOURCE_IP';"

# (4) 마스터의 binlog 포지션 정보 확인
MASTER_STATUS_FILE=/tmp/master-status
mysql -h $MYSQL_MASTER_HOST -u root -p$MYSQL_ROOT_PASSWORD -e "SHOW MASTER STATUS\G" > $MASTER_STATUS_FILE
BINLOG_FILE=`cat $MASTER_STATUS_FILE | grep File | xargs | cut -d' ' -f2`
BINLOG_POSITION=`cat $MASTER_STATUS_FILE | grep Position | xargs | cut -d' ' -f2`
echo "BINLOG_FILE=$BINLOG_FILE"
echo "BINLOG_POSITION=$BINLOG_POSITION"

# (5) 레플리케이션 시작
mysql -u root -p$MYSQL_ROOT_PASSWORD -e "CHANGE MASTER TO MASTER_HOST='$MYSQL_MASTER_HOST', MASTER_USER='$MYSQL_REPL_USER', MASTER_PASSWORD='$MYSQL_REPL_PASSWORD', MASTER_LOG_FILE='$BINLOG_FILE', MASTER_LOG_POS=$BINLOG_POSITION;"
mysql -u root -p$MYSQL_ROOT_PASSWORD -e "START SLAVE;"

echo "slave started"
  1. 환경 변수에 따라 마스터/슬레이브로 설정
  2. 슬레이브 마스터 간의 통신 확인
  3. 마스터에 레플리카 사용자 및 권한 추가
  4. 마스터 binlog의 포지션 설정
  5. 레플리케이션 시작
    스크립트 등 이미지 빌드에 필요한 파일을 다 갖췄다.

Dockerfile

FROM mysql:5.7

# (1) 패키지 업데이트 및 wget 설치
RUN apt-get update
RUN apt-get install -y wget

# (2) entrykit 설치
RUN wget https://github.com/progrium/entrykit/releases/download/v0.4.0/entrykit_0.4.0_linux_x86_64.tgz
RUN tar -xvzf entrykit_0.4.0_linux_x86_64.tgz
RUN rm entrykit_0.4.0_linux_x86_64.tgz
RUN mv entrykit /usr/local/bin/
RUN entrykit --symlink

# (3) 스크립트 및 각종 설정 파일 복사
COPY add-server-id.sh /usr/local/bin/
COPY etc/mysql/mysql.conf.d/mysqld.cnf /etc/mysql/mysql.conf.d/
COPY etc/mysql/conf.d/mysql.cnf /etc/mysql/conf.d/
COPY prepare.sh /docker-entrypoint-initdb.d
COPY init-data.sh /usr/local/bin/
COPY sql /sql

# (4) 스크립트, mysqld 실행
# entrypoint.sh 스크립트는 tododb에는 없지만 기반 이미지인 mysql:5.7에 포함된 파일로 실행가능
ENTRYPOINT [ \
  "prehook", \
    "add-server-id.sh", \
    "--", \
  "docker-entrypoint.sh" \
]

CMD ["mysqld"]

이제 ch04/tododb:latest라는 이름의 이미지를 만든다.
(도커파일에서 FROM mysql:5.7이라고만 되어있는데 mysql:5.7-debian 처럼 명확한 버전을 지정해서
apt-get 명령어가 먹는다)

docker image build -t ch04/tododb:latest .
  1. 이미지 태그명 수정
docker image tag ch04/tododb:latest localhost:5000/ch04/tododb:latest
  1. 이미지 등록
docker image push localhost:5000/ch04/tododb:latest

이제 빌드된 이미지를 사용해 스웜에서 MySQL 마스터 및 슬레이브 역할을 할 2개의 서비스를 생성하고 실행하기

todo_mysql.yml을 스택폴더에 넣고 스웜으로 배포하기
1. 우선 todo_mysql.yml을 스택 todo_mysql로 다시 배포한다.

docker container exec -it manager docker stack deploy -c /stack/todo-mysql.yml todo_mysql
  1. 서비스 배치 현황 체크
docker container exec -it manager docker service ls

초기 데이터를 넣기 전 마스터 컨테이너가 어느 스웜 노드에 배치됐는지 확인

docker container exec -it manager docker service ps todo_mysql_master --no-trunc --filter "desired-state=running"

특정 컨테이너에 데이터를 넣는 명령을 표준출력으로 출력하기

docker container exec -it manager docker service ps todo_mysql_master --no-trunc --filter "desired-state=running" --format "docker container exec -it {{.Node}} docker container exec -it {{.Name}}.{{.ID}} bash"

아래와 같이 master 컨테이너에서 init-data.sh 스크립트를 실행해 테이블 및 초기 데이터 생성

docker container exec -it c1cb1a87cfc59f7841c3622ec22808e313ed8e24774df97cd453598c05032327 docker container exec -it todo_mysql_master.1.y6xh5zyjtv5j01a55nj53zbzz init-data.sh

컨테이너 아이디가 blank로 나와서 우선 패스

API 서비스 구축

docker image build -t ch04/todoapi:latest .
  1. 이미지 태그명 수정
docker image tag ch04/todoapi:latest localhost:5000/ch04/todoapi:latest
  1. 이미지 등록
docker image push localhost:5000/ch04/todoapi:latest
  1. 우선 todo_mysql.yml을 스택 echo로 다시 배포한다.
docker container exec -it manager docker stack deploy -c /stack/todo-mysql.yml todo_mysql
  1. 서비스 배치 현황 체크
docker container exec -it manager docker service ls

초기 데이터를 넣기 전 마스터 컨테이너가 어느 스웜 노드에 배치됐는지 확인

docker container exec -it manager docker service ps todo_mysql_master --no-trunc --filter "desired-state=running"

책이 옛날 책이라 일부 구문이 에러를 발생시키고 적용이 안되서 그냥 흐름만 이해함

profile
김죵입니당 ^^

0개의 댓글