本文作者,繆睿,來自駐雲信息的雲計算資深數據庫架構師。
以下正文:
· 關於阿里雲的HAVIP
阿里雲官方文檔的介紹:
私網高可用虛擬IP(Private High-Availability Virtual IP Address,簡稱HaVip),是一種可以獨立創建和釋放的私網IP資源。這種私網IP的特殊之處在於,用戶可以在ECS上使用協議進行該IP的宣告。
-
一個HaVip對象可以與最多兩台ECS實例進行綁定;綁定了的實例可以通過ARP方式進行該私網IP的宣告。
-
一台ECS實例可以在持有一個普通私網IP的情況下,可以宣告多個HaVip類型的私網IP,從而同時持有多個私網IP。
-
利用可在ECS進行私網IP宣告的功能,可以 實現基於VRRP協議的高可用方案,包括keepalived、heartbeat等成熟的開源方案。
-
HaVip可以與EIP進行綁定,從而實現HaVip在ECS實例間切換時,發向EIP的消息也被重定向到新的ECS實例上。
-
HaVip僅支持VPC網絡環境。Classic網絡環境下不提供HaVip功能。
文字多了理解起來困難,直接看圖。
在vpc-23c099ge5中有個交換機vsw-23a3275jc的交換機,交換機下有個HAVIP是10.10.1.99,在這個高可用虛擬IP下掛載了兩台ECS,那10.10.1.99 這個IP地址就可以在這兩台ECS上飄來飄去了。
· Keepalived是什么?
keepalived是一個類似於layer3、4、7交換機制的軟件,也就是我們平時說的第3層、第4層和第7層交換。Keepalived的作用是檢測web服務器的狀態,如果有一台web服務器死機,或工作出現故障,Keepalived將檢測到,並將有故障的web服務器從系統中剔除,當web服務器工作正常后Keepalived自動將web服務器加入到服務器群中,這些工作全部自動完成,不需要人工干涉,需要人工做的只是修復故障的web服務器。
但是在這里,keepalived的作用是與HAVIP通信,目的是將HAVIP指向到我們開啟了keepalived服務的那台ECS上。
· 關於阿里雲的Oracle的高可用
有着Oracle背景的DBA們都知道,Oracle的高可用集群是Real Application Cluster(RAC),但是搭建RAC集群需要幾個硬性條網絡通訊模式得是廣播
-
網絡通訊模式得是廣播
-
必須有兩個網絡分別用於心跳鏈路與公網服務
-
共享存儲 (可以使用NFS掛載來解決)
這網絡廣播模式在阿里雲上就無法跳過,更不用說VPC環境下只能有一個網卡地址,只能考慮使用其他的方案來解決OracleDB的高可用環境。
有過阿里雲RDS經驗的同學都知道,RDS的高可用是通過主備庫的服務切換來實現的,當主庫損壞的情況下,備庫會在很短時間內接管服務,其代價就是在切換過程中session會斷開造成短時間的數據庫服務中斷,大概在30秒左右。而我們在阿里雲上實現Oracle高可用也是類似這種方式實現。
言歸正傳,接下來我們說說如何在阿里雲上部署這套高可用方案。
傳統方式下的Dataguard架構如下圖:
一般是由有兩台ECS,IP地址分別為10.10.1.2,與10.10.1.3,這兩台ECS上部署着一套Oracle PRIMARY-STANDBY環境,這套Dataguard方案使用Oracle dgbroker管理,當PRIMARY庫崩潰的時候,Standby會主動的接管服務,但是這里大家都知道,Oracle database的訪問是需要通過listener的,我們兩台ECS默認的IP地址是不同的,這樣當standby接管服務后,application的數據庫連接池要把IP改為10.10.1.3才能再次連接數據庫服務,大家都知道,連接池地址的改動是要重啟容器,如果application都需要重啟,就完全不能稱做高可用了,很慶幸,阿里雲提供了一個叫做havip的服務。
我們來看看下面這幅圖
這里我們在ECS原IP的基礎上,加入了HAVIP的概念,application 通過10.10.1.99這個IP地址訪問數據庫服務,當PRIMARY與STANDBY角色互換之后。
application依然還是通過10.10.1.99訪問數據庫服務,只是這個IP地址已經漂移到我們曾經的standbyDB了。大家都知道Oracle的RAC環境是必須共享存儲的,也就是說當物理文件損壞的時候,整個數據庫服務依然還是會崩潰。上面這套HAVIP+Dataguard的方案既實現了數據庫物理層面的災備,同時可以實現數據庫服務停止后的快速接管。
以上就是這套方案的框架圖,說起來很簡單,但是實現起來就麻煩了,主要兩個難點:
-
如果ECS服務不終止,數據庫角色做切換,havip如何漂移?
-
如果ECS服務強制停止了,Havip如何漂移到備用環境?
要解決這兩個問題,我們就要用到我們的keepalived了,具體的實現思路,我們來看看。
· 實現思路
1:首先我們先創建一套Dataguard環境,為了保證切換后連接池無需改動,兩台ECS上的DB的sid必須一致。
2: oracle的dataguard 通過DGbroker管理,當primary db崩潰physical standby db自動切換為primary;這里必須把observer啟動在STANDBY上面,我們試過在管理控制台上強制關閉ecs,如果observer所在的ECS被強制關閉,dgbroker無法做主備切換。
3: 接下來,將這兩台ECS加載到HAVIP服務的集群掛載進集群的時候,可以看到兩台ECS都是虛線連接,而且都是(備),這里,我們就要開始部署keepalived服務了。
4:通過keepalived做一個master->backup的配置集群啟動,這里貼出兩份配置文件這里master (10.10.1.2) backup(10.10.1.3)
master配置文件
keepalived.conf
! Configuration File for keepalived global_defs { router_id LVS_DEVEL #集群的ID 主備兩台機器的這名字得一樣 } #檢查腳本,keepalived會定時的執行shell做檢查 vrrp_script chk_http_port { script "/etc/keepalived/mcheckdb.sh" interval 2 weight 2 } vrrp_instance VI_1 { state MASTER interface eth0 virtual_router_id 51 priority 100 advert_int 1 authentication { auth_type PASS auth_pass 1111 } track_script { chk_http_port } virtual_ipaddress { 10.10.1.99 dev eth0 label eth0:havip #havip } unicast_src_ip 10.10.1.2 #本地IP unicast_peer { 10.10.1.3 #備機IP } } |
Backup 配置文件
keepalived.conf
! Configuration File for keepalived global_defs { router_id LVS_DEVEL } vrrp_script chk_http_port { script "/etc/keepalived/scheckdb.sh" interval 2 weight 2 } vrrp_instance VI_1 { state BACKUP interface eth0 virtual_router_id 51 priority 99 advert_int 1 authentication { auth_type PASS auth_pass 1111 } track_script { chk_http_port } virtual_ipaddress { 10.10.1.99 dev eth0 label eth0:havip } unicast_src_ip 10.10.1.3 unicast_peer { 10.10.1.2 } } |
這里我們假設兩個場景,keepalived啟動后。
1、10.10.1.2使用了master(primary)配置文件,10.10.1.3使用了backup(standby)配置文件。當primary db與standby db互換了角色,而這時候havip依然是與master也就是10.10.1.2這台綁定。
2、10.10.1.2使用了master(primary)配置文件,10.10.1.3使用了backup(standby)配置文件。我們強制關閉了10.10.1.2這台ECS,這時候havip漂移到了backup機器上,standby db也變成了primary角色,當我們再次啟動10.10.1.2這台ECS后,havip又會飄回master配置文件所在的ECS,這時候數據庫服務又無法通過havip訪問了。
這里該如何去解決這個問題呢?面對上面的兩個場景,我們取了個巧。
注意配置文件中的這兩段
這里shell都會定時的在ECS上執行用於檢查環境配置。那么既然可以寫邏輯,還有什么不能實現?
說到這,大家是不是很想看看shell的代碼~
首先我們看看master的檢查邏輯
mcheckdb.sh
#!/bin/bash max_sn="PRIMARY" su - oracle -c "sh /etc/keepalived/oracle/dbrole.sh" max_sn=`cat /etc/keepalived/oracle/dbrole` if [ "$max_sn" != "PRIMARY" ] then cat /etc/keepalived/samples/backup.keepalived.conf > /etc/keepalived/keepalived.conf /etc/init.d/keepalived restart echo `date` > /etc/keepalived/date fi; |
很簡單的邏輯,切換到oracle用戶執行一個dbrole.sh,這個shell會執行Oracle db的角色查詢,然后把結果寫在/etc/keepalived/oracle/dbrole這個文件中。如果結果不是’PRIMARY’就把/etc/keepalived/samples/backup.keepalived.conf 文件內容替換掉當前keepalived進程使用的配置文件,然后再重啟keepalived 服務。到這兒,大家應該知道如何做了吧。
scheckdb.sh
#!/bin/bash max_sn="PHYSICAL STANDBY" su - oracle -c "sh /etc/keepalived/oracle/dbrole.sh" max_sn=`cat /etc/keepalived/oracle/dbrole` if [ "$max_sn" = "PRIMARY" ] then cat /etc/keepalived/samples/master.keepalived.conf > /etc/keepalived/keepalived.conf /etc/init.d/keepalived restart #echo "stop keepalived" #打開監聽 #su - oracle -c " lsnrctl start listener2" fi; |
scheckdb.sh的內容大同小異樣,不過多了一步,打開監聽listener2,這listener2,就是開啟HAVIP的監聽地址。
我們可以在兩台ECS上都准備好master與backup 兩份配置文件,這樣不但解決了上面兩個場景的問題,還直接讓havip可以根據數據庫的角色做漂移,保證在dataguard可用的前提下,時刻漂移在我們的primary database。
最后,給大家提供一些代碼與一個小工具。
Keepalived 的各種配置文件:
下載地址:http://jiagouyun-cn.oss-cn-hangzhou.aliyuncs.com/oracle/keepalived/keepalived.zip
解壓后把整個keepallived 目錄直接放到/etc下,注意其中有個oracle目錄,包括其中的文件必須改成oracle用戶的權限。
再提供提供一個配置DG的shell工具,大家沒事可以用用,腳本有針對性,僅用於學習不建議配置生產環境時使用。
下載地址:http://jiagouyun-cn.oss-cn-hangzhou.aliyuncs.com/oracle/dataguard.1.3.zip