天天看點

Haproxy&Keepalived實作高可用

一、haproxy 編譯安裝,并簡述全局配置段各參數作用

編譯安裝

  • 腳本安裝
#!/bin/bash
 
 # 編譯安裝HAProxy
 
  
 
 . /etc/init.d/functions
 
 #HAproxy版本
 
 HAProxy_version=haproxy-2.6.1
 
 TAR=tar.gz
 
 HAProxy=${HAProxy_version}.${TAR}
 
  
 
 #HAProxy源碼下載下傳位址
 
 HAProxy_url=http://www.haproxy.org/download/2.6/src/haproxy-2.6.1.tar.gz
 
 # haproxy安裝路徑
 
 HAProxy_install_DIR=/apps/haproxy
 
  
 
 #lua版本
 
 Lua_version=lua-5.3.5
 
 TAR_lua=tar.gz
 
 Lua=${Lua_version}.${TAR_lua}
 
 #lua源碼下載下傳位址
 
 Lua_url=http://www.lua.org/ftp/${Lua}
 
  
 
  
 
 # CPU數量
 
 CPUS=`lscpu|grep "^CPU(s)"|awk '{print $2}'`
 
 # 系統類型
 
 os_type=`grep "^NAME" /etc/os-release |awk -F'"| ' '{print $2}'`
 
 # 系統版本号
 
 os_version=`awk -F'"' '/^VERSION_ID/{print $2}' /etc/os-release`
 
  
 
 color () {
 
 if [[ $2 -eq 0 ]];then
 
     echo -e "\e[1;32m$1\t\t\t\t\t\t[  OK  ]\e[0;m"
 
 else
 
     echo $2
 
     echo -e "\e[1;31m$1\t\t\t\t\t\t[ FAILED ]\e[0;m"
 
 fi
 
 }
 
  
 
 download_lua (){
 
 cd /opt
 
 if [ -e ${Lua} ];then
 
  color "lua安裝包已存在" 0
 
 else
 
  color "開始下載下傳lua安裝包" 0
 
  wget ${Lua_url}
 
  if [ $? -ne 0 ];then
 
    color "下載下傳lua安裝包失敗,退出!" 1
 
    exit 1
 
  fi
 
  
 
 fi
 
 }
 
  
 
 download_haproxy (){
 
 cd /opt
 
 if [ -e ${HAProxy} ];then
 
  color "haproxy安裝包已存在" 0
 
 else
 
  color "開始下載下傳haproxy安裝包" 0
 
  wget ${HAProxy_url}
 
  if [ $? -ne 0 ];then
 
    color "下載下傳haproxy安裝包失敗,退出!" 1
 
    exit 1
 
  fi
 
 fi
 
 }
 
  
 
 update_lua (){
 
 # 安裝依賴包
 
 yum -y install gcc readline-devel
 
  
 
 # 解壓源碼包
 
 tar -xvf /opt/${Lua} -C /usr/local/src
 
 ln -s /usr/local/src/${Lua_version} /usr/local/src/lua
 
  
 
 # 編譯安裝
 
 cd /usr/local/src/lua
 
 make linux test
 
 }
 
  
 
 install_haproxy (){
 
 # 安裝依賴包
 
 yum -y install gcc openssl-devel pcre-devel systemd-devel
 
  
 
 # 解壓源碼包
 
 tar xvf /opt/${HAProxy} -C /usr/local/src
 
 ln -s /usr/local/src/${HAProxy_version} /usr/local/src/haproxy
 
  
 
 # 編譯安裝
 
 cd /usr/local/src/haproxy
 
 make ARCH=x86_64 TARGET=linux-glibc USE_PCRE=1 USE_OPENSSL=1 USE_ZLIB=1 \
 
 USE_SYSTEMD=1 USE_LUA=1 LUA_INC=/usr/local/src/lua/src/ LUA_LIB=/usr/local/src/lua/src/
 
 make install PREFIX=${HAProxy_install_DIR}
 
 ln -s ${HAProxy_install_DIR}/sbin/haproxy /usr/sbin/
 
  
 
 # 準備服務啟動配置檔案
 
 ## 添加使用者
 
 useradd -r -s /sbin/nologin -d /var/lib/haproxy haproxy
 
 mkdir -p /etc/haproxy
 
 mkdir -p /var/lib/haproxy
 
 ## 準備service服務
 
 cat > /usr/lib/systemd/system/haproxy.service <<EOF
 
 [Unit]
 
 Description=HAProxy Load Balancer
 
 After=syslog.target network.target
 
  
 
 [Service]
 
 ExecStartPre=/usr/sbin/haproxy -f /etc/haproxy/haproxy.cfg -c -q
 
 ExecStart=/usr/sbin/haproxy -Ws -f /etc/haproxy/haproxy.cfg -p /var/lib/haproxy/haproxy.pid
 
 ExecReload=/bin/kill -USR2 $MAINPID
 
 LimitNOFILE=100000
 
  
 
 [Install]
 
 WantedBy=multi-user.target
 
 EOF
 
  
 
 ###準備haproxy配置檔案
 
 cat > /etc/haproxy/haproxy.cfg <<EOF
 
 global
 
  maxconn 100000
 
  chroot ${HAProxy_install_DIR}
 
  stats socket /var/lib/haproxy/haproxy.sock mode 600 level admin
 
  #uid 99
 
  #gid 99
 
  user haproxy
 
  group haproxy
 
  daemon
 
  #nbproc 4
 
  #cpu-map 1 0
 
  #cpu-map 2 1
 
  #cpu-map 3 2
 
  #cpu-map 4 3
 
  pidfile /var/lib/haproxy/haproxy.pid
 
  log 127.0.0.1 local2 info
 
  
 
 defaults
 
  option http-keep-alive
 
  option forwardfor
 
  maxconn 100000
 
  mode http
 
  timeout connect 300000ms
 
  timeout client 300000ms
 
  timeout server 300000ms
 
  
 
 listen stats
 
  mode http
 
  bind 0.0.0.0:9999
 
  stats enable
 
  log global
 
  stats uri /haproxy-status
 
  stats auth  haadmin:123456
 
  
 
 listen web_port
 
  bind 0.0.0.0:80
 
  mode http
 
  log global
 
  server web1 127.0.0.1:8080 check inter 3000 fall 2 rise 5
 
 EOF
 
  
 
 systemctl daemon-reload
 
 systemctl enable --now haproxy
 
 systemctl is-active haproxy
 
  
 
 if [ $? -ne 0 ];then
 
  color "haproxy服務啟動失敗!" 1
 
  exit 1
 
 else
 
  color "haproxy服務啟動成功" 0
 
 fi
 
 }
 
  
 
 download_lua
 
  
 
 download_haproxy
 
  
 
 update_lua
 
  
 
 install_haproxy
 
  
 
 exit 0      
  • 檢視狀态

說明:haproxy加載子配置檔案方法

haproxy本身是不支援在haproxy.cfg中通過include方式添加子配置檔案的,可通過在service中添加目錄方式加載子配置檔案,示例如下:

# cat /lib/systemd/system/haproxy.service 
 
 [Unit]
 
 Descriptinotallow=HAProxy Load Balancer
 
 After=syslog.target network.target
 
  
 
 [Service]
 
 #下面兩行添加子配置檔案路徑/etc/haproxy/conf.d/
 
 ExecStartPre=/usr/sbin/haproxy -f /etc/haproxy/haproxy.cfg -f /etc/haproxy/conf.d/ -c -q
 
 ExecStart=/usr/sbin/haproxy -Ws -f /etc/haproxy/haproxy.cfg -f /etc/haproxy/conf.d/ -p /var/lib/haproxy/haproxy.pid
 
 ExecReload=/bin/kill -USR2 $MAINPID
 
 LimitNOFILE=100000
 
  
 
 [Install]
 
 WantedBy=multi-user.target      

global全局配置參數

