由于網(wǎng)絡(luò)架構(gòu)的原因,在一般虛擬機或物理環(huán)境中常見的用 VIP 來實現(xiàn)雙機高可用方案,無法照搬到 Azure 平臺。但利用 Azure 平臺提供的負載均衡或者內(nèi)部負載均衡功能,可以達到類似的效果。
本文介紹如何基于 Azure Load Balancer (LB), 結(jié)合 Linux 開源的產(chǎn)品 DRBD,Pacemaker 和 Corosync 實現(xiàn) MariaDB 的雙機高可用,并且搭建了一個 web 環(huán)境用戶演示 HA 的故障轉(zhuǎn)移。
Note
在實際生產(chǎn)中,用戶請根據(jù)自己的需求在此架構(gòu)上進行擴展改進。
基本架構(gòu)如下:

前提
此處使用已經(jīng)存在的一個存儲賬號存儲所有的虛擬機磁盤。
虛擬網(wǎng)絡(luò)中至少兩個子網(wǎng),一個用于后端數(shù)據(jù)庫,一個用于前端 web。
如下圖,此處使用 lqihavnet 中 subnet-2 作為后端數(shù)據(jù)庫子網(wǎng);subnet-3 作為前端 web 子網(wǎng)。

創(chuàng)建虛擬機、可用性集和負載均衡
ASM 模式
在 Powershell 中執(zhí)行如下命令。
復(fù)制
add-azureaccount -e azurechinacloud
$stor="lqihastor"
$vnet="lqihavnet"
$svc="lqi1eha02"
$vmname1="lqi1ecmy01"
$vmname2="lqi1ecmy02"
$av1="mysqlav"
$av2="webav"
$vmname3="lqi1ecmy03"
$vmname4="lqi1ecmy04"
$sub1="Subnet-2"
$ip1="10.0.1.4"
$ip2="10.0.1.5"
$sub2="Subnet-3"
$ip3="10.0.2.4"
$ip4="10.0.2.5"
$loc="china east"
$imagename="f1179221e23b4dbb89e39d70e5bc9e72__OpenLogic-CentOS-72-20161027"
$vmsize="Small"
$vmuser="azureuser"
$vmpassword="P@ssw0rd01"
$datadisksize="5"
$ilb="lqilbmysql"
$epname1="MySQL"
$prot1="TCP"
$locport1="3306"
$pubport1="3306"
$ilbdist="SourceIP"
$ilbip="10.0.1.10"
$lb="lqilbweb"
$epname2="HTTP"
$prot2="TCP"
$locport2="80"
$pubport2="80"
$probeport="80"
$lbdist="SourceIP"
Set-AzureSubscription -SubscriptionId 9ef8a15c-15a2-4ef1-a19b-e31876ab177c -CurrentStorageAccountName $stor
創(chuàng)建后端數(shù)據(jù)庫虛擬機:設(shè)置網(wǎng)絡(luò),靜態(tài)內(nèi)網(wǎng) IP,添加數(shù)據(jù)磁盤。
復(fù)制
New-AzureVMConfig -Name "$vmname1" -InstanceSize $vmsize? -ImageName $imagename -AvailabilitySetName $av1 |
Add-AzureProvisioningConfig -Linux -LinuxUser $vmuser -Password $vmpassword |
Set-AzureSubnet -SubnetNames $sub1 |
Set-AzureStaticVNetIP -IPAddress $ip1 |
Add-AzureDataDisk -CreateNew -DiskSizeInGB $datadisksize -DiskLabel "DataDisk" -LUN 0 |
New-AzureVM -ServiceName $svc -vNetName $vnet? -Location $loc
New-AzureVMConfig -Name "$vmname2" -InstanceSize $vmsize? -ImageName $imagename -AvailabilitySetName $av1 |
Add-AzureProvisioningConfig -Linux -LinuxUser $vmuser -Password $vmpassword |
Set-AzureSubnet -SubnetNames $sub1 |
Set-AzureStaticVNetIP -IPAddress $ip2 |
Add-AzureDataDisk -CreateNew -DiskSizeInGB $datadisksize -DiskLabel "DataDisk" -LUN 0 |
New-AzureVM -ServiceName $svc -vNetName $vnet? -Location $loc
創(chuàng)建內(nèi)部負載均衡,并將虛擬機加入負載均衡。
復(fù)制
Add-AzureInternalLoadBalancer -ServiceName $svc -InternalLoadBalancerName $ilb –SubnetName $sub1 –StaticVNetIPAddress $ilbip
Get-AzureVM –ServiceName $svc –Name $vmname1 | Add-AzureEndpoint -Name $epname1 -Protocol $prot1 -LocalPort $locport1 -PublicPort $pubport1 -LoadBalancerDistribution $ilbdist –DefaultProbe -InternalLoadBalancerName $ilb | update-AzureVM
Get-AzureVM –ServiceName $svc –Name $vmname2 | Add-AzureEndpoint -Name $epname1 -Protocol $prot1 -LocalPort $locport1 -PublicPort $pubport1 -LoadBalancerDistribution $ilbdist –DefaultProbe -InternalLoadBalancerName $ilb | update-AzureVM
創(chuàng)建前端 web 虛擬機:設(shè)置網(wǎng)絡(luò),靜態(tài)內(nèi)網(wǎng) IP,加入可用性集,配置負載均衡。
復(fù)制
New-AzureVMConfig -Name "$vmname3" -InstanceSize $vmsize? -ImageName $imagename -AvailabilitySetName $av2 |
Add-AzureProvisioningConfig -Linux -LinuxUser $vmuser -Password $vmpassword |
Set-AzureSubnet -SubnetNames $sub2 |
Set-AzureStaticVNetIP -IPAddress $ip3 |
Add-AzureEndpoint -Name $epname2 -Protocol $prot2 -PublicPort $pubport2 -LocalPort $locport2 -LBSetName $lb -ProbePort $probeport -ProbeProtocol $prot2 -ProbeIntervalInSeconds 10 |
New-AzureVM -ServiceName $svc -vNetName $vnet? -Location $loc
New-AzureVMConfig -Name "$vmname4" -InstanceSize $vmsize? -ImageName $imagename -AvailabilitySetName $av2 |
Add-AzureProvisioningConfig -Linux -LinuxUser $vmuser -Password $vmpassword |
Set-AzureSubnet -SubnetNames $sub2 |
Set-AzureStaticVNetIP -IPAddress $ip4 |
Add-AzureEndpoint -Name $epname2 -Protocol $prot2 -PublicPort $pubport2 -LocalPort $locport2 -LBSetName $lb -ProbePort $probeport -ProbeProtocol $prot2 -ProbeIntervalInSeconds 10 |
New-AzureVM -ServiceName $svc -vNetName $vnet? -Location $loc
ARM 模式
從該 GitHub Repo :Azure-Customized-Resources中部署。
配置后端數(shù)據(jù)庫 HA
后端數(shù)據(jù)庫使用 DRBD + Pacemake + Corosync 實現(xiàn) MariaDB 主備集群。
其中,DRBD 實現(xiàn)數(shù)據(jù)的復(fù)制。管理工具 drbdadm。更多參考點擊drbd 介紹、工作原理及腦裂故障處理。
Corosync 是集群引擎,管理消息和成員。Pacemaker 是集群資源管理器,管理工具 pcs。
CentOS 7 中,將原來的管理工具進行了改進集成,現(xiàn)在僅需要使用 pcs 即可管理引擎和資源,進行配置同步。
如果您使用 CentOS 6,配置流程一樣,但配置使用的命令參數(shù)需要調(diào)整。
CentOS 7 開始,由于 license 問題,mysql 數(shù)據(jù)庫改成了開源的 MariaDB。
CentOS 7默認開啟了 SeLinux 增強安全功能,為方便 demo,這里關(guān)閉該功能,生產(chǎn)環(huán)境中如果需要開啟,在配置 DRDB 等時需要額外配置一些 SeLinux 規(guī)則,這里省略介紹。
配置前準備工作
在兩個節(jié)點上分別執(zhí)行如下命令:
在兩節(jié)點上編輯/etc/selinux/config,將SELINUX改為disabled,保存文件,重啟服務(wù)器。

