Compute Engine에서 DRBD를 사용하여 가용성이 높은 MySQL 5.6 클러스터 배포

Last reviewed 2019-05-10 UTC

이 튜토리얼에서는 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 인스턴스가 통신할 수 없는 상황에서 이 쿼럼 기기 노드가 두 인스턴스 중 하나와 통신할 수 있으며 여전히 다수에 도달할 수 있습니다.

다음 다이어그램은 여기에 설명된 시스템의 아키텍처를 보여줍니다.

DRBD 및 Compute Engine을 사용하여 Google Cloud에 배포된 MySQL 5.6 데이터베이스를 보여주는 아키텍처

목표

  • 클러스터 인스턴스를 만듭니다.
  • 두 인스턴스에 MySQL과 DRBD를 설치합니다.
  • DRBD 복제를 구성합니다.
  • 인스턴스에 Pacemaker를 설치합니다.
  • 인스턴스에 Pacemaker 클러스터링을 구성합니다.
  • 인스턴스를 만들고 쿼럼 기기로 구성합니다.
  • 장애 조치를 테스트합니다.

비용

가격 계산기를 사용하면 예상 사용량을 기준으로 예상 비용을 산출할 수 있습니다.

시작하기 전에

  1. 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.
  2. In the Google Cloud console, on the project selector page, select or create a Google Cloud project.

    Go to project selector

  3. Make sure that billing is enabled for your Google Cloud project.

  4. Enable the Compute Engine API.

    Enable the API

  5. In the Google Cloud console, on the project selector page, select or create a Google Cloud project.

    Go to project selector

  6. Make sure that billing is enabled for your Google Cloud project.

  7. Enable the Compute Engine API.

    Enable the API

이 튜토리얼에서는 달리 명시하지 않는 한 Cloud Shell을 사용하여 명령어를 입력합니다.

이 문서에 설명된 태스크를 완료했으면 만든 리소스를 삭제하여 청구가 계속되는 것을 방지할 수 있습니다. 자세한 내용은 삭제를 참조하세요.

설정

이 섹션에서는 서비스 계정을 설정하고 환경 변수를 만들고 IP 주소를 예약합니다.

클러스터 인스턴스에 대한 서비스 계정 설정

  1. Cloud Shell을 엽니다.

    Cloud Shell 열기

  2. 서비스 계정을 만듭니다.

    gcloud iam service-accounts create mysql-instance \
        --display-name "mysql-instance"
    
  3. 이 튜토리얼에 필요한 역할을 서비스 계정에 연결합니다.

    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 환경 변수 만들기

  1. 이 튜토리얼에 필요한 환경 변수가 있는 파일을 만듭니다.

    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
    
  2. 현재 세션에서 환경 변수를 로드하고 이후 로그인 시 변수를 자동으로 로드하도록 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을 사용합니다.

  1. 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}"
    
  2. 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}"
    
  3. 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}
    
  4. 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 설치 및 구성

이 섹션에서는 database1database2 인스턴스에 DRBD 패키지를 설치하고 구성한 다음 database1에서 database2로 DRBD 복제를 시작합니다.

database1에 DRBD 구성

  1. Google Cloud 콘솔에서 VM 인스턴스 페이지로 이동합니다.

    VM 인스턴스 페이지

  2. database1 인스턴스 행에서 SSH를 클릭하여 인스턴스에 연결합니다.

  3. 환경 변수에 인스턴스 메타데이터를 검색하고 저장하는 파일을 만듭니다.

    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
    
  4. 파일에서 메타데이터 변수를 로드합니다.

    source ~/.varsrc
    
  5. 데이터 디스크를 포맷합니다.

    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를 참조하세요.

  6. DRBD를 설치합니다.

    sudo apt -y install drbd8-utils
    
  7. DRBD 구성 파일을 만듭니다.

    sudo bash -c 'cat <<EOF  > /etc/drbd.d/global_common.conf
    global {
        usage-count no;
    }
    common {
        protocol C;
    }
    EOF'
    
  8. 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"
    
  9. DRBD 커널 모듈을 로드합니다.

    sudo modprobe drbd
    
  10. /dev/sdb 디스크의 내용을 지웁니다.

    sudo dd if=/dev/zero of=/dev/sdb bs=1k count=1024
    
  11. DRBD 리소스 r0를 만듭니다.

    sudo drbdadm create-md r0
    
  12. DRBD를 불러옵니다.

    sudo drbdadm up r0
    
  13. 시스템 시작 시 DRBD를 중지하여 클러스터 리소스 관리 소프트웨어가 필요한 모든 서비스를 순서대로 시작하도록 합니다.

    sudo update-rc.d drbd disable
    