chroot  #鎖定運作目錄
 
 deamon #以守護程序運作
 
 stats socket /var/ lib/haproxy/haproxy.sock mode 600 leveladmin  #socket檔案
 
 user, group,uid, gid #運作haproxy的使用者身份
 
 nbproc 1 #開啟的haproxy程序數,與CPU保持一緻
 
 nbthread 1 #指定每個haproxy程序開啟的線程數,預設為每個程序一個線程
 
 cpu-map 1 0  #綁定haproxy worker程序至指定CPU,将第1個work程序綁定至0号CPU,單程序多線程和多程序單線程不能并存。
 
 maxconn    #每個haproxy程序的最大并發連接配接數
 
 maxsslconn #每個haproxy程序ssl最大連接配接數,用于haproxy配置了證書的場景下
 
 maxconnrate  #每個程序每秒建立的最大連接配接數量
 
 spread-checks  #後端server狀态check随機提前或延遲百分比時間,建議2-5(20%-50%)之間
 
 pidfile    #指定pid檔案路徑
 
 log 127.0.0.1 local3 info  #定義全局的syslog伺服器;最多可以定義兩個      

proxies代理配置

defaults [<name>] #預設配置項,針對以下的frontend、backend和listen生效,可以多個name也可以沒有name
 
 frontend <name>  #前端servername,類似于Nginx的一個虛拟主機 server和LVS服務叢集。
 
 backend  <name>  #後端伺服器組,等于nginx的upstream和LVS中的RS伺服器
 
 listen <name>  #将frontend和backend合并在一起配置,相對于frontend和backend配置更簡潔,生産常用      

注意:name字段隻能使用大小寫字母,數字,‘-’,‘_’,‘.’和 ‘:’,并且嚴格區分大小寫。

  • defaults配置參數
option redispatch #當server Id對應的伺服器挂掉後,強制定向到其他健康的伺服器,重新派發
 
 option abortonclose  #當伺服器負載很高時,自動結束掉目前隊列處理比較久的連接配接,針對業務情況選擇開啟
 
 option http-keep-alive #開啟與用戶端的會話保持
 
 option forwardfor  #透傳用戶端真實IP至後端web伺服器
 
 mode http|tcp  #設定預設工作類型,使用TCP伺服器性能更好,減少壓力
 
 timeout http-keep-alive 120s #session 會話保持逾時時間,此時間段内會轉發到相同的後端伺服器
 
 timeout connect 120s #用戶端請求從haproxy到後端server最長連接配接等待時間(TCP連接配接之前),預設機關ms
 
 timeout server 600s #用戶端請求從haproxy到後端服務端的請求處理逾時時長(TCP連接配接之後),預設機關ms,
 
        #如果逾時,會出現502錯誤,此值建議設定較大些,訪止502錯誤
 
 timeout client 600s #設定haproxy與用戶端的最長非活動時間,預設機關ms,建議和timeout server相同
 
 timeout check   5s #對後端伺服器的預設檢測逾時時間
 
 default-server inter 1000 weight 3 #指定後端伺服器的預設設定      
  • listen配置參數

    範例

listen WEB_PORT_80 
 
    bind 10.0.0.7:80  
 
    mode http
 
    option forwardfor
 
    server web1   10.0.0.17:8080   check inter 3000 fall 3 rise 5
 
    server web2   10.0.0.27:8080   check inter 3000 fall 3 rise 5      
  • bind
#監聽http的多個IP的多個端口和sock檔案
 
 listen http_proxy 
 
     #指定HAProxy的監聽位址,可以是IPV4或IPV6,可以同時監聽多個IP或端口,可同時用于listen字段中
 
     bind :80,:443,:8801-8810
 
     #注意:如果需要綁定在非本機的IP,需要開啟核心參數:net.ipv4.ip_nonlocal_bind=1
 
     bind 10.0.0.1:10080,10.0.0.1:10443
 
     bind /var/run/ssl-frontend.sock user root mode 600 accept-proxy
 
   
 
 #https監聽
 
 listen http_https_proxy
 
     bind :80
 
     #公鑰和私鑰公共檔案
 
     bind :443 ssl crt /etc/haproxy/site.pem 
 
  
 
 #監聽ipv6、ipv4和unix sock檔案
 
 listen http_https_proxy_explicit
 
    bind ipv6@:80
 
    bind ipv4@public_ssl:443 ssl crt /etc/haproxy/site.pem
 
    bind [email protected] user root mode 600 accept-proxy
 
  
 
 #監聽file descriptor
 
 listen external_bind_app1
 
    bind "fd@${FD_APP1}"      
  • mode
mode http|tcp #指定負載協定類型      
  • option

配置選項,option後面加 httpchk,smtpchk,mysql-check,pgsql-check,ssl-hello-chk方法,可用于實作更多應用層檢測功能。

  • server

定義後端real server

check #對指定real進行健康狀态檢查.如果不加此設定,預設不開啟檢查,隻有check後面沒有其它配置也可以啟用檢查功能
 
       #預設對相應的後端伺服器IP和端口,利用TCP連接配接進行周期性健康性檢查,注意必須指定端口才能實作健康性檢查
 
     addr <IP>  #可指定的健康狀态監測IP,可以是專門的資料網段,減少業務網絡的流量
 
     port <num> #指定的健康狀态監測端口
 
     inter <num>  #健康狀态檢查間隔時間,預設2000 ms
 
     fall <num> #後端伺服器從線上轉為線下的檢查的連續失效次數,預設為3
 
     rise <num> #後端伺服器從下線恢複上線的檢查的連續有效次數,預設為2
 
 weight <weight>  #預設為1,最大值為256,0(狀态為藍色)表示不參與負載均衡,但仍接受持久連接配接
 
 backup #将後端伺服器标記為備份狀态,隻在所有非備份主機down機時提供服務,類似Sorry Server
 
 disabled #将後端伺服器标記為不可用狀态,即維護狀态,除了持久模式,将不再接受連接配接,狀态為深黃色,
 
    #優雅下線,不再接受新使用者的請求
 
 redirect prefix http://www.baidu.com/  #将請求臨時(302)重定向至其它URL,隻适用于http模式
 
 redir http://www.baidu.com #将請求臨時(302)重定向至其它URL,隻适用于http模式
 
 maxconn <maxconn>  #目前後端server的最大并發連接配接數      

二、使用haproxy作為代理伺服器,後端兩台nginx來提供web服務進行測試。

架構

haproxy

10.0.0.7

web1

10.0.0.17

web2

10.0.0.27

client

  1. 配置haproxy(10.0.0.7)
  • 修改haproxy.cfg配置檔案
[root@haproxy haproxy]# vim /etc/haproxy/haproxy.cfg 
 
 ......
 
 listen web_port
 
     bind 0.0.0.0:80
 
     mode http
 
     log global
 
     server web1 10.0.0.17:80 check inter 3s fall 3 rise 5
 
     server web2 10.0.0.27:80 check inter 3s fall 3 rise 5      
  • 重新開機服務

​systemctl restart haproxy​

  1. 配置web1(10.0.0.17)
  • 安裝nginx

​yum install nginx -y​

  • 準備網頁
echo "web1 `hostname -I`" > /usr/share/nginx/html/index.html      
  • 啟動服務

​systemctl start nginx​

  1. 配置web2(10.0.0.27)
  • 安裝nginx

​yum install nginx -y​

  • 準備網頁
echo "web2 `hostname -I`" > /usr/share/nginx/html/index.html      
  • 啟動服務

​systemctl start nginx​

  1. 驗證
Haproxy&amp;Keepalived實作高可用
Haproxy&amp;Keepalived實作高可用

三、簡述haproxy排程算法,并搭建監控頁面。

haproxy排程算法

1. 靜态算法

按照事先定義好的規則輪詢公平排程,不關心後端伺服器的目前負載、連接配接數和響應速度等,且無法實時修改權重(隻能為0和1,不支援其它值),隻能靠重新開機HAProxy生效。

  1. static-rr

    基于權重的輪詢排程,不支援運作時利用socat進行權重的動态調整(隻支援0和1,不支援其他值)及後端伺服器慢啟動,其後端主機數量沒有限制,相當于LVS中的wrr。

    配置示例