用全盤做一個主分區(qū)/dev/sdc, 不需要格式化成任何文件系統(tǒng),該分區(qū)將由 DRBD 接管,文件系統(tǒng)將建立在 DRBD 設(shè)備上。
復(fù)制
# fdisk /dev/sdc
配置 yum 倉庫以及后續(xù)需要使用的安裝包。
復(fù)制
# wget http://www.elrepo.org/elrepo-release-7.0-2.el7.elrepo.noarch.rpm
# rpm -ivh elrepo-release-7.0-2.el7.elrepo.noarch.rpm
# rpm --import /etc/pki/rpm-gpg/RPM-GPG-KEY-elrepo.org
# yum repolist
配置DRBD
在兩個節(jié)點上分別執(zhí)行如下命令。
安裝 DRBD 模塊,安裝完成后,重啟服務(wù)器。
復(fù)制
# yum install kmod-drbd84 drbd84-utils
加載 DRBD 內(nèi)核模塊,使用 lsmod 查看是否加載成功。
復(fù)制
# modprobe drbd
# lsmod | grep drbd

在兩個節(jié)點上,新建一個DRBD 資源。
命令中的mysqlr0,lqi1ecmy01,10.0.1.4,lqilecmy02,10.0.1.5部分根據(jù)自己的環(huán)境替換。
復(fù)制
# vi /etc/drbd.d/mysqlr0.res
resource mysqlr0 {
protocol C;
on lqi1ecmy01 {
device /dev/drbd1;
disk /dev/sdc;
address 10.0.1.4:7788;
meta-disk internal;
}
on lqi1ecmy02 {
device /dev/drbd1;
disk /dev/sdc;
address 10.0.1.5:7788;
meta-disk internal;
}
}
初始化 DRBD 資源,在兩個節(jié)點上分別執(zhí)行:
復(fù)制
# drbdadm create-md mysqlr0
啟動 DRBD 服務(wù),一個節(jié)點上執(zhí)行 start 命令后,立刻在另一個節(jié)點同步執(zhí)行,兩條命令執(zhí)行完畢,DRDB 服務(wù)將成功啟動。使用 status 命令查看服務(wù)狀態(tài),使用 enable 命令設(shè)置開機自啟動。
復(fù)制
# systemctl start drbd
# systemctl status drbd
# systemctl enable drbd
選擇其中一個節(jié)點執(zhí)行下面命令。命令執(zhí)行成功,該節(jié)點將成為 DRBD 主節(jié)點,另一節(jié)點成為備用節(jié)點,并開始第一次狀態(tài)和數(shù)據(jù)同步。
復(fù)制
# drbdadm primary mysqlr0 --force
使用下面命令查看同步狀態(tài),你可能看到 DRBD 處于 sync 狀態(tài)。等待 sync 成功,兩節(jié)點都變成 UptoDate 狀態(tài),再進行下一步操作。
復(fù)制
# cat /proc/drbd
或者
復(fù)制
# drbd-overview