database2에 DRBD 구성

이제 database2 인스턴스에 DRBD 패키지를 설치하고 구성합니다.

  1. SSH를 통해 database2 인스턴스에 연결합니다.
  2. 환경 변수에 인스턴스 메타데이터를 검색하고 저장하는 .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
    
  3. 파일에서 메타데이터 변수를 로드합니다.

    source ~/.varsrc
    
  4. 데이터 디스크를 포맷합니다.

    sudo bash -c  "mkfs.ext4 -m 0 -F -E  lazy_itable_init=0,lazy_journal_init=0,discard /dev/sdb"
    
  5. DRBD 패키지를 설치합니다.

    sudo apt -y install drbd8-utils
    
  6. DRBD 구성 파일을 만듭니다.

    sudo bash -c 'cat <<EOF  > /etc/drbd.d/global_common.conf
    global {
        usage-count no;
    }
    common {
        protocol C;
    }
    EOF'
    
  7. 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"
    
  8. DRBD 커널 모듈을 로드합니다.

    sudo modprobe drbd
    
  9. /dev/sdb 디스크를 지웁니다.

    sudo dd if=/dev/zero of=/dev/sdb bs=1k count=1024
    
  10. DRBD 리소스 r0를 만듭니다.

    sudo drbdadm create-md r0
    
  11. DRBD를 불러옵니다.

    sudo drbdadm up r0
    
  12. 시스템 시작 시 DRBD를 중지하여 클러스터 리소스 관리 소프트웨어가 필요한 모든 서비스를 순서대로 시작하도록 합니다.

    sudo update-rc.d drbd disable
    

database1에서 database2로 DRBD 복제 시작

  1. SSH를 통해 database1 인스턴스에 연결합니다.
  2. 기본 노드의 모든 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
    
  3. DRBD의 상태를 확인합니다.

    sudo cat /proc/drbd | grep ============
    

    출력 형식은 다음과 같습니다.

    [===================>] sync'ed:100.0% (208/307188)M
    
  4. /dev/drbd/srv에 마운트합니다.

    sudo mount -o discard,defaults /dev/drbd0 /srv
    

MySQL과 Pacemaker 설치

이 섹션에서는 각 인스턴스에 MySQL과 Pacemaker를 설치합니다.

database1에 MySQL 설치

  1. SSH를 통해 database1 인스턴스에 연결합니다.
  2. 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'
    
  3. 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
    
  4. 패키지 목록을 업데이트합니다.

    sudo apt update
    
  5. MySQL 서버를 설치합니다.

    sudo apt -y install mysql-server
    

    비밀번호를 입력하라는 메시지가 표시되면 DRBDha2를 입력합니다.

  6. MySQL 서버를 중지합니다.

    sudo /etc/init.d/mysql stop
    
  7. 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'
    
  8. MySQL 서버의 임시 디렉터리를 만듭니다(mysql.conf에 구성됨).

    sudo mkdir /srv/tmp
    sudo chmod 1777 /srv/tmp
    
  9. 모든 MySQL 데이터를 DRBD 디렉터리 /srv/mysql로 이동합니다.

    sudo mv /var/lib/mysql /srv/mysql
    
  10. DRBD 복제 스토리지 볼륨 아래에서 /var/lib/mysql/srv/mysql에 연결합니다.

    sudo ln -s /srv/mysql /var/lib/mysql
    
  11. /srv/mysql 소유자를 mysql 프로세스로 변경합니다.

    sudo chown -R mysql:mysql /srv/mysql
    
  12. InnoDB 초기 데이터를 삭제하여 디스크가 최대한 정리되었는지 확인합니다.

    sudo bash -c "cd /srv/mysql && rm ibdata1 && rm ib_logfile*"
    

    InnoDB는 MySQL 데이터베이스 관리 시스템용 스토리지 엔진입니다.

  13. MySQL을 시작합니다.

    sudo /etc/init.d/mysql start
    
  14. 나중에 배포를 테스트하려면 원격 연결에 대한 루트 사용자에게 액세스 권한을 부여합니다.

    mysql -uroot -pDRBDha2 -e "GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' IDENTIFIED BY 'DRBDha2' WITH GRANT OPTION;"
    
  15. 클러스터 리소스 관리에서 처리하는 자동 MySQL 시작 기능을 끕니다.

    sudo update-rc.d -f mysql disable
    