listen web_host
 
  bind 10.0.0.7:80,:8801-8810,10.0.0.7:9001-9010
 
  mode http
 
  log global
 
  balance static-rr
 
  server web1 10.0.0.17:80 weight 1 check inter 3000 fall 2 rise 5
 
  server web2 10.0.0.27:80 weight 2 check inter 3000 fall 2 rise 5      
  1. first

    根據伺服器在清單中的位置,自上而下進行排程,但是其隻會當第一台伺服器的連接配接數達到上限,新請求才會配置設定給下一台服務,是以會忽略伺服器的權重設定,此方式使用較少。

    不支援使用socat進行動态修改權重,可以設定0和1,可以設定其他值但無效

    配置示例

listen web_host
 
  bind 10.0.0.7:80,:8801-8810,10.0.0.7:9001-9010
 
  mode http
 
  log global
 
  balance first
 
  server web1 10.0.0.17:80 maxconn 2 weight 1 check inter 3000 fall 2 rise 5
 
  server web2 10.0.0.27:80 weight 1 check inter 3000 fall 2 rise 5      

2. 動态算法

基于後端伺服器狀态進行排程适當調整,新請求将優先排程至目前負載較低的伺服器,且權重可以在haproxy運作時動态調整無需重新開機。

  1. roundronbin

    基于權重的輪詢動态排程算法,支援權重的運作時調整,不同于lvs中的rr輪詢模式,HAProxy中的roundrobin支援慢啟動(新加的伺服器會逐漸增加轉發數),其每個後端backend中對多支援4095個real server,支援對real server權重動态調整,roundrobin為預設排程算法,此算法使用廣泛。

    配置示例

listen web_host
 
  bind 10.0.0.7:80,:8801-8810,10.0.0.7:9001-9010
 
  mode http
 
  log global
 
  balance roundrobin
 
  server web1 10.0.0.17:80 weight 1 check inter 3000 fall 2 rise 5
 
  server web2 10.0.0.27:80 weight 2 check inter 3000 fall 2 rise 5      

支援動态調整權重

# echo "get weight web_host/web1" | socat stdio /var/lib/haproxy/haproxy.sock 
 
 1 (initial 1)
 
  
 
 # echo "set weight web_host/web1 3" | socat stdio /var/lib/haproxy/haproxy.sock 
 
  
 
 # echo "get weight web_host/web1" | socat stdio /var/lib/haproxy/haproxy.sock 
 
 3 (initial 1)      
  1. leastconn

    權重的最少連接配接的動态,支援權重的運作時調整和慢啟動,即:根據目前連接配接最少的後端伺服器而非權重進行優先排程(新用戶端連接配接),比較适合長連接配接的場景使用,比如:MySQL等場景。

    配置示例

listen web_host
 
  bind 10.0.0.7:80,:8801-8810,10.0.0.7:9001-9010
 
  mode http
 
  log global
 
  balance leastconn
 
  server web1 10.0.0.17:80 weight 1 check inter 3000 fall 2 rise 5
 
  server web2 10.0.0.27:80 weight 1 check inter 3000 fall 2 rise 5      
  1. random

    在1.9版本開始增加 random的負載平衡算法,其基于随機數作為一緻性hash的key,随機負載平衡對于大型伺服器場或經常添加或删除伺服器非常有用,支援weight的動态調整,weight較大的主機有更大機率擷取新請求。

    配置示例

listen web_host
 
  bind 10.0.0.7:80,:8801-8810,10.0.0.7:9001-9010
 
  mode http
 
  log global
 
  balance random
 
  server web1 10.0.0.17:80 weight 1 check inter 3000 fall 2 rise 5
 
  server web2 10.0.0.27:80 weight 1 check inter 3000 fall 2 rise 5      

3. 其他算法

即可作為靜态算法,又可以通過選項成為動态算法

1)souce

源位址hash,基于使用者源位址hash并将請求轉發到後端伺服器,後續同一個源位址請求将被轉發至同一個後端web伺服器。此方式當後端伺服器資料量發生變化時,會導緻很多使用者的請求轉發至新的後端伺服器,預設為靜态方式,但是可以通過hash-type支援的選項更改。

這個算法一般是在不插入Cookie的TCP模式下使用,也可給拒絕會話cookie的客戶提供最好的會話粘性,适用于session會話保持但不支援cookie和緩存的場景。

源位址有兩種轉發用戶端請求到後端伺服器的伺服器選取計算方式,分别是取模法和一緻性hash。

  1. map-based取模法

    取模法,對source即源位址進行hash計算,再基于伺服器總權重的取模,最終結果決定将此請求轉發至對應的後端伺服器。此方法是靜态的,即不支援線上調整權重,不支援慢啟動,可實作對後端伺服器均衡排程。缺點是當伺服器的總權重發生變化時,即有伺服器上線或下線,都會因總權重發生變化而導緻排程結果整體改變,hash-type 指定的預設值為此算法

map-based算法:基于權重取模,hash(source_ip)%所有後端伺服器相加的總權重      

配置示例

listen web_host
 
  bind 10.0.0.7:80,:8801-8810,10.0.0.7:9001-9010
 
  mode tcp
 
  log global
 
  balance source
 
  hash-type map-based 
 
  server web1  10.0.0.17:80 weight 1 check inter 3000 fall 2 rise 3
 
  server web2  10.0.0.27:80 weight 1 check inter 3000 fall 2 rise 3
 
   
 
 #不支援動态調整權重值
 
 [root@haproxy ~]#echo "set weight web_host/10.0.0.27 10" | socat stdio /var/lib/haproxy/haproxy.sock 
 
 Backend is using a static LB algorithm and only accepts weights '0%' and '100%'. 
 
  
 
 #隻能動态上線和下線
 
 [root@haproxy ~]#echo "set weight web_host/10.0.0.27 0" | socat stdio /var/lib/haproxy/haproxy.sock 
 
 [root@haproxy conf.d]#echo "get weight web_host/10.0.0.27" | socat stdio /var/lib/haproxy/haproxy.sock 
 
 0 (initial 1)      
  1. 一緻性hash

    一緻性哈希,當伺服器的總權重發生變化時,對排程結果影響是局部的,不會引起大的變動,hash(o)mod n ,該hash算法是動态的,支援使用 socat等工具進行線上權重調整,支援慢啟動。

    算法:

1、key1=hash(source_ip)%(2^32) [0---4294967295]
 
 2、keyA=hash(後端伺服器虛拟ip)%(2^32)
 
 3、将key1和keyA都放在hash環上,将使用者請求排程到離key1最近的keyA對應的後端伺服器      

hash環偏斜問題

增加虛拟伺服器IP數量,比如:一個後端伺服器根據權重為1生成1000個虛拟IP,再hash。而後端伺服器權重為2則生成2000的虛拟IP,再bash,
 
 最終在hash環上生成3000個節點,進而解決hash環偏斜問題。      

配置示例

listen web_host
 
  bind 10.0.0.7:80,:8801-8810,10.0.0.7:9001-9010
 
  mode tcp
 
  log global
 
  balance source
 
  hash-type consistent
 
  server web1 10.0.0.17:80 weight 1 check inter 3000 fall 2 rise 5
 
  server web2 10.0.0.27:80 weight 1 check inter 3000 fall 2 rise 5      
2)uri

基于對使用者請求的URI的左半部分或整個uri做hash,再将hash結果對總權重進行取模後,根據最終結果将請求轉發到後端指定伺服器,适用于後端是緩存伺服器場景,預設是靜态算法,也可以通過hash-type指定map-based和consistent,來定義使用取模法還是一緻性hash。

注意:此算法基于應用層,是以隻支援 mode http ,不支援 mode tcp

<scheme>://<user>:<password>@<host>:<port>/<path>;<params>?<query>#<frag>
 
 左半部分:/<path>;<params>
 
 整個uri:/<path>;<params>?<query>#<frag>      
Haproxy&amp;Keepalived實作高可用