在創(chuàng)建的 DRBD 資源上創(chuàng)建文件系統(tǒng)并掛載。在主節(jié)點上執(zhí)行:
復(fù)制
# mkfs.ext3 /dev/drbd1
# mkdir /var/lib/mysql
# mount /dev/drbd1 /var/lib/mysql/
DRBD 配置完成,接下來安裝 MariaDB 服務(wù)器。
安裝 MariaDB 數(shù)據(jù)庫
在主節(jié)點上執(zhí)行如下命令,并初始化 mysql 安裝選項。
復(fù)制
# yum -y install mariadb-server mariadb
# service mariadb start
# /usr/bin/mysql_secure_installation
接著在備用節(jié)點上安裝數(shù)據(jù)庫。首先停止主節(jié)點上相關(guān)服務(wù):
復(fù)制
# systemctl stop mariadb.service
# umount /var/lib/mysql/
# drbdadm secondary mysqlr0
在另一節(jié)點上:
復(fù)制
# drbdadm primary mysqlr0
# mount /dev/drbd1 /var/lib/mysql
# yum install mariadb-server
# service mariadb start
然后在該節(jié)點上登錄數(shù)據(jù)庫,創(chuàng)建 web 應(yīng)用需要的數(shù)據(jù)庫和用戶。
復(fù)制
# mysql -u root -p
MariaDB [(none)]> create database wordpress;
Query OK, 1 row affected (0.04 sec)
MariaDB [(none)]> create user 'wpuser'@'%' identified by 'wppassword';
Query OK, 0 rows affected (0.00 sec)
MariaDB [(none)]> grant all privileges on wordpress.* to 'wpuser'@'%';
Query OK, 0 rows affected (0.00 sec)
MariaDB [(none)]> flush privileges;
Query OK, 0 rows affected (0.00 sec)
MariaDB [(none)]> exit
Bye
配置 Pacemaker + Corosync
在兩個節(jié)點上分別執(zhí)行如下命令。
復(fù)制
# yum install corosync pacemaker pcs
# systemctl start pcsd.service
# systemctl enable pcsd.service
為集群用戶設(shè)置密碼,該用戶將用來在集群節(jié)點間通信,進行數(shù)據(jù)同步。
復(fù)制
# passwd hacluster
該步驟僅需要在某一節(jié)點上執(zhí)行。
復(fù)制
# pcs cluster auth lqi1ecmy01 lqi1ecmy02
創(chuàng)建集群,啟動集群,查看集群狀態(tài)。
復(fù)制
# pcs cluster setup --name mysqlcluster lqi1ecmy01 lqi1ecmy02
# pcs cluster start –all
# pcs status
因為虛擬機沒有真正的 fence 設(shè)備,所以需要禁用 fence 功能。
復(fù)制
# pcs property set stonith-enabled=false
因為兩節(jié)點集群不需要在 vote 功能,所以禁用 quorum。
復(fù)制
# pcs property set no-quorum-policy=ignore
添加集群資源,將 DRBD,文件系統(tǒng)和MariaDB服務(wù)納入集群管理,并設(shè)置彼此之間的依賴關(guān)系。
復(fù)制
# pcs -f drbd_cfg resource create drbd_ha ocf:linbit:drbd drbd_resource=mysqlr0 op monitor interval=60s
# pcs -f drbd_cfg resource master? ms_drbd_ha drbd_ha master-max=1 master-node-max=1 clone-max=2 clone-node-max=1 notify=true
# pcs -f drbd_cfg resource create drbd_fs Filesystem device="/dev/drbd1" directory="/var/lib/mysql" fstype="ext3"
# pcs -f drbd_cfg resource constraint colocation add drbd_fs with ms_drbd_ha INFINITY with-rsc-role=Master
# pcs -f drbd_cfg constraint colocation add drbd_fs with ms_drbd_ha INFINITY with-rsc-role=Master
# pcs -f drbd_cfg constraint order promote ms_drbd_ha then start drbd_fs
# pcs -f drbd_cfg resource create mysql_svc ocf:heartbeat:mysql binary="/usr/bin/mysqld_safe" config="/etc/my.cnf" datadir="/var/lib/mysql" pid="/var/run/mariadb/mariadb.pid" socket="/var/lib/mysql/mysql.sock"? additional_parameters="--bind-address=0.0.0.0" op start timeout=60s op stop timeout=60s op monitor interval=20s timeout=30s
# pcs -f drbd_cfg constraint colocation add mysql_svc with drbd_fs INFINITY
# pcs -f drbd_cfg constraint order drbd_fs then mysql_svc
# pcs cluster cib-push drbd_cfg
配置好之后,查看集群運行狀態(tài)。正常狀態(tài)如下,若有異常,請根據(jù)錯誤信息進行故障排除。日志文件在/var/log/下。
復(fù)制
# pcs status