database1에 Pacemaker 설치

  1. 앞에서 만든 .varsrc 파일에서 메타데이터 변수를 로드합니다.

    source ~/.varsrc
    
  2. MySQL 서버를 중지합니다.

    sudo /etc/init.d/mysql stop
    
  3. Pacemaker를 설치합니다.

    sudo apt -y install pcs
    
  4. 기본 인스턴스에서 시스템 시작 시 pcsd, corosync, pacemaker를 사용 설정합니다.

    sudo update-rc.d -f pcsd enable
    sudo update-rc.d -f corosync enable
    sudo update-rc.d -f pacemaker enable
    
  5. pacemaker 전에 시작하도록 corosync를 구성합니다.

    sudo update-rc.d corosync defaults 20 20
    sudo update-rc.d pacemaker defaults 30 10
    
  6. 인증을 위해 클러스터 사용자 비밀번호를 haCLUSTER3으로 설정합니다.

    sudo bash -c "echo  hacluster:haCLUSTER3 | chpasswd"
    
  7. corosync-keygen 스크립트를 실행하여 128비트 클러스터 승인 키를 생성하고 /etc/corosync/authkey에 씁니다.

    sudo corosync-keygen -l
    
  8. authkeydatabase2 인스턴스에 복사합니다. 암호를 묻는 메시지가 표시되면 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
    
  9. 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: 클러스터의 노드를 정의하고 노드에 도달할 수 있는 방법을 정의합니다(이 경우 database1database2 노드).
    • quorum/two_node: 기본적으로 노드가 2개인 클러스터에서는 아무 노드도 쿼럼을 확보하지 않습니다. quorum 섹션의 two_node에 값 '1'을 지정하여 이 설정을 재정의할 수 있습니다.

    이 설정을 통해 클러스터를 구성하고 나중에 쿼럼 기기 역할을 할 세 번째 노드를 추가할 수 있도록 클러스터를 준비할 수 있습니다.

  10. corosync의 서비스 디렉터리를 만듭니다.

    sudo mkdir -p /etc/corosync/service.d
    
  11. Pacemaker를 인식하도록 corosync를 구성합니다.

    sudo bash -c 'cat <<EOF  > /etc/corosync/service.d/pcmk
    service {
        name: pacemaker
        ver: 1
    }
    EOF'
    
  12. 기본적으로 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'
    
  13. corosyncpacemaker 서비스를 다시 시작합니다.

    sudo service corosync restart
    sudo service pacemaker restart
    
  14. Corosync 쿼럼 기기 패키지를 설치합니다.

    sudo apt -y install corosync-qdevice
    
  15. 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 설치

  1. SSH를 통해 database2 인스턴스에 연결합니다.
  2. 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'
    
  3. 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
    
  4. 패키지 목록을 업데이트합니다.

    sudo apt update
    
  5. MySQL 서버를 설치합니다.

    sudo apt -y install mysql-server
    

    비밀번호를 입력하라는 메시지가 표시되면 DRBDha2를 입력합니다.

  6. MySQL 서버를 중지합니다.

    sudo /etc/init.d/mysql stop
    
  7. 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'
    
  8. /var/lib/mysql 아래의 데이터를 제거하고 복제된 DRBD 볼륨의 마운트 지점 대상에 대한 심볼릭 링크를 추가합니다. DRBD 볼륨(/dev/drbd0)은 장애 조치가 발생할 때만 /srv에서 마운트됩니다.

    sudo rm -rf /var/lib/mysql
    sudo ln -s /srv/mysql /var/lib/mysql
    
  9. 클러스터 리소스 관리에서 처리하는 자동 MySQL 시작 기능을 끕니다.

    sudo update-rc.d -f mysql disable
    