uri取模法配置示例

listen web_host
 
  bind 10.0.0.7:80,:8801-8810,10.0.0.7:9001-9010
 
  mode http
 
  log global
 
  balance uri
 
  server web1 10.0.0.17:80 weight 1 check inter 3000 fall 2 rise 5
 
  server web2 10.0.0.27:80 weight 1 check inter 3000 fall 2 rise 5      

uri 一緻性hash配置示例

listen web_host
 
  bind 10.0.0.7:80,:8801-8810,10.0.0.7:9001-9010
 
  mode http
 
  log global
 
  balance uri
 
  hash-type consistent
 
  server web1 10.0.0.17:80 weight 1 check inter 3000 fall 2 rise 5
 
  server web2 10.0.0.27:80 weight 1 check inter 3000 fall 2 rise 5      
3)url_param

url_param對使用者請求的url中的 params 部分中的一個參數key對應的value值作hash計算,并由伺服器總權重相除以後派發至某挑出的伺服器;通常用于追蹤使用者,以確定來自同一個使用者的請求始終發往同一個real server,如果無沒key,将按roundrobin算法。

# 假設:
 
 url = http://www.magedu.com/foo/bar/index.php?key=value
 
  
 
 # 則:
 
 host = "www.magedu.com"
 
 url_param = "key=value"      

取模法配置示例

listen web_host
 
  bind 10.0.0.7:80,:8801-8810,10.0.0.7:9001-9010
 
  mode http
 
  log global
 
  balance url_param userid    #url_param hash
 
  server web1 10.0.0.17:80 weight 1 check inter 3000 fall 2 rise 5
 
  server web2 10.0.0.27:80 weight 1 check inter 3000 fall 2 rise 5      

一緻性hash配置示例

listen web_host
 
  bind 10.0.0.7:80,:8801-8810,10.0.0.7:9001-9010
 
  mode http
 
  log global
 
  balance url_param userid    #對url_param的值取hash
 
  hash-type consistent
 
  server web1 10.0.0.17:80 weight 1 check inter 3000 fall 2 rise 5
 
  server web2 10.0.0.27:80 weight 1 check inter 3000 fall 2 rise 5      
4)hdr

針對使用者每個http頭部(header)請求中的指定資訊做hash,此處由name指定的http首部将會被取出并做hash計算,然後由伺服器總權重取模以後派發至某挑出的伺服器,如果無有效值,則會使用預設的輪詢排程。

取模法配置示例

listen web_host
 
  bind 10.0.0.7:80,:8801-8810,10.0.0.7:9001-9010
 
  mode http
 
  log global
 
  balance hdr(User-Agent)
 
  #balance hdr(host)
 
    
 
  server web1 10.0.0.17:80 weight 1 check inter 3000 fall 2 rise 5
 
  server web2 10.0.0.27:80 weight 1 check inter 3000 fall 2 rise 5      

一緻性hash配置示例

listen web_host
 
  bind 10.0.0.7:80,:8801-8810,10.0.0.7:9001-9010
 
  mode http
 
  log global
 
  balance hdr(User-Agent)
 
  hash-type consistent
 
  server web1 10.0.0.17:80 weight 1 check inter 3000 fall 2 rise 5
 
  server web2 10.0.0.27:80 weight 1 check inter 3000 fall 2 rise 5      
5)rdp-cookie

rdp-cookie對遠windows遠端桌面的負載,使用cookie保持會話,預設是靜态,也可以通過hash-type指定map-based和consistent,來定義使用取模法還是一緻性hash。

取模法配置示例

listen RDP
 
  bind 10.0.0.7:3389
 
  balance rdp-cookie
 
  mode tcp
 
  server rdp0 10.0.0.17:3389 check fall 3 rise 5 inter 2000 weight 1      

一緻性hash配置示例

listen magedu_RDP_3389
 
  bind  172.16.0.100:3389
 
  balance rdp-cookie
 
  hash-type consistent
 
  mode tcp
 
  server rdp0 10.0.0.200:3389 check fall 3 rise 5 inter 2000 weight 1      

注意:基于iptables實作RDP協定轉發,必須開啟ip轉發功能: net.ipv4.ip_forward = 1。

4. 算法總結

#靜态
 
 static-rr--------->tcp/http  
 
 first------------->tcp/http
 
  
 
 #動态
 
 roundrobin-------->tcp/http
 
 leastconn--------->tcp/http
 
 random------------>tcp/http
 
  
 
 #以下靜态和動态取決于hash_type是否consistent
 
 source------------>tcp/http
 
 Uri--------------->http
 
 url_param--------->http     
 
 hdr--------------->http
 
 rdp-cookie-------->tcp      

5. 适用場景

static-rr     #做session共享的web叢集
 
 first        #使用較少
 
  
 
 roundrobin     #預設排程算法
 
 leastconn      #資料庫
 
 random       #對于大型伺服器場或經常添加或删除伺服器非常有用
 
  
 
 source       #基于用戶端公網IP的會話保持
 
  
 
 Uri        #緩存伺服器,CDN服務商,藍汛、百度、阿裡雲、騰訊
 
 url_param      #可以實作session保持
 
  
 
 hdr        #基于用戶端請求封包頭部做下一步處理
 
 rdp-cookie     #基于Windows主機,很少使用      

搭建監控頁面

  1. 修改haproxy配置檔案
[root@haproxy haproxy]# vim /etc/haproxy/haproxy.cfg 
 
 .....
 
 #添加如下status資訊
 
 listen stats
 
  mode http
 
  bind 0.0.0.0:9999
 
  stats enable
 
  log global
 
  stats uri /haproxy-status
 
  stats auth  haadmin:123456      
  1. 通路http://10.0.0.7:9999/haproxy-status監控網頁

使用者名:haadmin,密碼:123456

Haproxy&amp;Keepalived實作高可用
  1. 進入監控首頁
Haproxy&amp;Keepalived實作高可用

四、基于haproxy,實作網頁動靜分離。

架構

haproxy

10.0.0.7

static-web

10.0.0.17

dynamic-web

10.0.0.27

client

  1. 配置haproxy(10.0.0.7)
  • 修改haproxy配置
[root@haproxy haproxy]# cat /etc/haproxy/haproxy.cfg 
 
 .....
 
 #添加如下内容
 
 frontend http_port
 
     bind 10.0.0.7:80
 
     mode http
 
     log global
 
     balance roundrobin
 
     option httplog
 
   
 
   
 
     ########acl setting#############
 
     acl acl_static path_end -i .jpg .jpeg .png .gif .css .js
 
     acl acl_dynamic path_end -i .php
 
   
 
     #######acl hosts####################
 
     use_backend static_hosts if acl_static
 
     use_backend dynamic_hosts if acl_dynamic
 
     default_backend default_hosts
 
  
 
  
 
 #靜态伺服器
 
 backend static_hosts
 
     mode http
 
     server web1 10.0.0.17:80 check inter 3s fall 3 rise 5
 
  
 
 #動态伺服器
 
 backend dynamic_hosts
 
     mode http
 
     server web2 10.0.0.27:80 check inter 3s fall 3 rise 5
 
  
 
 #預設伺服器
 
 backend default_hosts
 
     mode http
 
     server web 10.0.0.7:8080 check inter 3s fall 3 rise 5      
  • 重新開機服務

    ​systemctl restart haproxy​

  1. 配置靜态伺服器static-hosts(10.0.0.17)

    将圖檔1.jpg上傳至/usr/share/nginx/html目錄下

[root@web1 html]# ls
 
 1.jpg  404.html  50x.html  en-US  icons  img  index.html  nginx-logo.png  poweredby.png      
  1. 配置動态伺服器dynamic-hosts(10.0.0.27)

    準備php檔案

#cat /usr/share/nginx/html/test.php
 
 <?php
 
 <h1> dynamic-hosts 10.0.0.27</h1>;                                                                                                                                                                             
 
 ?>      
  1. 配置預設伺服器default-hosts(10.0.0.7)
  • 安裝nginx
  • 修改監聽端口為8080
