이 튜토리얼에서는 DRBD(Distributed Replicated Block Device)와 Compute Engine을 사용하여 MySQL 5.6 데이터베이스를 Google Cloud에 배포하는 과정을 안내합니다. DRBD는 Linux 플랫폼용 분산 복제 스토리지 시스템입니다.
이 튜토리얼은 시스템 관리자, 개발자, 엔지니어, 데이터베이스 관리자, DevOps 엔지니어에게 유용합니다. 다음과 같은 이유로 인해 관리형 서비스를 사용하지 않고 직접 MySQL 인스턴스를 관리하는 것이 좋을 수 있습니다.
- MySQL의 리전 간 인스턴스를 사용하고 있습니다.
- MySQL의 관리형 버전에서 사용할 수 없는 매개변수를 설정해야 합니다.
- 관리형 버전에서 설정할 수 없는 방식으로 성능을 최적화하려고 합니다.
DRBD는 블록 기기 수준의 복제 기능을 제공합니다. 즉, MySQL 자체에서 복제를 구성할 필요가 없으며 즉시 부하 분산 및 보안 연결과 같은 DRBD 이점을 얻을 수 있습니다.
이 튜토리얼에서는 다음 항목을 사용합니다.
이 문서는 MySQL 클러스터링, DRBD 구성, Linux 리소스 관리와 같은 고급 기능을 참조하지만 이 리소스를 사용하는 경우 고급 지식이 필요하지 않습니다.
아키텍처
Pacemaker는 클러스터 리소스 관리자입니다. Corosync는 Pacemaker에서 사용하는 클러스터 통신 및 참여 패키지입니다. 이 튜토리얼에서는 DRBD를 사용하여 기본 인스턴스에서 대기 인스턴스로 MySQL 디스크를 복제합니다. 클라이언트가 MySQL 클러스터에 연결하려면 내부 부하 분산기도 배포해야 합니다.
Pacemaker가 관리하는 세 개의 컴퓨팅 인스턴스로 구성된 클러스터를 배포합니다. 기본 인스턴스와 대기 인스턴스로 사용되는 두 개의 인스턴스에 MySQL을 설치합니다. 세 번째 인스턴스는 쿼럼 기기 역할을 합니다.
클러스터에서 각 노드는 활성 노드, 즉 MySQL을 실행하는 노드에 대해 투표합니다. 노드가 2개인 클러스터에서는 활성 노드를 판단하는 데 하나의 투표 응답만 받습니다. 이러한 경우 클러스터 동작은 분할 브레인 문제 또는 다운타임을 초래할 수 있습니다. 두 노드 시나리오에서 한 번의 투표만 필요하므로 분할 브레인 문제는 두 노드가 모두 제어 권한을 가질 때 발생합니다. 연결이 끊어지는 경우 종료되는 노드가 항상 기본 노드로 구성된 노드일 때 다운타임이 발생합니다. 두 노드가 서로 연결이 끊어지면 두 개 이상의 클러스터 노드가 활성 노드라고 가정할 위험이 있습니다.
쿼럼 기기를 추가하면 이러한 상황을 방지할 수 있습니다. 쿼럼 기기는 중재자 역할을 하며 투표 작업만 수행합니다. 이렇게 하면 database1
인스턴스와 database2
인스턴스가 통신할 수 없는 상황에서 이 쿼럼 기기 노드가 두 인스턴스 중 하나와 통신할 수 있으며 여전히 다수에 도달할 수 있습니다.
다음 다이어그램은 여기에 설명된 시스템의 아키텍처를 보여줍니다.
목표
- 클러스터 인스턴스를 만듭니다.
- 두 인스턴스에 MySQL과 DRBD를 설치합니다.
- DRBD 복제를 구성합니다.
- 인스턴스에 Pacemaker를 설치합니다.
- 인스턴스에 Pacemaker 클러스터링을 구성합니다.
- 인스턴스를 만들고 쿼럼 기기로 구성합니다.
- 장애 조치를 테스트합니다.
비용
가격 계산기를 사용하면 예상 사용량을 기준으로 예상 비용을 산출할 수 있습니다.
시작하기 전에
- Sign in to your Google Cloud account. If you're new to Google Cloud, create an account to evaluate how our products perform in real-world scenarios. New customers also get $300 in free credits to run, test, and deploy workloads.
-
In the Google Cloud console, on the project selector page, select or create a Google Cloud project.
-
Make sure that billing is enabled for your Google Cloud project.
-
Enable the Compute Engine API.
-
In the Google Cloud console, on the project selector page, select or create a Google Cloud project.
-
Make sure that billing is enabled for your Google Cloud project.
-
Enable the Compute Engine API.
이 튜토리얼에서는 달리 명시하지 않는 한 Cloud Shell을 사용하여 명령어를 입력합니다.
이 문서에 설명된 태스크를 완료했으면 만든 리소스를 삭제하여 청구가 계속되는 것을 방지할 수 있습니다. 자세한 내용은 삭제를 참조하세요.
설정
이 섹션에서는 서비스 계정을 설정하고 환경 변수를 만들고 IP 주소를 예약합니다.
클러스터 인스턴스에 대한 서비스 계정 설정
Cloud Shell을 엽니다.
서비스 계정을 만듭니다.
gcloud iam service-accounts create mysql-instance \ --display-name "mysql-instance"
이 튜토리얼에 필요한 역할을 서비스 계정에 연결합니다.
gcloud projects add-iam-policy-binding ${DEVSHELL_PROJECT_ID} \ --member=serviceAccount:mysql-instance@${DEVSHELL_PROJECT_ID}.iam.gserviceaccount.com \ --role=roles/compute.instanceAdmin.v1 gcloud projects add-iam-policy-binding ${DEVSHELL_PROJECT_ID} \ --member=serviceAccount:mysql-instance@${DEVSHELL_PROJECT_ID}.iam.gserviceaccount.com \ --role=roles/compute.viewer gcloud projects add-iam-policy-binding ${DEVSHELL_PROJECT_ID} \ --member=serviceAccount:mysql-instance@${DEVSHELL_PROJECT_ID}.iam.gserviceaccount.com \ --role=roles/iam.serviceAccountUser
Cloud Shell 환경 변수 만들기
이 튜토리얼에 필요한 환경 변수가 있는 파일을 만듭니다.
cat <<EOF > ~/.mysqldrbdrc # Cluster instance names DATABASE1_INSTANCE_NAME=database1 DATABASE2_INSTANCE_NAME=database2 QUORUM_INSTANCE_NAME=qdevice CLIENT_INSTANCE_NAME=mysql-client # Cluster IP addresses DATABASE1_INSTANCE_IP="10.140.0.2" DATABASE2_INSTANCE_IP="10.140.0.3" QUORUM_INSTANCE_IP="10.140.0.4" ILB_IP="10.140.0.6" # Cluster zones and region DATABASE1_INSTANCE_ZONE="asia-east1-a" DATABASE2_INSTANCE_ZONE="asia-east1-b" QUORUM_INSTANCE_ZONE="asia-east1-c" CLIENT_INSTANCE_ZONE="asia-east1-c" CLUSTER_REGION="asia-east1" EOF
현재 세션에서 환경 변수를 로드하고 이후 로그인 시 변수를 자동으로 로드하도록 Cloud Shell을 설정합니다.
source ~/.mysqldrbdrc grep -q -F "source ~/.mysqldrbdrc" ~/.bashrc || echo "source ~/.mysqldrbdrc" >> ~/.bashrc
IP 주소 예약
Cloud Shell에서 세 개의 클러스터 노드 각각에 대한 내부 IP 주소를 예약합니다.
gcloud compute addresses create ${DATABASE1_INSTANCE_NAME} ${DATABASE2_INSTANCE_NAME} ${QUORUM_INSTANCE_NAME} \ --region=${CLUSTER_REGION} \ --addresses "${DATABASE1_INSTANCE_IP},${DATABASE2_INSTANCE_IP},${QUORUM_INSTANCE_IP}" \ --subnet=default
Compute Engine 인스턴스 만들기
다음 단계에서 클러스터 인스턴스는 Debian 9를 사용하고 클라이언트 인스턴스는 Ubuntu 16을 사용합니다.
Cloud Shell에서
asia-east1-a
영역에database1
이라는 MySQL 인스턴스를 만듭니다.gcloud compute instances create ${DATABASE1_INSTANCE_NAME} \ --zone=${DATABASE1_INSTANCE_ZONE} \ --machine-type=n1-standard-2 \ --network-tier=PREMIUM \ --maintenance-policy=MIGRATE \ --image-family=debian-9 \ --image-project=debian-cloud \ --boot-disk-size=50GB \ --boot-disk-type=pd-standard \ --boot-disk-device-name=${DATABASE1_INSTANCE_NAME} \ --create-disk=mode=rw,size=300,type=pd-standard,name=disk-1 \ --private-network-ip=${DATABASE1_INSTANCE_NAME} \ --tags=mysql --service-account=mysql-instance@${DEVSHELL_PROJECT_ID}.iam.gserviceaccount.com \ --scopes="https://www.googleapis.com/auth/compute,https://www.googleapis.com/auth/servicecontrol,https://www.googleapis.com/auth/service.management.readonly" \ --metadata="DATABASE1_INSTANCE_IP=${DATABASE1_INSTANCE_IP},DATABASE2_INSTANCE_IP=${DATABASE2_INSTANCE_IP},DATABASE1_INSTANCE_NAME=${DATABASE1_INSTANCE_NAME},DATABASE2_INSTANCE_NAME=${DATABASE2_INSTANCE_NAME},QUORUM_INSTANCE_NAME=${QUORUM_INSTANCE_NAME},DATABASE1_INSTANCE_ZONE=${DATABASE1_INSTANCE_ZONE},DATABASE2_INSTANCE_ZONE=${DATABASE2_INSTANCE_ZONE}"
asia-east1-b
영역에database2
라는 MySQL 인스턴스를 만듭니다.gcloud compute instances create ${DATABASE2_INSTANCE_NAME} \ --zone=${DATABASE2_INSTANCE_ZONE} \ --machine-type=n1-standard-2 \ --network-tier=PREMIUM \ --maintenance-policy=MIGRATE \ --image-family=debian-9 \ --image-project=debian-cloud \ --boot-disk-size=50GB \ --boot-disk-type=pd-standard \ --boot-disk-device-name=${DATABASE2_INSTANCE_NAME} \ --create-disk=mode=rw,size=300,type=pd-standard,name=disk-2 \ --private-network-ip=${DATABASE2_INSTANCE_NAME} \ --tags=mysql \ --service-account=mysql-instance@${DEVSHELL_PROJECT_ID}.iam.gserviceaccount.com \ --scopes="https://www.googleapis.com/auth/compute,https://www.googleapis.com/auth/servicecontrol,https://www.googleapis.com/auth/service.management.readonly" \ --metadata="DATABASE1_INSTANCE_IP=${DATABASE1_INSTANCE_IP},DATABASE2_INSTANCE_IP=${DATABASE2_INSTANCE_IP},DATABASE1_INSTANCE_NAME=${DATABASE1_INSTANCE_NAME},DATABASE2_INSTANCE_NAME=${DATABASE2_INSTANCE_NAME},QUORUM_INSTANCE_NAME=${QUORUM_INSTANCE_NAME},DATABASE1_INSTANCE_ZONE=${DATABASE1_INSTANCE_ZONE},DATABASE2_INSTANCE_ZONE=${DATABASE2_INSTANCE_ZONE}"
asia-east1-c
영역에 Pacemaker가 사용할 쿼럼 노드를 만듭니다.gcloud compute instances create ${QUORUM_INSTANCE_NAME} \ --zone=${QUORUM_INSTANCE_ZONE} \ --machine-type=n1-standard-1 \ --network-tier=PREMIUM \ --maintenance-policy=MIGRATE \ --image-family=debian-9 \ --image-project=debian-cloud \ --boot-disk-size=10GB \ --boot-disk-type=pd-standard \ --boot-disk-device-name=${QUORUM_INSTANCE_NAME} \ --private-network-ip=${QUORUM_INSTANCE_NAME}
MySQL 클라이언트 인스턴스를 만듭니다.
gcloud compute instances create ${CLIENT_INSTANCE_NAME} \ --image-family=ubuntu-1604-lts \ --image-project=ubuntu-os-cloud \ --tags=mysql-client \ --zone=${CLIENT_INSTANCE_ZONE} \ --boot-disk-size=10GB \ --metadata="ILB_IP=${ILB_IP}"
DRBD 설치 및 구성
이 섹션에서는 database1
및 database2
인스턴스에 DRBD 패키지를 설치하고 구성한 다음 database1
에서 database2
로 DRBD 복제를 시작합니다.
database1에 DRBD 구성
Google Cloud 콘솔에서 VM 인스턴스 페이지로 이동합니다.
database1
인스턴스 행에서 SSH를 클릭하여 인스턴스에 연결합니다.환경 변수에 인스턴스 메타데이터를 검색하고 저장하는 파일을 만듭니다.
sudo bash -c cat <<EOF > ~/.varsrc DATABASE1_INSTANCE_IP=$(curl -s "http://metadata.google.internal/computeMetadata/v1/instance/attributes/DATABASE1_INSTANCE_IP" -H "Metadata-Flavor: Google") DATABASE2_INSTANCE_IP=$(curl -s "http://metadata.google.internal/computeMetadata/v1/instance/attributes/DATABASE2_INSTANCE_IP" -H "Metadata-Flavor: Google") DATABASE1_INSTANCE_NAME=$(curl -s "http://metadata.google.internal/computeMetadata/v1/instance/attributes/DATABASE1_INSTANCE_NAME" -H "Metadata-Flavor: Google") DATABASE2_INSTANCE_NAME=$(curl -s "http://metadata.google.internal/computeMetadata/v1/instance/attributes/DATABASE2_INSTANCE_NAME" -H "Metadata-Flavor: Google") DATABASE2_INSTANCE_ZONE=$(curl -s "http://metadata.google.internal/computeMetadata/v1/instance/attributes/DATABASE2_INSTANCE_ZONE" -H "Metadata-Flavor: Google") DATABASE1_INSTANCE_ZONE=$(curl -s "http://metadata.google.internal/computeMetadata/v1/instance/attributes/DATABASE1_INSTANCE_ZONE" -H "Metadata-Flavor: Google") QUORUM_INSTANCE_NAME=$(curl -s "http://metadata.google.internal/computeMetadata/v1/instance/attributes/QUORUM_INSTANCE_NAME" -H "Metadata-Flavor: Google") EOF
파일에서 메타데이터 변수를 로드합니다.
source ~/.varsrc
데이터 디스크를 포맷합니다.
sudo bash -c "mkfs.ext4 -m 0 -F -E \ lazy_itable_init=0,lazy_journal_init=0,discard /dev/sdb"
mkfs.ext4
옵션에 대한 자세한 설명은 mkfs.ext4 manpage를 참조하세요.DRBD를 설치합니다.
sudo apt -y install drbd8-utils
DRBD 구성 파일을 만듭니다.
sudo bash -c 'cat <<EOF > /etc/drbd.d/global_common.conf global { usage-count no; } common { protocol C; } EOF'
DRBD 리소스 파일을 만듭니다.
sudo bash -c "cat <<EOF > /etc/drbd.d/r0.res resource r0 { meta-disk internal; device /dev/drbd0; net { allow-two-primaries no; after-sb-0pri discard-zero-changes; after-sb-1pri discard-secondary; after-sb-2pri disconnect; rr-conflict disconnect; } on database1 { disk /dev/sdb; address 10.140.0.2:7789; } on database2 { disk /dev/sdb; address 10.140.0.3:7789; } } EOF"
DRBD 커널 모듈을 로드합니다.
sudo modprobe drbd
/dev/sdb
디스크의 내용을 지웁니다.sudo dd if=/dev/zero of=/dev/sdb bs=1k count=1024
DRBD 리소스
r0
를 만듭니다.sudo drbdadm create-md r0
DRBD를 불러옵니다.
sudo drbdadm up r0
시스템 시작 시 DRBD를 중지하여 클러스터 리소스 관리 소프트웨어가 필요한 모든 서비스를 순서대로 시작하도록 합니다.
sudo update-rc.d drbd disable
database2에 DRBD 구성
이제 database2
인스턴스에 DRBD 패키지를 설치하고 구성합니다.
- SSH를 통해
database2
인스턴스에 연결합니다. 환경 변수에 인스턴스 메타데이터를 검색하고 저장하는
.varsrc
파일을 만듭니다.sudo bash -c cat <<EOF > ~/.varsrc DATABASE1_INSTANCE_IP=$(curl -s "http://metadata.google.internal/computeMetadata/v1/instance/attributes/DATABASE1_INSTANCE_IP" -H "Metadata-Flavor: Google") DATABASE2_INSTANCE_IP=$(curl -s "http://metadata.google.internal/computeMetadata/v1/instance/attributes/DATABASE2_INSTANCE_IP" -H "Metadata-Flavor: Google") DATABASE1_INSTANCE_NAME=$(curl -s "http://metadata.google.internal/computeMetadata/v1/instance/attributes/DATABASE1_INSTANCE_NAME" -H "Metadata-Flavor: Google") DATABASE2_INSTANCE_NAME=$(curl -s "http://metadata.google.internal/computeMetadata/v1/instance/attributes/DATABASE2_INSTANCE_NAME" -H "Metadata-Flavor: Google") DATABASE2_INSTANCE_ZONE=$(curl -s "http://metadata.google.internal/computeMetadata/v1/instance/attributes/DATABASE2_INSTANCE_ZONE" -H "Metadata-Flavor: Google") DATABASE1_INSTANCE_ZONE=$(curl -s "http://metadata.google.internal/computeMetadata/v1/instance/attributes/DATABASE1_INSTANCE_ZONE" -H "Metadata-Flavor: Google") QUORUM_INSTANCE_NAME=$(curl -s "http://metadata.google.internal/computeMetadata/v1/instance/attributes/QUORUM_INSTANCE_NAME" -H "Metadata-Flavor: Google") EOF
파일에서 메타데이터 변수를 로드합니다.
source ~/.varsrc
데이터 디스크를 포맷합니다.
sudo bash -c "mkfs.ext4 -m 0 -F -E lazy_itable_init=0,lazy_journal_init=0,discard /dev/sdb"
DRBD 패키지를 설치합니다.
sudo apt -y install drbd8-utils
DRBD 구성 파일을 만듭니다.
sudo bash -c 'cat <<EOF > /etc/drbd.d/global_common.conf global { usage-count no; } common { protocol C; } EOF'
DRBD 리소스 파일을 만듭니다.
sudo bash -c "cat <<EOF > /etc/drbd.d/r0.res resource r0 { meta-disk internal; device /dev/drbd0; net { allow-two-primaries no; after-sb-0pri discard-zero-changes; after-sb-1pri discard-secondary; after-sb-2pri disconnect; rr-conflict disconnect; } on ${DATABASE1_INSTANCE_NAME} { disk /dev/sdb; address ${DATABASE1_INSTANCE_IP}:7789; } on ${DATABASE2_INSTANCE_NAME} { disk /dev/sdb; address ${DATABASE2_INSTANCE_IP}:7789; } } EOF"
DRBD 커널 모듈을 로드합니다.
sudo modprobe drbd
/dev/sdb
디스크를 지웁니다.sudo dd if=/dev/zero of=/dev/sdb bs=1k count=1024
DRBD 리소스
r0
를 만듭니다.sudo drbdadm create-md r0
DRBD를 불러옵니다.
sudo drbdadm up r0
시스템 시작 시 DRBD를 중지하여 클러스터 리소스 관리 소프트웨어가 필요한 모든 서비스를 순서대로 시작하도록 합니다.
sudo update-rc.d drbd disable
database1에서 database2로 DRBD 복제 시작
- SSH를 통해
database1
인스턴스에 연결합니다. 기본 노드의 모든
r0
리소스를 덮어씁니다.sudo drbdadm -- --overwrite-data-of-peer primary r0 sudo mkfs.ext4 -m 0 -F -E lazy_itable_init=0,lazy_journal_init=0,discard /dev/drbd0
DRBD의 상태를 확인합니다.
sudo cat /proc/drbd | grep ============
출력 형식은 다음과 같습니다.
[===================>] sync'ed:100.0% (208/307188)M
/dev/drbd
를/srv
에 마운트합니다.sudo mount -o discard,defaults /dev/drbd0 /srv
MySQL과 Pacemaker 설치
이 섹션에서는 각 인스턴스에 MySQL과 Pacemaker를 설치합니다.
database1에 MySQL 설치
- SSH를 통해
database1
인스턴스에 연결합니다. MySQL 5.6 패키지 정의로 APT 저장소를 업데이트합니다.
sudo bash -c 'cat <<EOF > /etc/apt/sources.list.d/mysql.list deb http://repo.mysql.com/apt/debian/ stretch mysql-5.6\ndeb-src http://repo.mysql.com/apt/debian/ stretch mysql-5.6 EOF'
GPG 키를 APT
repository.srv
파일에 추가합니다.wget -O /tmp/RPM-GPG-KEY-mysql https://repo.mysql.com/RPM-GPG-KEY-mysql sudo apt-key add /tmp/RPM-GPG-KEY-mysql
패키지 목록을 업데이트합니다.
sudo apt update
MySQL 서버를 설치합니다.
sudo apt -y install mysql-server
비밀번호를 입력하라는 메시지가 표시되면
DRBDha2
를 입력합니다.MySQL 서버를 중지합니다.
sudo /etc/init.d/mysql stop
MySQL 구성 파일을 만듭니다.
sudo bash -c 'cat <<EOF > /etc/mysql/mysql.conf.d/my.cnf [mysqld] bind-address = 0.0.0.0 # You may want to listen at localhost at the beginning datadir = /var/lib/mysql tmpdir = /srv/tmp user = mysql EOF'
MySQL 서버의 임시 디렉터리를 만듭니다(
mysql.conf
에 구성됨).sudo mkdir /srv/tmp sudo chmod 1777 /srv/tmp
모든 MySQL 데이터를 DRBD 디렉터리
/srv/mysql
로 이동합니다.sudo mv /var/lib/mysql /srv/mysql
DRBD 복제 스토리지 볼륨 아래에서
/var/lib/mysql
을/srv/mysql
에 연결합니다.sudo ln -s /srv/mysql /var/lib/mysql
/srv/mysql
소유자를mysql
프로세스로 변경합니다.sudo chown -R mysql:mysql /srv/mysql
InnoDB
초기 데이터를 삭제하여 디스크가 최대한 정리되었는지 확인합니다.sudo bash -c "cd /srv/mysql && rm ibdata1 && rm ib_logfile*"
InnoDB는 MySQL 데이터베이스 관리 시스템용 스토리지 엔진입니다.
MySQL을 시작합니다.
sudo /etc/init.d/mysql start
나중에 배포를 테스트하려면 원격 연결에 대한 루트 사용자에게 액세스 권한을 부여합니다.
mysql -uroot -pDRBDha2 -e "GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' IDENTIFIED BY 'DRBDha2' WITH GRANT OPTION;"
클러스터 리소스 관리에서 처리하는 자동 MySQL 시작 기능을 끕니다.
sudo update-rc.d -f mysql disable
database1에 Pacemaker 설치
앞에서 만든
.varsrc
파일에서 메타데이터 변수를 로드합니다.source ~/.varsrc
MySQL 서버를 중지합니다.
sudo /etc/init.d/mysql stop
Pacemaker를 설치합니다.
sudo apt -y install pcs
기본 인스턴스에서 시스템 시작 시
pcsd
,corosync
,pacemaker
를 사용 설정합니다.sudo update-rc.d -f pcsd enable sudo update-rc.d -f corosync enable sudo update-rc.d -f pacemaker enable
pacemaker
전에 시작하도록corosync
를 구성합니다.sudo update-rc.d corosync defaults 20 20 sudo update-rc.d pacemaker defaults 30 10
인증을 위해 클러스터 사용자 비밀번호를
haCLUSTER3
으로 설정합니다.sudo bash -c "echo hacluster:haCLUSTER3 | chpasswd"
corosync-keygen
스크립트를 실행하여 128비트 클러스터 승인 키를 생성하고/etc/corosync/authkey
에 씁니다.sudo corosync-keygen -l
authkey
를database2
인스턴스에 복사합니다. 암호를 묻는 메시지가 표시되면Enter
를 누릅니다.sudo chmod 444 /etc/corosync/authkey gcloud beta compute scp /etc/corosync/authkey ${DATABASE2_INSTANCE_NAME}:~/authkey --zone=${DATABASE2_INSTANCE_ZONE} --internal-ip sudo chmod 400 /etc/corosync/authkey
Corosync 클러스터 구성 파일을 만듭니다.
sudo bash -c "cat <<EOF > /etc/corosync/corosync.conf totem { version: 2 cluster_name: mysql_cluster transport: udpu interface { ringnumber: 0 Bindnetaddr: ${DATABASE1_INSTANCE_IP} broadcast: yes mcastport: 5405 } } quorum { provider: corosync_votequorum two_node: 1 } nodelist { node { ring0_addr: ${DATABASE1_INSTANCE_NAME} name: ${DATABASE1_INSTANCE_NAME} nodeid: 1 } node { ring0_addr: ${DATABASE2_INSTANCE_NAME} name: ${DATABASE2_INSTANCE_NAME} nodeid: 2 } } logging { to_logfile: yes logfile: /var/log/corosync/corosync.log timestamp: on } EOF"
totem
섹션은 안정적 통신을 위해 Totem 프로토콜을 구성합니다. Corosync는 이 통신을 사용하여 클러스터 멤버십을 제어하고 클러스터 멤버가 서로 통신하는 방법을 지정합니다.설정에서 중요한 설정 항목은 다음과 같습니다.
transport
: 유니캐스트 모드(udpu)를 지정합니다.Bindnetaddr
: Corosync가 바인딩할 네트워크 주소를 지정합니다.nodelist
: 클러스터의 노드를 정의하고 노드에 도달할 수 있는 방법을 정의합니다(이 경우database1
및database2
노드).quorum
/two_node
: 기본적으로 노드가 2개인 클러스터에서는 아무 노드도 쿼럼을 확보하지 않습니다.quorum
섹션의two_node
에 값 '1'을 지정하여 이 설정을 재정의할 수 있습니다.
이 설정을 통해 클러스터를 구성하고 나중에 쿼럼 기기 역할을 할 세 번째 노드를 추가할 수 있도록 클러스터를 준비할 수 있습니다.
corosync
의 서비스 디렉터리를 만듭니다.sudo mkdir -p /etc/corosync/service.d
Pacemaker를 인식하도록
corosync
를 구성합니다.sudo bash -c 'cat <<EOF > /etc/corosync/service.d/pcmk service { name: pacemaker ver: 1 } EOF'
기본적으로
corosync
서비스를 사용합니다.sudo bash -c 'cat <<EOF > /etc/default/corosync # Path to corosync.conf COROSYNC_MAIN_CONFIG_FILE=/etc/corosync/corosync.conf # Path to authfile COROSYNC_TOTEM_AUTHKEY_FILE=/etc/corosync/authkey # Enable service by default START=yes EOF'
corosync
및pacemaker
서비스를 다시 시작합니다.sudo service corosync restart sudo service pacemaker restart
Corosync 쿼럼 기기 패키지를 설치합니다.
sudo apt -y install corosync-qdevice
DRBD 실패 이벤트를 처리할 셸 스크립트를 설치합니다.
sudo bash -c 'cat << 'EOF' > /var/lib/pacemaker/drbd_cleanup.sh #!/bin/sh if [ -z \$CRM_alert_version ]; then echo "\$0 must be run by Pacemaker version 1.1.15 or later" exit 0 fi tstamp="\$CRM_alert_timestamp: " case \$CRM_alert_kind in resource) if [ \${CRM_alert_interval} = "0" ]; then CRM_alert_interval="" else CRM_alert_interval=" (\${CRM_alert_interval})" fi if [ \${CRM_alert_target_rc} = "0" ]; then CRM_alert_target_rc="" else CRM_alert_target_rc=" (target: \${CRM_alert_target_rc})" fi case \${CRM_alert_desc} in Cancelled) ;; *) echo "\${tstamp}Resource operation "\${CRM_alert_task}\${CRM_alert_interval}" for "\${CRM_alert_rsc}" on "\${CRM_alert_node}": \${CRM_alert_desc}\${CRM_alert_target_rc}" >> "\${CRM_alert_recipient}" if [ "\${CRM_alert_task}" = "stop" ] && [ "\${CRM_alert_desc}" = "Timed Out" ]; then echo "Executing recovering..." >> "\${CRM_alert_recipient}" pcs resource cleanup \${CRM_alert_rsc} fi ;; esac ;; *) echo "\${tstamp}Unhandled \$CRM_alert_kind alert" >> "\${CRM_alert_recipient}" env | grep CRM_alert >> "\${CRM_alert_recipient}" ;; esac EOF' sudo chmod 0755 /var/lib/pacemaker/drbd_cleanup.sh sudo touch /var/log/pacemaker_drbd_file.log sudo chown hacluster:haclient /var/log/pacemaker_drbd_file.log
database2에 MySQL 설치
- SSH를 통해
database2
인스턴스에 연결합니다. MySQL 5.6 패키지로 APT 저장소를 업데이트합니다.
sudo bash -c 'cat <<EOF > /etc/apt/sources.list.d/mysql.list deb http://repo.mysql.com/apt/debian/ stretch mysql-5.6\ndeb-src http://repo.mysql.com/apt/debian/ stretch mysql-5.6 EOF'
GPT 키를 APT 저장소에 추가합니다.
wget -O /tmp/RPM-GPG-KEY-mysql https://repo.mysql.com/RPM-GPG-KEY-mysql sudo apt-key add /tmp/RPM-GPG-KEY-mysql
패키지 목록을 업데이트합니다.
sudo apt update
MySQL 서버를 설치합니다.
sudo apt -y install mysql-server
비밀번호를 입력하라는 메시지가 표시되면
DRBDha2
를 입력합니다.MySQL 서버를 중지합니다.
sudo /etc/init.d/mysql stop
MySQL 구성 파일을 만듭니다.
sudo bash -c 'cat <<EOF > /etc/mysql/mysql.conf.d/my.cnf [mysqld] bind-address = 0.0.0.0 # You may want to listen at localhost at the beginning datadir = /var/lib/mysql tmpdir = /srv/tmp user = mysql EOF'
/var/lib/mysql
아래의 데이터를 제거하고 복제된 DRBD 볼륨의 마운트 지점 대상에 대한 심볼릭 링크를 추가합니다. DRBD 볼륨(/dev/drbd0
)은 장애 조치가 발생할 때만/srv
에서 마운트됩니다.sudo rm -rf /var/lib/mysql sudo ln -s /srv/mysql /var/lib/mysql
클러스터 리소스 관리에서 처리하는 자동 MySQL 시작 기능을 끕니다.
sudo update-rc.d -f mysql disable
database2에 Pacemaker 설치
.varsrc
파일에서 메타데이터 변수를 로드합니다.source ~/.varsrc
Pacemaker를 설치합니다.
sudo apt -y install pcs
이전에 복사한 Corosync
authkey
파일을/etc/corosync/
로 이동합니다.sudo mv ~/authkey /etc/corosync/ sudo chown root: /etc/corosync/authkey sudo chmod 400 /etc/corosync/authkey
대기 인스턴스에서 시스템 시작시
pcsd
,corosync
,pacemaker
를 사용 설정합니다.sudo update-rc.d -f pcsd enable sudo update-rc.d -f corosync enable sudo update-rc.d -f pacemaker enable
pacemaker
전에 시작하도록corosync
를 구성합니다.sudo update-rc.d corosync defaults 20 20 sudo update-rc.d pacemaker defaults 30 10
인증용 클러스터 사용자 비밀번호를 설정합니다. 비밀번호는
database1
인스턴스에 사용한 비밀번호(haCLUSTER3
)와 동일합니다.sudo bash -c "echo hacluster:haCLUSTER3 | chpasswd"
corosync
구성 파일을 만듭니다.sudo bash -c "cat <<EOF > /etc/corosync/corosync.conf totem { version: 2 cluster_name: mysql_cluster transport: udpu interface { ringnumber: 0 Bindnetaddr: ${DATABASE2_INSTANCE_IP} broadcast: yes mcastport: 5405 } } quorum { provider: corosync_votequorum two_node: 1 } nodelist { node { ring0_addr: ${DATABASE1_INSTANCE_NAME} name: ${DATABASE1_INSTANCE_NAME} nodeid: 1 } node { ring0_addr: ${DATABASE2_INSTANCE_NAME} name: ${DATABASE2_INSTANCE_NAME} nodeid: 2 } } logging { to_logfile: yes logfile: /var/log/corosync/corosync.log timestamp: on } EOF"
Corosync 서비스 디렉터리를 만듭니다.
sudo mkdir /etc/corosync/service.d
Pacemaker를 인식하도록
corosync
를 구성합니다.sudo bash -c 'cat <<EOF > /etc/corosync/service.d/pcmk service { name: pacemaker ver: 1 } EOF'
기본적으로
corosync
서비스를 사용합니다.sudo bash -c 'cat <<EOF > /etc/default/corosync # Path to corosync.conf COROSYNC_MAIN_CONFIG_FILE=/etc/corosync/corosync.conf # Path to authfile COROSYNC_TOTEM_AUTHKEY_FILE=/etc/corosync/authkey # Enable service by default START=yes EOF'
corosync
및pacemaker
서비스를 다시 시작합니다.sudo service corosync restart sudo service pacemaker restart
Corosync 쿼럼 기기 패키지를 설치합니다.
sudo apt -y install corosync-qdevice
DRBD 실패 이벤트를 처리할 셸 스크립트를 설치합니다.
sudo bash -c 'cat << 'EOF' > /var/lib/pacemaker/drbd_cleanup.sh #!/bin/sh if [ -z \$CRM_alert_version ]; then echo "\$0 must be run by Pacemaker version 1.1.15 or later" exit 0 fi tstamp="\$CRM_alert_timestamp: " case \$CRM_alert_kind in resource) if [ \${CRM_alert_interval} = "0" ]; then CRM_alert_interval="" else CRM_alert_interval=" (\${CRM_alert_interval})" fi if [ \${CRM_alert_target_rc} = "0" ]; then CRM_alert_target_rc="" else CRM_alert_target_rc=" (target: \${CRM_alert_target_rc})" fi case \${CRM_alert_desc} in Cancelled) ;; *) echo "\${tstamp}Resource operation "\${CRM_alert_task}\${CRM_alert_interval}" for "\${CRM_alert_rsc}" on "\${CRM_alert_node}": \${CRM_alert_desc}\${CRM_alert_target_rc}" >> "\${CRM_alert_recipient}" if [ "\${CRM_alert_task}" = "stop" ] && [ "\${CRM_alert_desc}" = "Timed Out" ]; then echo "Executing recovering..." >> "\${CRM_alert_recipient}" pcs resource cleanup \${CRM_alert_rsc} fi ;; esac ;; *) echo "\${tstamp}Unhandled \$CRM_alert_kind alert" >> "\${CRM_alert_recipient}" env | grep CRM_alert >> "\${CRM_alert_recipient}" ;; esac EOF' sudo chmod 0755 /var/lib/pacemaker/drbd_cleanup.sh sudo touch /var/log/pacemaker_drbd_file.log sudo chown hacluster:haclient /var/log/pacemaker_drbd_file.log
Corosync 클러스터 상태를 확인합니다.
sudo corosync-cmapctl | grep "members...ip"
출력 형식은 다음과 같습니다.
runtime.totem.pg.mrp.srp.members.1.ip (str) = r(0) ip(10.140.0.2) runtime.totem.pg.mrp.srp.members.2.ip (str) = r(0) ip(10.140.0.3)
클러스터 시작
- SSH를 통해
database2
인스턴스에 연결합니다. .varsrc
파일에서 메타데이터 변수를 로드합니다.source ~/.varsrc
클러스터 노드에 대해 인증합니다.
sudo pcs cluster auth --name mysql_cluster ${DATABASE1_INSTANCE_NAME} ${DATABASE2_INSTANCE_NAME} -u hacluster -p haCLUSTER3
클러스터를 시작합니다.
sudo pcs cluster start --all
클러스터 상태를 확인합니다.
sudo pcs status
출력 형식은 다음과 같습니다.
Cluster name: mysql_cluster WARNING: no stonith devices and stonith-enabled is not false Stack: corosync Current DC: database2 (version 1.1.16-94ff4df) - partition with quorum Last updated: Sat Nov 3 07:24:53 2018 Last change: Sat Nov 3 07:17:17 2018 by hacluster via crmd on database2 2 nodes configured 0 resources configured Online: [ database1 database2 ] No resources Daemon Status: corosync: active/enabled pacemaker: active/enabled pcsd: active/enabled
클러스터 리소스를 관리하기 위한 Pacemaker 구성
다음으로 DRBD, 디스크, MySQL 및 쿼럼 리소스로 Pacemaker를 구성합니다.
- SSH를 통해
database1
인스턴스에 연결합니다. Pacemaker
pcs
유틸리티를 사용하여 몇 가지 변경사항을 파일의 큐에 포함하고 나중에 이러한 변경사항을 CIB(Cluster Information Base)에 원자적으로 푸시합니다.sudo pcs cluster cib clust_cfg
나중에 쿼럼 기기를 배포하므로 STONITH를 사용 중지합니다.
sudo pcs -f clust_cfg property set stonith-enabled=false
쿼럼 관련 설정을 사용 중지합니다. 나중에 쿼럼 기기 노드를 설정합니다.
sudo pcs -f clust_cfg property set no-quorum-policy=stop
복구 후 Pacemaker가 리소스를 뒤로 이동하지 못하도록 방지합니다.
sudo pcs -f clust_cfg resource defaults resource-stickiness=200
클러스터에 DRBD 리소스를 만듭니다.
sudo pcs -f clust_cfg resource create mysql_drbd ocf:linbit:drbd \ drbd_resource=r0 \ op monitor role=Master interval=110 timeout=30 \ op monitor role=Slave interval=120 timeout=30 \ op start timeout=120 \ op stop timeout=60
DRBD 리소스에 기본 역할이 하나만 할당되어 있는지 확인합니다.
sudo pcs -f clust_cfg resource master primary_mysql mysql_drbd \ master-max=1 master-node-max=1 \ clone-max=2 clone-node-max=1 \ notify=true
DRBD 디스크를 마운트할 파일 시스템 리소스를 만듭니다.
sudo pcs -f clust_cfg resource create mystore_FS Filesystem \ device="/dev/drbd0" \ directory="/srv" \ fstype="ext4"
동일한 VM의 디스크 리소스와 함께 DRBD 리소스를 동일하게 배치하도록 클러스터를 구성합니다.
sudo pcs -f clust_cfg constraint colocation add mystore_FS with primary_mysql INFINITY with-rsc-role=Master
DRBD 기본 등급이 승급된 후에만 디스크 리소스를 가져오도록 클러스터를 구성합니다.
sudo pcs -f clust_cfg constraint order promote primary_mysql then start mystore_FS
MySQL 서비스를 만듭니다.
sudo pcs -f clust_cfg resource create mysql_service ocf:heartbeat:mysql \ binary="/usr/bin/mysqld_safe" \ config="/etc/mysql/my.cnf" \ datadir="/var/lib/mysql" \ pid="/var/run/mysqld/mysql.pid" \ socket="/var/run/mysqld/mysql.sock" \ additional_parameters="--bind-address=0.0.0.0" \ op start timeout=60s \ op stop timeout=60s \ op monitor interval=20s timeout=30s
동일한 VM의 디스크 리소스와 함께 MySQL 리소스를 동일하게 배치하도록 클러스터를 구성합니다.
sudo pcs -f clust_cfg constraint colocation add mysql_service with mystore_FS INFINITY
시작 순서에서 DRBD 파일 시스템이 MySQL 서비스보다 우선하는지 확인합니다.
sudo pcs -f clust_cfg constraint order mystore_FS then mysql_service
알림 에이전트를 만들고 패치를 로그 파일에 수신자로 추가합니다.
sudo pcs -f clust_cfg alert create id=drbd_cleanup_file description="Monitor DRBD events and perform post cleanup" path=/var/lib/pacemaker/drbd_cleanup.sh sudo pcs -f clust_cfg alert recipient add drbd_cleanup_file id=logfile value=/var/log/pacemaker_drbd_file.log
클러스터에 대한 변경 사항을 커밋합니다.
sudo pcs cluster cib-push clust_cfg
모든 리소스가 온라인 상태인지 확인합니다.
sudo pcs status
출력 형식은 다음과 같습니다.
Online: [ database1 database2 ] Full list of resources: Master/Slave Set: primary_mysql [mysql_drbd] Masters: [ database1 ] Slaves: [ database2 ] mystore_FS (ocf::heartbeat:Filesystem): Started database1 mysql_service (ocf::heartbeat:mysql): Started database1
쿼럼 기기 구성
- SSH를 통해
qdevice
인스턴스에 연결합니다. pcs
와corosync-qnetd
를 설치합니다.sudo apt update && sudo apt -y install pcs corosync-qnetd
Pacemaker/Corosync 구성 시스템 데몬(
pcsd
) 서비스를 시작하고 시스템 시작 시 사용 설정합니다.sudo service pcsd start sudo update-rc.d pcsd enable
인증을 위해 클러스터 사용자 비밀번호(
haCLUSTER3
)를 설정합니다.sudo bash -c "echo hacluster:haCLUSTER3 | chpasswd"
쿼럼 기기 상태를 확인합니다.
sudo pcs qdevice status net --full
출력 형식은 다음과 같습니다.
QNetd address: *:5403 TLS: Supported (client certificate required) Connected clients: 0 Connected clusters: 0 Maximum send/receive size: 32768/32768 bytes
database1에 쿼럼 기기 설정 구성
- SSH를 통해
database1
노드에 연결합니다. .varsrc
파일에서 메타데이터 변수를 로드합니다.source ~/.varsrc
클러스터의 쿼럼 기기 노드를 인증합니다.
sudo pcs cluster auth --name mysql_cluster ${QUORUM_INSTANCE_NAME} -u hacluster -p haCLUSTER3
쿼럼 기기를 클러스터에 추가합니다.
ffsplit
알고리즘을 사용하면 활성 노드가 투표 수의 50% 이상을 기준으로 결정됩니다.sudo pcs quorum device add model net host=${QUORUM_INSTANCE_NAME} algorithm=ffsplit
쿼럼 설정을
corosync.conf
에 추가합니다.sudo bash -c "cat <<EOF > /etc/corosync/corosync.conf totem { version: 2 cluster_name: mysql_cluster transport: udpu interface { ringnumber: 0 Bindnetaddr: ${DATABASE1_INSTANCE_IP} broadcast: yes mcastport: 5405 } } quorum { provider: corosync_votequorum device { votes: 1 model: net net { tls: on host: ${QUORUM_INSTANCE_NAME} algorithm: ffsplit } } } nodelist { node { ring0_addr: ${DATABASE1_INSTANCE_NAME} name: ${DATABASE1_INSTANCE_NAME} nodeid: 1 } node { ring0_addr: ${DATABASE2_INSTANCE_NAME} name: ${DATABASE2_INSTANCE_NAME} nodeid: 2 } } logging { to_logfile: yes logfile: /var/log/corosync/corosync.log timestamp: on } EOF"
corosync
서비스를 다시 시작하여 새 쿼럼 기기 설정을 새로고침합니다.sudo service corosync restart
corosync
쿼럼 기기 데몬을 시작하고 시스템 시작 시 불러옵니다.sudo service corosync-qdevice start sudo update-rc.d corosync-qdevice defaults
database2의 쿼럼 기기 설정 구성
- SSH를 통해
database2
노드에 연결합니다. .varsrc
파일에서 메타데이터 변수를 로드합니다.source ~/.varsrc
쿼럼 설정을
corosync.conf
에 추가합니다.sudo bash -c "cat <<EOF > /etc/corosync/corosync.conf totem { version: 2 cluster_name: mysql_cluster transport: udpu interface { ringnumber: 0 Bindnetaddr: ${DATABASE2_INSTANCE_IP} broadcast: yes mcastport: 5405 } } quorum { provider: corosync_votequorum device { votes: 1 model: net net { tls: on host: ${QUORUM_INSTANCE_NAME} algorithm: ffsplit } } } nodelist { node { ring0_addr: ${DATABASE1_INSTANCE_NAME} name: ${DATABASE1_INSTANCE_NAME} nodeid: 1 } node { ring0_addr: ${DATABASE2_INSTANCE_NAME} name: ${DATABASE2_INSTANCE_NAME} nodeid: 2 } } logging { to_logfile: yes logfile: /var/log/corosync/corosync.log timestamp: on } EOF"
corosync
서비스를 다시 시작하여 새 쿼럼 기기 설정을 새로고침합니다.sudo service corosync restart
corosync 쿼럼 기기 데몬을 시작하고 시스템 시작 시 불러옵니다.
sudo service corosync-qdevice start sudo update-rc.d corosync-qdevice defaults
클러스터 상태 확인
다음 단계는 클러스터 리소스가 온라인 상태인지 확인하는 것입니다.
- SSH를 통해
database1
인스턴스에 연결합니다. 클러스터 상태를 확인합니다.
sudo pcs status
출력 형식은 다음과 같습니다.
Cluster name: mysql_cluster Stack: corosync Current DC: database1 (version 1.1.16-94ff4df) - partition with quorum Last updated: Sun Nov 4 01:49:18 2018 Last change: Sat Nov 3 15:48:21 2018 by root via cibadmin on database1 2 nodes configured 4 resources configured Online: [ database1 database2 ] Full list of resources: Master/Slave Set: primary_mysql [mysql_drbd] Masters: [ database1 ] Slaves: [ database2 ] mystore_FS (ocf::heartbeat:Filesystem): Started database1 mysql_service (ocf::heartbeat:mysql): Started database1 Daemon Status: corosync: active/enabled pacemaker: active/enabled pcsd: active/enabled
쿼럼 상태를 표시합니다.
sudo pcs quorum status
출력 형식은 다음과 같습니다.
Quorum information ------------------ Date: Sun Nov 4 01:48:25 2018 Quorum provider: corosync_votequorum Nodes: 2 Node ID: 1 Ring ID: 1/24 Quorate: Yes Votequorum information ---------------------- Expected votes: 3 Highest expected: 3 Total votes: 3 Quorum: 2 Flags: Quorate Qdevice Membership information ---------------------- Nodeid Votes Qdevice Name 1 1 A,V,NMW database1 (local) 2 1 A,V,NMW database2 0 1 Qdevice
쿼럼 기기 상태를 표시합니다.
sudo pcs quorum device status
출력 형식은 다음과 같습니다.
Qdevice information ------------------- Model: Net Node ID: 1 Configured node list: 0 Node ID = 1 1 Node ID = 2 Membership node list: 1, 2 Qdevice-net information ---------------------- Cluster name: mysql_cluster QNetd host: qdevice:5403 Algorithm: Fifty-Fifty split Tie-breaker: Node with lowest node ID State: Connected
내부 부하 분산기를 클러스터 IP로 구성
Cloud Shell을 엽니다.
비관리형 인스턴스 그룹을 만들고
database1
인스턴스를 추가합니다.gcloud compute instance-groups unmanaged create ${DATABASE1_INSTANCE_NAME}-instance-group \ --zone=${DATABASE1_INSTANCE_ZONE} \ --description="${DATABASE1_INSTANCE_NAME} unmanaged instance group" gcloud compute instance-groups unmanaged add-instances ${DATABASE1_INSTANCE_NAME}-instance-group \ --zone=${DATABASE1_INSTANCE_ZONE} \ --instances=${DATABASE1_INSTANCE_NAME}
비관리형 인스턴스 그룹을 만들고
database2
인스턴스를 추가합니다.gcloud compute instance-groups unmanaged create ${DATABASE2_INSTANCE_NAME}-instance-group \ --zone=${DATABASE2_INSTANCE_ZONE} \ --description="${DATABASE2_INSTANCE_NAME} unmanaged instance group" gcloud compute instance-groups unmanaged add-instances ${DATABASE2_INSTANCE_NAME}-instance-group \ --zone=${DATABASE2_INSTANCE_ZONE} \ --instances=${DATABASE2_INSTANCE_NAME}
port 3306
상태 확인을 만듭니다.gcloud compute health-checks create tcp mysql-backend-healthcheck \ --port 3306
리전 내부 백엔드 서비스를 만듭니다.
gcloud compute backend-services create mysql-ilb \ --load-balancing-scheme internal \ --region ${CLUSTER_REGION} \ --health-checks mysql-backend-healthcheck \ --protocol tcp
두 인스턴스 그룹을 백엔드 서비스에 백엔드로 추가합니다.
gcloud compute backend-services add-backend mysql-ilb \ --instance-group ${DATABASE1_INSTANCE_NAME}-instance-group \ --instance-group-zone ${DATABASE1_INSTANCE_ZONE} \ --region ${CLUSTER_REGION} gcloud compute backend-services add-backend mysql-ilb \ --instance-group ${DATABASE2_INSTANCE_NAME}-instance-group \ --instance-group-zone ${DATABASE2_INSTANCE_ZONE} \ --region ${CLUSTER_REGION}
부하 분산기에 대한 전달 규칙을 만듭니다.
gcloud compute forwarding-rules create mysql-ilb-forwarding-rule \ --load-balancing-scheme internal \ --ports 3306 \ --network default \ --subnet default \ --region ${CLUSTER_REGION} \ --address ${ILB_IP} \ --backend-service mysql-ilb
내부 부하 분산기 상태 확인을 허용하는 방화벽 규칙을 만듭니다.
gcloud compute firewall-rules create allow-ilb-healthcheck \ --direction=INGRESS --network=default \ --action=ALLOW --rules=tcp:3306 \ --source-ranges=130.211.0.0/22,35.191.0.0/16 --target-tags=mysql
부하 분산기 상태를 확인하려면 Google Cloud 콘솔에서 부하 분산 페이지로 이동합니다.
mysql-ilb
를 클릭합니다.클러스터는 지정된 시간에 하나의 인스턴스만 MySQL을 실행하도록 허용하므로 내부 부하 분산기의 측면에서는 하나의 인스턴스만 정상입니다.
MySQL 클라이언트에서 클러스터에 연결
- SSH를 통해
mysql-client
인스턴스에 연결합니다. 패키지 정의를 업데이트합니다.
sudo apt-get update
MySQL 클라이언트를 설치합니다.
sudo apt-get install -y mysql-client
샘플 데이터로 테이블을 만들고 채우는 스크립트 파일을 만듭니다.
cat <<EOF > db_creation.sql CREATE DATABASE source_db; use source_db; CREATE TABLE source_table ( id BIGINT NOT NULL AUTO_INCREMENT, timestamp timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, event_data float DEFAULT NULL, PRIMARY KEY (id) ); DELIMITER $$ CREATE PROCEDURE simulate_data() BEGIN DECLARE i INT DEFAULT 0; WHILE i < 100 DO INSERT INTO source_table (event_data) VALUES (ROUND(RAND()*15000,2)); SET i = i + 1; END WHILE; END$$ DELIMITER ; CALL simulate_data() EOF
테이블을 만듭니다.
ILB_IP=$(curl -s "http://metadata.google.internal/computeMetadata/v1/instance/attributes/ILB_IP" -H "Metadata-Flavor: Google") mysql -u root -pDRBDha2 "-h${ILB_IP}" < db_creation.sql
클러스터 테스트
배포된 클러스터의 HA 기능을 테스트하려면 다음 테스트를 수행할 수 있습니다.
- 마스터 데이터베이스가
database2
인스턴스로 장애 조치할 수 있는지 여부를 테스트하려면database1
인스턴스를 종료합니다. database1
이 클러스터에 다시 조인할 수 있는지 확인하려면database1
인스턴스를 시작합니다.- 마스터 데이터베이스가
database1
인스턴스로 장애 조치할 수 있는지 여부를 테스트하려면database2
인스턴스를 종료합니다. database2
가 클러스터에 다시 조인할 수 있고database1
인스턴스가 마스터 역할을 계속 유지하는지 확인하려면database2
인스턴스를 시작합니다.- 분할 브레인 문제를 시뮬레이션하려면
database1
과database2
사이에 네트워크 파티션을 만듭니다.
Cloud Shell을 엽니다.
database1
인스턴스를 중지합니다.gcloud compute instances stop ${DATABASE1_INSTANCE_NAME} \ --zone=${DATABASE1_INSTANCE_ZONE}
클러스터의 상태를 확인합니다.
gcloud compute ssh ${DATABASE2_INSTANCE_NAME} \ --zone=${DATABASE2_INSTANCE_ZONE} \ --command="sudo pcs status"
출력은 다음과 같이 표시됩니다. 변경한 구성이 작동하는지 확인합니다.
2 nodes configured 4 resources configured Online: [ database2 ] OFFLINE: [ database1 ] Full list of resources: Master/Slave Set: primary_mysql [mysql_drbd] Masters: [ database2 ] Stopped: [ database1 ] mystore_FS (ocf::heartbeat:Filesystem): Started database2 mysql_service (ocf::heartbeat:mysql): Started database2 Daemon Status: corosync: active/enabled pacemaker: active/enabled pcsd: active/enabled
database1
인스턴스를 시작합니다.gcloud compute instances start ${DATABASE1_INSTANCE_NAME} \ --zone=${DATABASE1_INSTANCE_ZONE}
클러스터의 상태를 확인합니다.
gcloud compute ssh ${DATABASE1_INSTANCE_NAME} \ --zone=${DATABASE1_INSTANCE_ZONE} \ --command="sudo pcs status"
출력 형식은 다음과 같습니다.
2 nodes configured 4 resources configured Online: [ database1 database2 ] Full list of resources: Master/Slave Set: primary_mysql [mysql_drbd] Masters: [ database2 ] Slaves: [ database1 ] mystore_FS (ocf::heartbeat:Filesystem): Started database2 mysql_service (ocf::heartbeat:mysql): Started database2 Daemon Status: corosync: active/enabled pacemaker: active/enabled pcsd: active/enabled
database2
인스턴스를 중지합니다.gcloud compute instances stop ${DATABASE2_INSTANCE_NAME} \ --zone=${DATABASE2_INSTANCE_ZONE}
클러스터의 상태를 확인합니다.
gcloud compute ssh ${DATABASE1_INSTANCE_NAME} \ --zone=${DATABASE1_INSTANCE_ZONE} \ --command="sudo pcs status"
출력 형식은 다음과 같습니다.
2 nodes configured 4 resources configured Online: [ database1 ] OFFLINE: [ database2 ] Full list of resources: Master/Slave Set: primary_mysql [mysql_drbd] Masters: [ database1 ] Stopped: [ database2 ] mystore_FS (ocf::heartbeat:Filesystem): Started database1 mysql_service (ocf::heartbeat:mysql): Started database1 Daemon Status: corosync: active/enabled pacemaker: active/enabled pcsd: active/enabled
database2
인스턴스를 시작합니다.gcloud compute instances start ${DATABASE2_INSTANCE_NAME} \ --zone=${DATABASE2_INSTANCE_ZONE}
클러스터의 상태를 확인합니다.
gcloud compute ssh ${DATABASE1_INSTANCE_NAME} \ --zone=${DATABASE1_INSTANCE_ZONE} \ --command="sudo pcs status"
출력 형식은 다음과 같습니다.
2 nodes configured 4 resources configured Online: [ database1 database2 ] Full list of resources: Master/Slave Set: primary_mysql [mysql_drbd] Masters: [ database1 ] Slaves: [ database2 ] mystore_FS (ocf::heartbeat:Filesystem): Started database1 mysql_service (ocf::heartbeat:mysql): Started database1 Daemon Status: corosync: active/enabled pacemaker: active/enabled pcsd: active/enabled
database1
과database2
사이에 네트워크 파티션을 만듭니다.gcloud compute firewall-rules create block-comms \ --description="no MySQL communications" \ --action=DENY \ --rules=all \ --source-tags=mysql \ --target-tags=mysql \ --priority=800
몇 분 후에 클러스터의 상태를 확인합니다. 쿼럼 정책은 네트워크 파티션 상황에서 가장 낮은 ID 노드이므로
database1
이 기본 역할을 유지하는 방법에 유의하세요. 그동안에는database2
MySQL 서비스가 중지됩니다. 이 쿼럼 메커니즘은 네트워크 파티션이 발생할 때 분할 브레인 문제를 방지합니다.gcloud compute ssh ${DATABASE1_INSTANCE_NAME} \ --zone=${DATABASE1_INSTANCE_ZONE} \ --command="sudo pcs status"
출력 형식은 다음과 같습니다.
2 nodes configured 4 resources configured Online: [ database1 ] OFFLINE: [ database2 ] Full list of resources: Master/Slave Set: primary_mysql [mysql_drbd] Masters: [ database1 ] Stopped: [ database2 ] mystore_FS (ocf::heartbeat:Filesystem): Started database1 mysql_service (ocf::heartbeat:mysql): Started database1
네트워크 파티션을 제거하려면 네트워크 방화벽 규칙을 삭제합니다. (메시지가 표시되면
Y
를 누릅니다.)gcloud compute firewall-rules delete block-comms
클러스터 상태가 정상으로 돌아왔는지 확인합니다.
gcloud compute ssh ${DATABASE1_INSTANCE_NAME} \ --zone=${DATABASE1_INSTANCE_ZONE} \ --command="sudo pcs status"
출력 형식은 다음과 같습니다.
2 nodes configured 4 resources configured Online: [ database1 database2 ] Full list of resources: Master/Slave Set: primary_mysql [mysql_drbd] Masters: [ database1 ] Slaves: [ database2 ] mystore_FS (ocf::heartbeat:Filesystem): Started database1 mysql_service (ocf::heartbeat:mysql): Started database1
SSH를 통해
mysql-client
인스턴스에 연결합니다.셸에서 이전에 만든 테이블을 조회합니다.
ILB_IP=$(curl -s "http://metadata.google.internal/computeMetadata/v1/instance/attributes/ILB_IP" -H "Metadata-Flavor: Google") mysql -uroot "-h${ILB_IP}" -pDRBDha2 -e "select * from source_db.source_table LIMIT 10"
출력에는 클러스터의 데이터 일관성을 확인하는 다음 형식의 레코드 10개가 나열되어야 합니다.
+----+---------------------+------------+ | id | timestamp | event_data | +----+---------------------+------------+ | 1 | 2018-11-27 21:00:09 | 1279.06 | | 2 | 2018-11-27 21:00:09 | 4292.64 | | 3 | 2018-11-27 21:00:09 | 2626.01 | | 4 | 2018-11-27 21:00:09 | 252.13 | | 5 | 2018-11-27 21:00:09 | 8382.64 | | 6 | 2018-11-27 21:00:09 | 11156.8 | | 7 | 2018-11-27 21:00:09 | 636.1 | | 8 | 2018-11-27 21:00:09 | 14710.1 | | 9 | 2018-11-27 21:00:09 | 11642.1 | | 10 | 2018-11-27 21:00:09 | 14080.3 | +----+---------------------+------------+
장애 조치 시퀀스
클러스터의 기본 노드가 다운되면 장애 조치 시퀀스는 다음과 같습니다.
- 쿼럼 기기와 대기 노드 모두 기본 노드와의 연결이 끊어집니다.
- 쿼럼 기기는 대기 노드에 대해 투표하고 대기 노드는 자체적으로 투표합니다.
- 쿼럼이 대기 노드에 의해 획득됩니다.
- 대기 노드가 기본 노드로 승격됩니다.
- 새 기본 노드는 다음 작업을 수행합니다.
- DRBD를 기본으로 승격
- DRBD에서 MySQL 데이터 디스크를 마운트
- MySQL 시작
- 부하 분산기에 대해 정상적으로 작동
- 부하 분산기가 트래픽을 새 기본 노드로 보내기 시작합니다.
삭제
프로젝트 삭제
- In the Google Cloud console, go to the Manage resources page.
- In the project list, select the project that you want to delete, and then click Delete.
- In the dialog, type the project ID, and then click Shut down to delete the project.
다음 단계
- DRBD에 대해 자세히 알아보세요.
- Pacemaker에 대해 자세히 읽어봅니다.
- Corosync Cluster Engine에 대해 자세히 읽어봅니다.
- 고급 MySQL 서버 5.6 설정은 MySQL 서버 관리 설명서를 참조하세요.
- MySQL에 대한 원격 액세스를 설정하려면 Compute Engine에서 MySQL에 대한 원격 액세스를 설정하는 방법을 참조하세요.
- MySQL에 대한 상세 설명은 공식 MySQL 문서를 참조하세요.
- Google Cloud에 대한 참조 아키텍처, 다이어그램, 권장사항을 살펴보세요. Cloud 아키텍처 센터를 살펴보세요.