database2에 Pacemaker 설치

  1. .varsrc 파일에서 메타데이터 변수를 로드합니다.

    source ~/.varsrc
    
  2. Pacemaker를 설치합니다.

    sudo apt -y install pcs
    
  3. 이전에 복사한 Corosync authkey 파일을 /etc/corosync/로 이동합니다.

    sudo mv ~/authkey /etc/corosync/
    sudo chown root: /etc/corosync/authkey
    sudo chmod 400 /etc/corosync/authkey
    
  4. 대기 인스턴스에서 시스템 시작시 pcsd, corosync, pacemaker를 사용 설정합니다.

    sudo update-rc.d -f pcsd enable
    sudo update-rc.d -f corosync enable
    sudo update-rc.d -f pacemaker enable
    
  5. pacemaker 전에 시작하도록 corosync를 구성합니다.

    sudo update-rc.d corosync defaults 20 20
    sudo update-rc.d pacemaker defaults 30 10
    
  6. 인증용 클러스터 사용자 비밀번호를 설정합니다. 비밀번호는 database1 인스턴스에 사용한 비밀번호(haCLUSTER3)와 동일합니다.

    sudo bash -c "echo  hacluster:haCLUSTER3 | chpasswd"
    
  7. 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"
    
  8. Corosync 서비스 디렉터리를 만듭니다.

    sudo mkdir /etc/corosync/service.d
    
  9. Pacemaker를 인식하도록 corosync를 구성합니다.

    sudo bash -c 'cat <<EOF  > /etc/corosync/service.d/pcmk
    service {
    name: pacemaker
    ver: 1
    }
    EOF'
    
  10. 기본적으로 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'
    
  11. corosyncpacemaker 서비스를 다시 시작합니다.

    sudo service corosync restart
    sudo service pacemaker restart
    
  12. Corosync 쿼럼 기기 패키지를 설치합니다.

    sudo apt -y install corosync-qdevice
    
  13. 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
    
  14. 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)
    

클러스터 시작

  1. SSH를 통해 database2 인스턴스에 연결합니다.
  2. .varsrc 파일에서 메타데이터 변수를 로드합니다.

    source ~/.varsrc
    
  3. 클러스터 노드에 대해 인증합니다.

    sudo pcs cluster auth --name mysql_cluster ${DATABASE1_INSTANCE_NAME} ${DATABASE2_INSTANCE_NAME} -u hacluster -p haCLUSTER3
    
  4. 클러스터를 시작합니다.

    sudo pcs cluster start --all
    
  5. 클러스터 상태를 확인합니다.

    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를 구성합니다.

  1. SSH를 통해 database1 인스턴스에 연결합니다.
  2. Pacemaker pcs 유틸리티를 사용하여 몇 가지 변경사항을 파일의 큐에 포함하고 나중에 이러한 변경사항을 CIB(Cluster Information Base)에 원자적으로 푸시합니다.

    sudo pcs cluster cib clust_cfg
    
  3. 나중에 쿼럼 기기를 배포하므로 STONITH를 사용 중지합니다.

    sudo pcs -f clust_cfg property set stonith-enabled=false
    
  4. 쿼럼 관련 설정을 사용 중지합니다. 나중에 쿼럼 기기 노드를 설정합니다.

    sudo pcs -f clust_cfg property set no-quorum-policy=stop
    
  5. 복구 후 Pacemaker가 리소스를 뒤로 이동하지 못하도록 방지합니다.

    sudo pcs -f clust_cfg resource defaults resource-stickiness=200
    
  6. 클러스터에 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
    
  7. 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
    
  8. DRBD 디스크를 마운트할 파일 시스템 리소스를 만듭니다.

    sudo pcs -f clust_cfg resource create mystore_FS Filesystem \
        device="/dev/drbd0" \
        directory="/srv" \
        fstype="ext4"
    
  9. 동일한 VM의 디스크 리소스와 함께 DRBD 리소스를 동일하게 배치하도록 클러스터를 구성합니다.

    sudo pcs -f clust_cfg constraint colocation add mystore_FS with primary_mysql INFINITY with-rsc-role=Master
    
  10. DRBD 기본 등급이 승급된 후에만 디스크 리소스를 가져오도록 클러스터를 구성합니다.

    sudo pcs -f clust_cfg constraint order promote primary_mysql then start mystore_FS
    
  11. 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
    
  12. 동일한 VM의 디스크 리소스와 함께 MySQL 리소스를 동일하게 배치하도록 클러스터를 구성합니다.

    sudo pcs -f clust_cfg constraint colocation add mysql_service with mystore_FS INFINITY
    
  13. 시작 순서에서 DRBD 파일 시스템이 MySQL 서비스보다 우선하는지 확인합니다.

    sudo pcs -f clust_cfg constraint order mystore_FS then mysql_service
    
  14. 알림 에이전트를 만들고 패치를 로그 파일에 수신자로 추가합니다.

    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
    
  15. 클러스터에 대한 변경 사항을 커밋합니다.

    sudo pcs cluster cib-push clust_cfg
    
  16. 모든 리소스가 온라인 상태인지 확인합니다.

    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
    