在兩邊節(jié)點上,執(zhí)行下面命令設(shè)置 Corosync,Pacemaker 開機自啟動。MariaDB 不需要設(shè)置,集群會根據(jù) DRBD 主備關(guān)系自動判斷在哪個節(jié)點啟動該服務(wù)。
復(fù)制
# systemctl enable corosync pacemaker
配置前端 web LB
同樣,我們需要在系統(tǒng)中禁用 Selinux,步驟參考前面配置 MariaDB 部分。在實際生產(chǎn)環(huán)境中,建議開啟,因為 web 服務(wù)器和端口是曝露在公網(wǎng)環(huán)境中的。
此處通過安裝 Nginx + Wordpress 來演示負載均衡。下面步驟需要在兩個節(jié)點上分別執(zhí)行。
安裝 nginx, PHP, mariaDB 客戶端。
首先配置 yum 倉庫。
復(fù)制
# vi /etc/yum.repos.d/nginx.repo
[nginx]
name=nginx repo
baseurl=http://nginx.org/packages/mainline/rhel/7/$basearch/
gpgcheck=0
enabled=1
# yum install mariadb nginx php php-fpm php-mysql
配置 nginx,同樣根據(jù)自己的環(huán)境替換lqi1eha02,wordpress,wpuser,wppassword,10.0.1.10部分內(nèi)容。
復(fù)制
# vi /etc/nginx/conf.d/default.conf
server {
listen 80;
server_name lqi1eha02.chinacloudapp.cn;
access_log /usr/share/nginx/lqi1eha02.chinacloudapp.cn/logs/access.log;
error_log /usr/share/nginx/lqi1eha02.chinacloudapp.cn/logs/error.log;
location / {
root /usr/share/nginx/lqi1eha02.chinacloudapp.cn;
index index.php index.html index.htm;
if (-f $request_filename) {
expires 30d;
break;
}
if (!-e $request_filename) {
rewrite ^(.+)$ /index.php?q=$1 last;
}
}
location ~ .php$ {
fastcgi_pass? localhost:9000;? # port where FastCGI processes were spawned
fastcgi_index? index.php;
fastcgi_param? SCRIPT_FILENAME? /usr/share/nginx/lqi1eha02.chinacloudapp.cn$fastcgi_script_name;? # same path as above
fastcgi_param PATH_INFO? ? ? ? ? ? ? $fastcgi_script_name;
include /etc/nginx/fastcgi_params;
}
}
# vi /etc/php.ini
cgi.fix_pathinfo=0
# mkdir /usr/share/nginx/lqi1eha02.chinacloudapp.cn/
# mkdir /usr/share/nginx/lqi1eha02.chinacloudapp.cn/logs
安裝 wordpress。配置數(shù)據(jù)庫連接信息。兩節(jié)點上分別執(zhí)行。
復(fù)制
# wget http://wordpress.org/latest.tar.gz
# tar zxvf wordpress-4.6.1.tar.gz
# mv wordpress/* /usr/share/nginx/lqi1eha02.chinacloudapp.cn/
# cp /usr/share/nginx/lqi1eha02.chinacloudapp.cn/wp-config-sample.php /usr/share/nginx/lqi1eha02.chinacloudapp.cn/wp-config.php
# vi wp-config.php
// ** MySQL settings - You can get this info from your web host ** //
/** The name of the database for WordPress */
define('DB_NAME', 'wordpress');
/** MySQL database username */
define('DB_USER', 'wpuser');
/** MySQL database password */
define('DB_PASSWORD', 'wppassword');
/** MySQL hostname */
define('DB_HOST', '10.0.1.10');
# chown +R nginx:nginx /usr/share/nginx/lqi1eha02.chinacloudapp.cn/
# chmod +R 777 /usr/share/nginx/lqi1eha02.chinacloudapp.cn/
重啟服務(wù),使配置生效,并設(shè)置開機自啟動。
復(fù)制
# systemctl restart nginx php-fpm
# systemctl enable nginx php-fpm
通過瀏覽器訪問 web 域名,初始化 wordpress。