server {
 
         listen       8080;
 
         listen       [::]:8080;
 
     ......
 
     }      
  • 準備預設網頁
[root@haproxy haproxy]# echo "nginx `hostname -I`" > /usr/share/nginx/html/index.html      
  • 重新開機服務

    ​systemctl restart nginx​

  1. 實作動靜分離
  • 檢視jpg圖檔時,排程至static-hosts(10.0.0.17)
Haproxy&amp;Keepalived實作高可用
  • 檢視test.php時,排程至dynamic-hosts(10.0.0.27)
Haproxy&amp;Keepalived實作高可用

test.php内容

Haproxy&amp;Keepalived實作高可用
  • 檢視其他類型頁面時,排程至default-host(10.0.0.7)
Haproxy&amp;Keepalived實作高可用

五、使用haproxy,實作https。

架構

https

http

http

haproxy

10.0.0.7

web1

10.0.0.17

web2

10.0.0.27

client

haproxy配置(10.0.0.7)

  • 制作證書
mkdir -p /etc/haproxy/ssl
 
 cd /etc/haproxy/ssl
 
 openssl req -x509 -newkey rsa:2048 -subj "/CN=www.test.com" -keyout www.test.com.key -nodes -days 365 -out www.test.com.crt
 
 cat www.test.com.crt www.test.com.key > www.test.com.pem   #crt放前面      
  • 配置https
#cat /etc/haproxy/haproxy.cfg
 
 ......
 
 listen web_port
 
     bind 10.0.0.7:80
 
     bind 10.0.0.7:443 ssl crt /etc/haproxy/ssl/www.test.com.pem  #證書路徑
 
     redirect scheme https if !{ ssl_fc } #注意{ }内空格
 
     http-request set-header X-forwarded-Port %[dst_port]
 
     http-request add-header X-forwarder-Proto https if { ssl_fc }
 
  
 
     mode http
 
     log global
 
     option httplog
 
     balance roundrobin
 
     server web1 10.0.0.17:80 check inter 3s fall 3 rise 5   #後端real server使用http
 
     server web2 10.0.0.27:80 check inter 3s fall 3 rise 5      
  • 重新開機服務

​systemctl restart haproxy​

Real Server配置

​hostname -I > /usr/share/nginx/html/index.html​

實作https

通路http://www.test.com會自動跳轉至https://www.test.com,代理後端兩web伺服器(10.0.0.17/10.0.0.27)

Haproxy&amp;Keepalived實作高可用

輪詢通路web1

Haproxy&amp;Keepalived實作高可用

輪詢通路web2

Haproxy&amp;Keepalived實作高可用

六、詳解keepalived配置和使用

keepalived配置檔案

配置檔案

​/etc/keepalived/keepalived.conf​

配置檔案組成

  • global configuration

    global definitions:定義郵件配置,route_id,vrrp配置,多點傳播位址等

  • vrrp configuration

    vrrp instance(s):定義每個vrrp虛拟路由器

  • lvs configuration

    virtual server group(s)

    virtual server(s):LVS叢集的VS和RS

keepalived配置使用說明

global全局配置

global_defs {
 
     notification_email {
 
         root@localhost #keepalived 發生故障切換時郵件發送的目标郵箱,可以按行區分寫多個
 
         [email protected]
 
     }
 
     notification_email_from keepalived@localhost #發郵件的位址
 
     smtp_server 127.0.0.1  #郵件伺服器位址
 
     smtp_connect_timeout 30  #郵件伺服器連接配接timeout
 
     router_id ka1.example.com  #每個keepalived主機唯一辨別,建議使用目前主機名,但多節點重名不影響
 
     vrrp_skip_check_adv_addr #對所有通告封包都檢查,會比較消耗性能,啟用此配置後,如果收到的通告封包和上一個封包
 
        #是同一個路由器,則跳過檢查,預設值為全檢查
 
     vrrp_strict    #嚴格遵守VRRP協定,啟用此項後以下狀況将無法啟動服務:
 
      #1.無VIP位址
 
      #2.配置了單點傳播鄰居
 
      #3.在VRRP版本2中有IPv6位址,開啟動此項并且沒有配置vrrp_iptables時會自動開啟iptables防火牆規則,預設導緻VIP無法通路,建議不加此項配置
 
     vrrp_garp_interval 0 #gratuitous ARP messages 封包發送延遲,0表示不延遲
 
     vrrp_gna_interval 0    #unsolicited NA messages (不請自來)消息發送延遲
 
     vrrp_mcast_group4 224.0.0.18 #指定多點傳播IP位址範圍:224.0.0.0到239.255.255.255,預設值:224.0.0.18 
 
     vrrp_iptables    #此項和vrrp_strict同時開啟時,則不會添加防火牆規則,如果無配置vrrp_strict項,則無需啟用此項配置
 
 }      

虛拟路由配置

vrrp_instance <STRING> {  #<String>為vrrp的執行個體名,一般為業務名稱
 
  配置參數
 
  ......
 
  }
 
  
 
 #配置參數
 
 state MASTER|BACKUP    #目前節點在此虛拟路由器上的初始狀态,狀态為MASTER或者BACKUP
 
 interface IFACE_NAME   #綁定為目前虛拟路由器使用的實體接口,如:eth0,bond0,br0,可以和VIP不在一個網卡
 
 virtual_router_id VRID   #每個虛拟路由器惟一辨別,範圍:0-255,每個虛拟路由器此值必須唯一,否則服務無法啟動,
 
        #同屬一個虛拟路由器的多個keepalived節點必須相同,務必要确認在同一網絡中此值必須唯一
 
  
 
 priority 100   #目前實體節點在此虛拟路由器的優先級,範圍:1-254,值越大優先級越高,每個keepalived主機節點此值不同
 
 advert_int 1   #vrrp通告的時間間隔,預設1s
 
  
 
 authentication { #認證機制
 
     auth_type AH|PASS    #AH為IPSEC認證(不推薦),PASS為簡單密碼(建議使用)
 
     auth_pass <PASSWORD> #預共享密鑰,僅前8位有效,同一個虛拟路由器的多個keepalived節點必須一樣
 
 }
 
  
 
 virtual_ipaddress {    #虛拟IP,生産環境可能指定上百個IP位址
 
     #<IPADDR>/<MASK> brd <IPADDR> dev <STRING> scope <SCOPE> label <LABEL>
 
     192.168.200.100    #指定VIP,不指定網卡,預設為eth0,注意:不指定/prefix,預設為/32
 
     192.168.200.101/24 dev eth1    #指定VIP的網卡,建議和interface指令指定的網卡不在一個網卡
 
     192.168.200.102/24 dev eth2 label eth2:1 #指定VIP的網卡label 
 
 }
 
  
 
  
 
 #單點傳播配置,預設keepalived主機之間利用多點傳播互相通告消息,會造成網絡擁塞,可以替換成單點傳播,減少網絡流量
 
 #注意:啟用vrrp_strict時,不能啟用單點傳播
 
 #在所有節點vrrp_instance語句塊中設定對方主機的IP,建議設定為專用于對應心跳線網絡的位址,而非使用業務網絡
 
 unicast_src_ip <IPADDR>    #指定發送單點傳播的源IP,本機IP
 
 unicast_peer {
 
     <IPADDR>     #指定接收單點傳播的對方目标主機IP
 
     <IPADDR2>      #如果有多個keepalived,再加其它節點的IP
 
     ......
 
 }
 
  
 
 track_interface {  #配置監控網絡接口,一旦出現故障,則轉為FAULT狀态實作位址轉移
 
     eth0
 
     eth1
 
     ......
 
 }      

虛拟服務配置

  • 虛拟服務組配置

将多個虛拟伺服器定義成一個組,統一對外服務,如:http和https定義成一個虛拟伺服器組