쿼럼 기기 구성

  1. SSH를 통해 qdevice 인스턴스에 연결합니다.
  2. pcscorosync-qnetd를 설치합니다.

    sudo apt update && sudo apt -y install pcs corosync-qnetd
    
  3. Pacemaker/Corosync 구성 시스템 데몬(pcsd) 서비스를 시작하고 시스템 시작 시 사용 설정합니다.

    sudo service pcsd start
    sudo update-rc.d pcsd enable
    
  4. 인증을 위해 클러스터 사용자 비밀번호(haCLUSTER3)를 설정합니다.

    sudo bash -c "echo  hacluster:haCLUSTER3 | chpasswd"
    
  5. 쿼럼 기기 상태를 확인합니다.

    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에 쿼럼 기기 설정 구성

  1. SSH를 통해 database1 노드에 연결합니다.
  2. .varsrc 파일에서 메타데이터 변수를 로드합니다.

    source ~/.varsrc
    
  3. 클러스터의 쿼럼 기기 노드를 인증합니다.

    sudo pcs cluster auth --name mysql_cluster ${QUORUM_INSTANCE_NAME} -u hacluster -p haCLUSTER3
    
  4. 쿼럼 기기를 클러스터에 추가합니다. ffsplit 알고리즘을 사용하면 활성 노드가 투표 수의 50% 이상을 기준으로 결정됩니다.

    sudo pcs quorum device add model net host=${QUORUM_INSTANCE_NAME} algorithm=ffsplit
    
  5. 쿼럼 설정을 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"
    
  6. corosync 서비스를 다시 시작하여 새 쿼럼 기기 설정을 새로고침합니다.

    sudo service corosync restart
    
  7. corosync 쿼럼 기기 데몬을 시작하고 시스템 시작 시 불러옵니다.

    sudo service corosync-qdevice start
    sudo update-rc.d corosync-qdevice defaults
    

database2의 쿼럼 기기 설정 구성

  1. SSH를 통해 database2 노드에 연결합니다.
  2. .varsrc 파일에서 메타데이터 변수를 로드합니다.

    source ~/.varsrc
    
  3. 쿼럼 설정을 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"
    
  4. corosync 서비스를 다시 시작하여 새 쿼럼 기기 설정을 새로고침합니다.

    sudo service corosync restart
    
  5. corosync 쿼럼 기기 데몬을 시작하고 시스템 시작 시 불러옵니다.

    sudo service corosync-qdevice start
    sudo update-rc.d corosync-qdevice defaults
    

클러스터 상태 확인

다음 단계는 클러스터 리소스가 온라인 상태인지 확인하는 것입니다.

  1. SSH를 통해 database1 인스턴스에 연결합니다.
  2. 클러스터 상태를 확인합니다.

    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
    
  3. 쿼럼 상태를 표시합니다.

    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
    
  4. 쿼럼 기기 상태를 표시합니다.

    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로 구성

  1. Cloud Shell을 엽니다.

    Cloud Shell 열기

  2. 비관리형 인스턴스 그룹을 만들고 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}
    
  3. 비관리형 인스턴스 그룹을 만들고 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}
    
  4. port 3306 상태 확인을 만듭니다.

    gcloud compute health-checks create tcp mysql-backend-healthcheck \
        --port 3306
    
  5. 리전 내부 백엔드 서비스를 만듭니다.

    gcloud compute backend-services create mysql-ilb \
        --load-balancing-scheme internal \
        --region ${CLUSTER_REGION} \
        --health-checks mysql-backend-healthcheck \
        --protocol tcp
    
  6. 두 인스턴스 그룹을 백엔드 서비스에 백엔드로 추가합니다.

    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}
    
  7. 부하 분산기에 대한 전달 규칙을 만듭니다.

    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
    
  8. 내부 부하 분산기 상태 확인을 허용하는 방화벽 규칙을 만듭니다.

    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
    
  9. 부하 분산기 상태를 확인하려면 Google Cloud 콘솔에서 부하 분산 페이지로 이동합니다.

    부하 분산 페이지 열기

  10. mysql-ilb를 클릭합니다.

    이미지

    클러스터는 지정된 시간에 하나의 인스턴스만 MySQL을 실행하도록 허용하므로 내부 부하 분산기의 측면에서는 하나의 인스턴스만 정상입니다.

    이미지