這樣,一個簡單的 web 環(huán)境就設(shè)置好了。下面進行測試。
故障轉(zhuǎn)移測試
我們模擬每個節(jié)點宕機的情況下,看能否正常使用 wordpress。順序分別為:
mysql slave 宕機
master 宕機
nginx 中任何一個宕機
在每個節(jié)點宕機后,更新一篇帖子,再將服務(wù)集群恢復(fù),看是否能正確更新到數(shù)據(jù)庫,并顯示出來。
數(shù)據(jù)庫備用節(jié)點宕機
備用節(jié)點宕機完全不影響服務(wù)正常使用,但重新啟用備用節(jié)點后,要注意觀察集群服務(wù)是否恢復(fù)正常,如 pcs status, /proc/drbd。
下圖顯示備用節(jié)點宕機。我們更新一篇帖子:This is my second blog…(詳細看最后 wordpress 截圖)

啟動備用節(jié)點后,注意觀察節(jié)點狀態(tài)。

主節(jié)點宕機
如下圖所示,服務(wù)自動切換到備用節(jié)點。我們更新一篇帖子:this is my third blog…

重新啟動故障節(jié)點,注意觀察集群狀態(tài)和 DRBD 同步狀態(tài)。

任一前端 web 宕機
前端 web 采用了負載均衡,因此不論那一臺宕機,服務(wù)會自動全部轉(zhuǎn)移到另一節(jié)點。我們分別在每一條宕機后更新一篇帖子:This is my fourth/fifth blog….
最后,當所有節(jié)點全部啟動,我們來看看是否所有帖子都能顯示,如下圖。