virtual_server_group <STRING> {
 
            # Virtual IP Address and Port
 
            <IPADDR> <PORT>
 
            <IPADDR> <PORT>
 
            ...
 
            # <IPADDR RANGE> has the form
 
            # XXX.YYY.ZZZ.WWW-VVV eg 192.168.200.1-10
 
            # range includes both .1 and .10 address
 
            <IPADDR RANGE> <PORT># VIP range VPORT
 
            <IPADDR RANGE> <PORT>
 
            ...
 
            # Firewall Mark (fwmark)
 
            fwmark <INTEGER>
 
            fwmark <INTEGER>
 
            ...
 
 }      

虛拟伺服器配置

virtual_server IP port {    #定義虛拟主機IP位址及其端口
 
     delay_loop <INT>     #檢查後端伺服器的時間間隔
 
     lb_algo rr|wrr|lc|wlc|lblc|sh|dh #定義排程方法
 
     lb_kind NAT|DR|TUN     #叢集的類型,注意要大寫
 
     persistence_timeout <INT>    #持久連接配接時長
 
     protocol TCP|UDP|SCTP    #指定服務協定,一般為TCP
 
     sorry_server <IPADDR> <PORT> #所有RS故障時,備用伺服器位址
 
     real_server <IPADDR> <PORT> {  #RS的IP和PORT
 
         weight <INT>     #RS權重
 
         notify_up <STRING>|<QUOTED-STRING> #RS上線通知腳本
 
         notify_down <STRING>|<QUOTED-STRING> #RS下線通知腳本
 
         HTTP_GET|SSL_GET|TCP_CHECK|SMTP_CHECK|MISC_CHECK { ... } #定義目前主機健康狀态檢測方法
 
     }
 
 }
 
 #注意:括号必須分行寫,兩個括号寫在同一行,如: }} 會出錯      

其他配置