MySQL 클라이언트에서 클러스터에 연결

  1. SSH를 통해 mysql-client 인스턴스에 연결합니다.
  2. 패키지 정의를 업데이트합니다.

    sudo apt-get update
    
  3. MySQL 클라이언트를 설치합니다.

    sudo apt-get install -y mysql-client
    
  4. 샘플 데이터로 테이블을 만들고 채우는 스크립트 파일을 만듭니다.

    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
    
  5. 테이블을 만듭니다.

    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 인스턴스를 시작합니다.
  • 분할 브레인 문제를 시뮬레이션하려면 database1database2 사이에 네트워크 파티션을 만듭니다.

  1. Cloud Shell을 엽니다.

    Cloud Shell 열기

  2. database1 인스턴스를 중지합니다.

    gcloud compute instances stop ${DATABASE1_INSTANCE_NAME} \
        --zone=${DATABASE1_INSTANCE_ZONE}
    
  3. 클러스터의 상태를 확인합니다.

    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
    
  4. database1 인스턴스를 시작합니다.

    gcloud compute instances start ${DATABASE1_INSTANCE_NAME} \
        --zone=${DATABASE1_INSTANCE_ZONE}
    
  5. 클러스터의 상태를 확인합니다.

    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
    
  6. database2 인스턴스를 중지합니다.

    gcloud compute instances stop ${DATABASE2_INSTANCE_NAME} \
        --zone=${DATABASE2_INSTANCE_ZONE}
    
  7. 클러스터의 상태를 확인합니다.

    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
    
  8. database2 인스턴스를 시작합니다.

    gcloud compute instances start ${DATABASE2_INSTANCE_NAME} \
        --zone=${DATABASE2_INSTANCE_ZONE}
    
  9. 클러스터의 상태를 확인합니다.

    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
    
  10. database1database2 사이에 네트워크 파티션을 만듭니다.

    gcloud compute firewall-rules create block-comms \
        --description="no MySQL communications" \
        --action=DENY \
        --rules=all \
        --source-tags=mysql \
        --target-tags=mysql \
        --priority=800
    
  11. 몇 분 후에 클러스터의 상태를 확인합니다. 쿼럼 정책은 네트워크 파티션 상황에서 가장 낮은 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
    
  12. 네트워크 파티션을 제거하려면 네트워크 방화벽 규칙을 삭제합니다. (메시지가 표시되면 Y를 누릅니다.)

    gcloud compute firewall-rules delete block-comms
    
  13. 클러스터 상태가 정상으로 돌아왔는지 확인합니다.

    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
    
  14. SSH를 통해 mysql-client 인스턴스에 연결합니다.

  15. 셸에서 이전에 만든 테이블을 조회합니다.

    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 |
    +----+---------------------+------------+
    

장애 조치 시퀀스

클러스터의 기본 노드가 다운되면 장애 조치 시퀀스는 다음과 같습니다.

  1. 쿼럼 기기와 대기 노드 모두 기본 노드와의 연결이 끊어집니다.
  2. 쿼럼 기기는 대기 노드에 대해 투표하고 대기 노드는 자체적으로 투표합니다.
  3. 쿼럼이 대기 노드에 의해 획득됩니다.
  4. 대기 노드가 기본 노드로 승격됩니다.
  5. 새 기본 노드는 다음 작업을 수행합니다.
    1. DRBD를 기본으로 승격
    2. DRBD에서 MySQL 데이터 디스크를 마운트
    3. MySQL 시작
    4. 부하 분산기에 대해 정상적으로 작동
  6. 부하 분산기가 트래픽을 새 기본 노드로 보내기 시작합니다.

삭제

프로젝트 삭제

  1. In the Google Cloud console, go to the Manage resources page.

    Go to Manage resources

  2. In the project list, select the project that you want to delete, and then click Delete.
  3. In the dialog, type the project ID, and then click Shut down to delete the project.

다음 단계