include /etc/keepalived/conf.d/*.conf   #将VRRP相關配置放在子配置檔案中      

七、keeplived 結合haproxy 實作高可用

haproxy+keepalived 10.0.0.10

master

lo:10.0.0.10

eth0:10.0.0.7

backup

lo:10.0.0.10

eth0:10.0.0.17

Client1

web1

10.0.0.27

web2

10.0.0.37

master(10.0.0.7)

安裝keepalived

#!/bin/bash
 
 # 編譯安裝Keepalived
 
  
 
 . /etc/init.d/functions
 
 # Keepalived版本
 
 Keepalived_versinotallow=keepalived-2.2.4
 
 TAR=tar.gz
 
 Keepalived=${Keepalived_version}.${TAR}
 
 
 
 # Keepalived源碼下載下傳位址
 
 Keepalived_url=https://keepalived.org/software/${Keepalived}
 
 # Keepalived安裝路徑
 
 Keepalived_install_DIR=/apps/keepalived
 
 
 
 # CPU數量
 
 CPUS=`lscpu|grep "^CPU(s)"|awk '{print $2}'`
 
 # 系統類型
 
 os_type=`grep "^NAME" /etc/os-release |awk -F'"| ' '{print $2}'`
 
 # 系統版本号
 
 os_versinotallow=`awk -F'"' '/^VERSION_ID/{print $2}' /etc/os-release`
 
  
 
 color () {
 
 if [[ $2 -eq 0 ]];then
 
     echo -e "\e[1;32m$1\t\t\t\t\t\t[  OK  ]\e[0;m"
 
 else
 
     echo $2
 
     echo -e "\e[1;31m$1\t\t\t\t\t\t[ FAILED ]\e[0;m"
 
 fi
 
 }
 
  
 
 download_keepalived (){
 
 cd /opt
 
 if [ -e ${Keepalived} ];then
 
     color "Keepalived安裝包已存在" 0
 
 else
 
     color "開始下載下傳Keepalived安裝包" 0
 
     wget ${Keepalived_url} --no-check-certificate
 
     if [ $? -ne 0 ];then
 
         color "下載下傳Keepalived安裝包失敗,退出!" 1
 
         exit 1
 
     fi
 
 fi
 
 }
 
  
 
 install_keepalived (){
 
 # 安裝依賴包
 
 yum install -y gcc curl openssl-devel libnl3-devel net-snmp-devel
 
 
 
 # 解壓源碼包
 
 tar xvf /opt/${Keepalived} -C /usr/local/src
 
 ln -s /usr/local/src/${Keepalived_version} /usr/local/src/keepalived
 
 
 
 # 編譯安裝
 
 cd /usr/local/src/keepalived
 
 # 選項--disable-fwmark可用于禁用iptables規則,可訪止VIP無法通路,無此選項預設會啟用ipatbles規則
 
 ./configure --prefix=${Keepalived_install_DIR} --disable-fwmark
 
  
 
 make -j ${CPUS} && make install
 
 
 
 # 準備服務啟動配置檔案
 
 mkdir /etc/keepalived
 
 cp ${Keepalived_install_DIR}/etc/keepalived/keepalived.conf /etc/keepalived/
 
  
 
 systemctl daemon-reload
 
 systemctl enable --now keepalived
 
 systemctl is-active keepalived
 
  
 
 if [ $? -ne 0 ];then
 
     color "keepalived服務啟動失敗!" 1
 
     exit 1
 
 else
 
     color "keepalived服務啟動成功" 0
 
 fi
 
 }
 
  
 
 download_keepalived
 
  
 
 install_keepalived
 
  
 
 exit 0      

修改keepalived配置檔案

[root@master ~]# vim /etc/keepalived/keepalived.conf
 
 ! Configuration File for keepalived
 
  
 
 global_defs {
 
    notification_email {
 
      [email protected]
 
      [email protected]
 
      [email protected]
 
    }
 
    notification_email_from [email protected]
 
    smtp_server 192.168.200.1
 
    smtp_connect_timeout 30
 
    router_id 10.0.0.7
 
    vrrp_skip_check_adv_addr
 
    vrrp_garp_interval 0
 
    vrrp_gna_interval 0
 
    vrrp_mcast_group4 224.0.0.18
 
 }
 
  
 
 # 腳本需放在調用之前,先定義好
 
 vrrp_script chk_haproxy {
 
     script "/etc/keepalived/chk_haproxy.sh"
 
     interval 1
 
     timeout 2
 
     weight -30
 
     fall 3
 
     rise 5
 
 }
 
  
 
 vrrp_instance haproxy {
 
     state MASTER
 
     interface eth0
 
     virtual_router_id 51
 
     priority 100
 
     advert_int 1
 
     authentication {                                                                                                                                                                               
 
         auth_type PASS
 
         auth_pass 1111
 
     }
 
     virtual_ipaddress {
 
         10.0.0.10/24 dev eth0 label eth0:1
 
     }
 
   
 
     track_script {
 
       chk_haproxy
 
     }
 
  
 
 }      

準備chk_haproxy.sh腳本

[root@master ~]# cat /etc/keepalived/chk_haproxy.sh 
 
 #!/bin/bash
 
 /usr/bin/killall -0 haproxy
 
  
 
 #添加執行權限
 
 [root@master ~]# chmod a+x /etc/keepalived/chk_haproxy.sh      

安裝haproxy

修改haproxy配置檔案

[root@master ~]# vim /etc/haproxy/haproxy.cfg 
 
     group haproxy
 
     daemon
 
     #nbproc 4
 
     #cpu-map 1 0
 
     #cpu-map 2 1
 
     #cpu-map 3 2
 
     #cpu-map 4 3
 
     pidfile /var/lib/haproxy/haproxy.pid
 
     log 127.0.0.1 local2 info
 
  
 
 defaults
 
     option http-keep-alive
 
     option forwardfor
 
     maxconn 100000
 
     mode http
 
     timeout connect 300000ms
 
     timeout client 300000ms
 
     timeout server 300000ms
 
  
 
 listen stats
 
     mode http
 
     bind 0.0.0.0:9999
 
     stats enable
 
     log global
 
     stats uri   /haproxy-status
 
     stats auth  haadmin:123456
 
  
 
 listen VIP     #新增以下配置
 
     bind 10.0.0.10:80
 
     mode http
 
     log global
 
     option httplog
 
     server web1 10.0.0.27:80 check inter 3s fall 3 rise 5
 
     server web2 10.0.0.37:80 check inter 3s fall 3 rise 5      

啟用核心參數

#限制響應級别:arp_ignore
 
 #0:預設值,表示可使用本地任意接口上配置的任意位址進行響應
 
 #1:僅在請求的目标IP配置在本地主機的接收到請求封包的接口上時,才給予響應
 
 echo 1 > /proc/sys/net/ipv4/conf/all/arp_ignore
 
 echo 1 > /proc/sys/net/ipv4/conf/lo/arp_ignore
 
  
 
 #限制通告級别:arp_announce
 
 #0:預設值,把本機所有接口的所有資訊向每個接口的網絡進行通告
 
 #1:盡量避免将接口資訊向非直接連接配接網絡進行通告
 
 #2:必須避免将接口資訊向非本網絡進行通告
 
 echo 2 > /proc/sys/net/ipv4/conf/all/arp_announce
 
 echo 2 > /proc/sys/net/ipv4/conf/lo/arp_announce
 
  
 
 echo "net.ipv4.ip_nonlocal_bind = 1" >> /etc/sysctl.conf #開啟後VIP不在本地,haproxy也可綁定該位址
 
 echo "net.ipv4.ip_forward = 1" >> /etc/sysctl.conf   #開啟ipv4路由轉發功能      

執行​

​sysctl -p​

​指令,修改核心生效

檢視狀态,VIP(10.0.0.10)漂移在MASTER,haproxy綁定80端口正常

[root@master ~]# hostname -I
 
 10.0.0.7 10.0.0.10 
 
 [root@master ~]# ss -ntl
 
 State       Recv-Q Send-Q                                                           Local Address:Port                                                                          Peer Address:Port            
 
 LISTEN      0      128                                                                          *:22                                                                                       *:*                
 
 LISTEN      0      100                                                                  127.0.0.1:25                                                                                       *:*                
 
 LISTEN      0      128                                                                          *:9999                                                                                     *:*                
 
 LISTEN      0      128                                                                          *:111                                                                                      *:*                
 
 LISTEN      0      128                                                                  10.0.0.10:80                                                                                       *:*                
 
 LISTEN      0      128                                                                       [::]:22                                                                                    [::]:*                
 
 LISTEN      0      100                                                                      [::1]:25                                                                                    [::]:*                
 
 LISTEN      0      128                                                                       [::]:111                                                                                   [::]:*                
 
 [root@master ~]#      

backup(10.0.0.17)

安裝keepalived

安裝方法同master

修改配置

[root@backup ~]# vim /etc/keepalived/keepalived.conf 
 
  
 
 ! Configuration File for keepalived
 
  
 
 global_defs {
 
    notification_email {
 
      [email protected]
 
      [email protected]
 
      [email protected]
 
    }
 
    notification_email_from [email protected]
 
    smtp_server 192.168.200.1
 
    smtp_connect_timeout 30
 
    router_id 10.0.0.17         #與master不同,為本機IP
 
    vrrp_skip_check_adv_addr
 
    vrrp_garp_interval 0
 
    vrrp_gna_interval 0
 
    vrrp_mcast_group4 224.0.0.18
 
 }
 
  
 
 vrrp_instance haproxy {
 
     state BACKUP           #BACKUP
 
     interface eth0
 
     virtual_router_id 51
 
     priority 80                         #優先級80                                                                                                                                                          
 
     advert_int 1
 
     authentication {
 
         auth_type PASS
 
         auth_pass 1111
 
     }
 
     virtual_ipaddress {
 
         10.0.0.10/24 dev eth0 label eth0:1
 
     }
 
 }      

安裝haproxy

[root@backup ~]# vim /etc/haproxy/haproxy.cfg 
 
     group haproxy
 
     daemon
 
     #nbproc 4
 
     #cpu-map 1 0
 
     #cpu-map 2 1
 
     #cpu-map 3 2
 
     #cpu-map 4 3
 
     pidfile /var/lib/haproxy/haproxy.pid
 
     log 127.0.0.1 local2 info
 
  
 
 defaults
 
     option http-keep-alive
 
     option forwardfor
 
     maxconn 100000
 
     mode http
 
     timeout connect 300000ms
 
     timeout client 300000ms
 
     timeout server 300000ms
 
  
 
 listen stats
 
     mode http
 
     bind 0.0.0.0:9999
 
     stats enable
 
     log global
 
     stats uri   /haproxy-status
 
     stats auth  haadmin:123456
 
  
 
 listen VIP     #新增以下配置
 
     bind 10.0.0.10:80
 
     mode http
 
     log global
 
     option httplog
 
     server web1 10.0.0.27:80 check inter 3s fall 3 rise 5
 
     server web2 10.0.0.37:80 check inter 3s fall 3 rise 5      

啟用核心參數

#限制響應級别:arp_ignore
 
 #0:預設值,表示可使用本地任意接口上配置的任意位址進行響應
 
 #1:僅在請求的目标IP配置在本地主機的接收到請求封包的接口上時,才給予響應
 
 echo 1 > /proc/sys/net/ipv4/conf/all/arp_ignore
 
 echo 1 > /proc/sys/net/ipv4/conf/lo/arp_ignore
 
  
 
 #限制通告級别:arp_announce
 
 #0:預設值,把本機所有接口的所有資訊向每個接口的網絡進行通告
 
 #1:盡量避免将接口資訊向非直接連接配接網絡進行通告
 
 #2:必須避免将接口資訊向非本網絡進行通告
 
 echo 2 > /proc/sys/net/ipv4/conf/all/arp_announce
 
 echo 2 > /proc/sys/net/ipv4/conf/lo/arp_announce
 
  
 
 echo "net.ipv4.ip_nonlocal_bind = 1" >> /etc/sysctl.conf #開啟後VIP不在本地,haproxy也可綁定該位址
 
 echo "net.ipv4.ip_forward = 1" >> /etc/sysctl.conf   #開啟ipv4路由轉發功能      

執行​

​sysctl -p​

​指令,修改核心生效

檢視狀态,BACKUP上無VIP(10.0.0.10),haproxy綁定10.0.0.10:80端口正常

[root@backup ~]# hostname -I
 
 10.0.0.17 
 
 [root@backup ~]# ss -ntl
 
 State       Recv-Q Send-Q                                                           Local Address:Port                                                                          Peer Address:Port            
 
 LISTEN      0      128                                                                          *:9999                                                                                     *:*                
 
 LISTEN      0      128                                                                          *:111                                                                                      *:*                
 
 LISTEN      0      128                                                                  10.0.0.10:80                                                                                       *:*                
 
 LISTEN      0      128                                                                          *:22                                                                                       *:*                
 
 LISTEN      0      100                                                                  127.0.0.1:25                                                                                       *:*                
 
 LISTEN      0      128                                                                       [::]:111                                                                                   [::]:*                
 
 LISTEN      0      128                                                                       [::]:22                                                                                    [::]:*                
 
 LISTEN      0      100                                                                      [::1]:25                                                                                    [::]:*      

web1(10.0.0.27)

  • 安裝nginx

​yun install nginx -y​

  • 準備網頁
[root@web1 ~]# hostname -I > /usr/share/nginx/html/index.html      
  • 啟動服務

​systemctl start nginx​

web2(10.0.0.37)

  • 安裝nginx

​yun install nginx -y​

  • 準備網頁
[root@web2 ~]# hostname -I > /usr/share/nginx/html/index.html      
  • 啟動服務

​systemctl start nginx​

實作高可用

master正常情況下,haproxy輪詢排程至後端web server

Haproxy&amp;Keepalived實作高可用
Haproxy&amp;Keepalived實作高可用

模拟master故障,停止keepalived

[root@master ~]# systemctl stop keepalived
 
 [root@master ~]# hostname -I
 
 10.0.0.7 
 
  
 
 # 檢視backup,VIP已轉移至backup上
 
 [root@backup ~]# hostname -I
 
 10.0.0.17 10.0.0.10      

通路後端web server正常

Haproxy&amp;Keepalived實作高可用
Haproxy&amp;Keepalived實作高可用

模拟master故障,停止haproxy

[root@master ~]# systemctl stop haproxy
 
 [root@master ~]# hostname -I
 
 10.0.0.7      

keepalived監測到haproxy程序不存在,自動進行降級處理,抓包可看到master節點優先級-30至70,backup節點優先級80升為主。

Haproxy&amp;Keepalived實作高可用

VIP漂移至backup

[root@backup ~]# hostname -I
 
 10.0.0.17 10.0.0.10      

通路後端web server正常

Haproxy&amp;Keepalived實作高可用
Haproxy&amp;Keepalived實作高可用

八、簡述腦裂,産生的原因,預防的辦法

腦裂

指在一個高可用(HA)系統中,當連接配接着的兩個節點斷開聯系時,本來為一個整體的系統,分裂為兩個獨立節點,這時兩個節點開始争搶共享資源,結果會導緻系統混亂,資料損壞。

腦裂産生的原因

  1. 高可用伺服器對之間心跳線發生故障,導緻無法正常通信
  2. 心跳線壞了(包括斷了,老化)
  3. 因網卡及相關驅動壞了,IP配置及沖突問題(網卡直連)
  4. 因心跳線間連接配接的裝置故障(網卡及交換機)
  5. 因仲裁的機器出現問題(采用仲裁的方案)
  6. 高可用伺服器上開啟了iptables防火牆阻止了心跳消息傳輸
  7. 高可用伺服器上心跳網卡位址等資訊配置不正确,導緻發送心跳失敗
  8. 其他服務配置不當等原因,如心跳方式不同,心跳廣播沖突,軟體bug等
  9. keepalived配置裡同一VRRP執行個體如果virtual_router_id兩端參數配置不一緻也會導緻腦裂問題發生

常見預防/解決方案

  1. 添加備援心跳線,可同時使用串行電纜和以太網電纜連接配接,同時使用兩條心跳線路。

    這樣一條線路壞了,另一個還是好的,依然能傳送心跳消息。

  2. 當檢測到裂腦時強行關閉一個心跳節點(這個功能需特殊裝置支援,如Stonith、feyce)。

    相當于備節點接收不到心跳消患,通過單獨的線路發送關機指令關閉主節點的電源。

  3. 做好對裂腦的監控報警(如郵件及手機短信等或值班),在問題發生時人為第一時間介入仲裁,降低損失。

    例如将報警消息發送到管理者手機上,管理者可以通過手機回複對應數字或簡單的字元串操作傳回給伺服器.讓伺服器根據指令自動處理相應故障,這樣解決故障的時間更短.

九、實作keeplived監控,通知

添加腳本調用方法

#vim /etc/keepalived/keepalived.conf
 
 ......
 
 # 在vrrp_instance 語句塊中添加
 
 vrrp_instance haproxy {
 
     state MASTER
 
     interface eth0
 
     virtual_router_id 51
 
     priority 100
 
     advert_int 1
 
     authentication {
 
         auth_type PASS
 
         auth_pass 1111
 
     }
 
     virtual_ipaddress {
 
         10.0.0.10/24 dev eth0 label eth0:1
 
     }
 
  
 
     track_script {
 
       chk_haproxy 
 
     }
 
  
 
     # 添加如下調用腳本方法
 
     notify_master "/etc/keepalived/notify.sh master" #目前節點成為master時調用
 
     notify_backup "/etc/keepalived/notify.sh backpup"  #目前節點成為backup時調用
 
     notify_fault  "/etc/keepalived/notify.sh fault"  #目前節點成故障時調用
 
 }      

建立通知腳本

# cat /etc/keepalived/notify.sh 
 
 #!/bin/bash
 
  
 
 # 接收人郵箱位址
 
 cnotallow='[email protected]'
 
 notify() {
 
   mailsubject="$(hostname) to be $1, vip 轉移"
 
   mailbody="$(date +'%F %T'): vrrp transition, $(hostname) changed to be $1"
 
   echo "$mailbody" | mail -s "$mailsubject" $contact
 
 }
 
 case $1 in
 
 master)
 
   notify master
 
   ;;
 
 backup)
 
   notify backup
 
   ;;
 
 fault)
 
   notify fault
 
   ;;
 
 *)
 
   echo "Usage: $(basename $0) {master|backup|fault}"
 
   exit 1
 
   ;;
 
 esac      

腳本授權

​chmod a+x /etc/keepalived/notify.sh​

郵件配置

# vim /etc/mail.rc
 
 ......
 
 #在最後添加下面資訊
 
 set [email protected]   #發送的郵箱位址
 
 set smtp=smtp.qq.com     #smtp伺服器
 
 set [email protected] #郵箱登入賬号
 
 set smtp-auth-password=uqswsruhknlm  #郵箱登入授權碼
 
 set smtp-auth=login
 
 set ssl-verify=ignore      

重新開機服務

模拟故障,郵件通知

  • 停止master節點haproxy
[root@master ~]# systemctl stop haproxy      
  • 抓包可看到master節點優先級降至70,backup節點成為主
[root@master ~]# tcpdump -i eth0 -nn host 224.0.0.18
 
 tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
 
 listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes
 
 13:50:50.289041 IP 10.0.0.7 > 224.0.0.18: VRRPv2, Advertisement, vrid 51, prio 70, authtype simple, intvl 1s, length 20
 
 13:51:50.294612 IP 10.0.0.7 > 224.0.0.18: VRRPv2, Advertisement, vrid 51, prio 70, authtype simple, intvl 1s, length 20
 
 13:51:50.978643 IP 10.0.0.17 > 224.0.0.18: VRRPv2, Advertisement, vrid 51, prio 80, authtype simple, intvl 1s, length 20
 
 13:51:51.983404 IP 10.0.0.17 > 224.0.0.18: VRRPv2, Advertisement, vrid 51, prio 80, authtype simple, intvl 1s, length 20
 
 13:51:52.987030 IP 10.0.0.17 > 224.0.0.18: VRRPv2, Advertisement, vrid 51, prio 80, authtype simple, intvl 1s, length 20      
  • 郵箱收到通知,backup節點升為主
  • 恢複master節點haproxy
[root@master ~]# systemctl start haproxy      
  • 抓包可看到master節點優先級恢複至100,master節點恢複為主
[root@master ~]# tcpdump -i eth0 -nn host 224.0.0.18
 
 tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
 
 listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes
 
 13:58:16.942124 IP 10.0.0.17 > 224.0.0.18: VRRPv2, Advertisement, vrid 51, prio 80, authtype simple, intvl 1s, length 20
 
 13:58:17.945570 IP 10.0.0.17 > 224.0.0.18: VRRPv2, Advertisement, vrid 51, prio 80, authtype simple, intvl 1s, length 20
 
 13:58:18.947258 IP 10.0.0.17 > 224.0.0.18: VRRPv2, Advertisement, vrid 51, prio 80, authtype simple, intvl 1s, length 20
 
 13:58:19.948354 IP 10.0.0.17 > 224.0.0.18: VRRPv2, Advertisement, vrid 51, prio 80, authtype simple, intvl 1s, length 20
 
 13:58:20.554474 IP 10.0.0.7 > 224.0.0.18: VRRPv2, Advertisement, vrid 51, prio 100, authtype simple, intvl 1s, length 20
 
 13:58:21.556958 IP 10.0.0.7 > 224.0.0.18: VRRPv2, Advertisement, vrid 51, prio 100, authtype simple, intvl 1s, length 20
 
 13:58:22.560039 IP 10.0.0.7 > 224.0.0.18: VRRPv2, Advertisement, vrid 51, prio 100, authtype simple, intvl 1s, length 20
 
 13:58:23.561156 IP 10.0.0.7 > 224.0.0.18: VRRPv2, Advertisement, vrid 51, prio 100, authtype simple, intvl 1s, length 20      
  • 郵箱收到通知,master節點恢複為主

繼續閱讀