Keepalived服務詳解

Praywu發表於2020-09-23

1. VRRP協議

1.1 VRRP協議概述

  • VRRP協議的出現是為了解決靜態路由的單點故障,它是通過一種競選機制來將路由任務交給某個vrrp路由器的
  • 在VRRP物理結構中,有多個物理的VRRP路由器,其中有一臺稱為“master”(主節點路由器),其他的都是“backup”(備節點路由器)
    • master和backup的身份,是通過他媽的優先順序來定義競選的
  • 在VRRP虛擬結構中,虛擬路由都是通過“MAC+VRID”的形式來標識的,如“00-00-5E-00-01-{VRID}”
    • 只有master節點才會傳送VRRP廣告包(vrrp advertisement message)
    • 當master節點宕掉的時候,backup中優先順序最高的VRRP裝置會搶佔並升級為master

1.2 VRRP的術語

  • 虛擬路由器
    • 由一個Master路由器和多個Backup路由器組成,主機將虛擬路由器當做預設閘道器(將Master和Backup看做一個整體)
  • VRID
    • 虛擬路由器的標識,有相同的VRID的一組路由器構成一個虛擬路由器
  • Master路由器
    • 虛擬路由器中承擔報文轉發任務的路由器
  • Backup路由器
    • 虛擬路由器中備份節點路由器
  • 虛擬IP地址
    • 虛擬路由器的IP地址,一個虛擬路由器可以擁有一個或多個IP地址
  • VIP
    • IP地址擁有者,介面IP地址與虛擬IP地址相同的路由器被稱為IP地址擁有者
  • VMAC
    • 虛擬MAC地址,一個虛擬路由器擁有一個虛擬MAC地址,通常情況下,虛擬路由器回應ARP請求使用的是虛擬MAC地址
  • 優先順序
    • VRRP根據優先順序來確定虛擬路由器中每臺路由器的地位
  • 非搶佔式
    • 如果backup路由器工作在此模式下,則若Master路由器沒有出現故障,backup即使隨後被配置了更高的優先順序也不會成為Master
  • 搶佔式
    • 如果backup路由器工作在搶佔方式下,當它收到VRRP報文後,會將主機的優先順序與通告報文中的優先順序進行比較,
    • 如果主機的優先順序比當前的Master路由器的優先順序高,就會主動搶佔成為Master路由器,否則,將保持Backup狀態

1.3 VRRP的工作過程

  • 虛擬路由器中的路由器根據優先順序選舉出Master
    • Master路由器通過傳送免費ARP報文,將主機的虛擬MAC地址通知給它連線的裝置或者主機,從而承擔報文轉發任務
  • Master路由器週期性傳送VRRP報文,以公佈其配置資訊(優先順序等)和工作狀況
  • 如果Master路由器出現故障,虛擬路由器中的Backup路由器將根據優先順序重新選舉出新的Master
  • 虛擬路由器狀態切換時,Master路由器由一臺裝置切換為另一臺裝置
    • 新的Master路由器傳送一個攜帶虛擬路由器的MAC地址和虛擬IP地址資訊的免費ARP報文,以更新與它連線的主機中的ARP相關的資訊
    • 網路中的主機感知不到Master路由器已經切換為另外一臺裝置
  • Backup路由器的優先順序高於Master路由器時,由Backup路由器的工作方式(搶佔方式和非搶佔方式)決定是否重新選舉Master
  • 為了保證Master路由器和Backup路由器能夠協調工作,VRRP需要實現以下功能
    • Master路由器的選舉
    • Master路由器狀態的通告
    • 為了提高安全性,VRRP還提供了認證功能

1.4 Master路由器的選舉

  • VRRP根據優先順序來確定虛擬路由器中每臺路由器的角色(Master路由器或Backup路由器),優先順序越高,則越有可能成為Master路由器
  • 初始建立的路由器在Backup狀態,通過VRRP報文獲知虛擬路由器中其他成員的優先順序
    • 如果VRRP報文中Master路由器的優先順序高於自己的優先順序,則路由器保持在Backup狀態
    • 如果VRRP報文中Master路由器的優先順序低於自己的優先順序
      • 採用搶佔工作方式的路由器將搶佔成為Master狀態,週期性的傳送VRRP報文
      • 採用非搶佔式工作方式的路由器仍保持Backup狀態
    • 如果在一定時間內沒有收到VRRP報文,則路由器切換為Master狀態
  • VRRP優先順序的取值範圍為0到255(數值越大優先順序越高),可配置的範圍是1到254
    • 優先順序0為系統保留給路由器放棄Master位置時候使用,255則是系統保留給IP地址擁有者使用
    • 當路由器為IP地址擁有者時,其優先順序始終為255,因此當虛擬路由器記憶體在IP地址擁有者時,只要其工作正常,則為Master路由器

1.5 Master路由器狀態的通告

  • Master路由器週期性傳送VRRP報文,在虛擬路由器中公佈其配置資訊(優先順序等)和工作狀況
    • Backup路由器通過接收到VRRP報文的情況來判斷Master路由器是否工作正常
  • Master路由器主動放棄Master地位(如Master路由器退出虛擬路由器)時
    • 會傳送優先順序為0的VRRP報文,致使Backup路由器快速切換變成Master路由器,這個切換時間稱為Skew time
    • 計算方式為(256-Backup路由器的優先順序)/256,單位為秒
  • 當Master路由器因故障不能傳送VRRP報文時,Backup路由器並不能立即知道其工作狀況
    • Backup路由器等待一段時間後,如果還沒接收到VRRP報文,那麼會認為Master路由器無法正常工作,而把自己升級為Master路由器,週期性傳送VRRP報文,如果此時多個Backup路由器競爭Master路由器的位置,將通過優先順序來選舉Master路由器,Backup路由器預設等待的時間稱為Master_Down_Interval,取值為:(3*VRRP報文的傳送時間間隔)+Skewtime,單位為秒

在效能不夠穩定的網路中,Backup路由器可能因為網路堵塞而在Master_Down_Interval期間沒有收到Master路由器的報文而主動搶佔為Master位置,如果此時原Master路由器的報文又到達了,就會出現虛擬路由器的成員頻繁的進行Master搶佔現象,為了緩解這種現象的發生,特制定了延遲等待定時器,它可以使得Backup路由器在等待了Master_Down_Interval後,再等待延遲等待時間,如在此期間仍然沒有收到VRRP報文,此時Backup路由器才會切換為Master路由器,對外傳送VRRP報文。

1.6 認證方式

1)無認證

  • 不進行任何VRRP報文的合法性認證,不提供安全性保障

2)簡單字元認證

  • 在一個有可能受到安全威脅的網路中,可以將認證方式設定為簡單字元認證(一般就採用這種認證)
  • 傳送VRRP報文的路由器將認證字填入到報文中,而收到VRRP報文的路由器會將收到的VRRP報文中的認證字和本地配置的認證字進行比較,如果認證字相同,則認為接受到的報文是合法的VRRP報文,否則認為接收到的報文是一個非法報文

3)MD5認證

  • 在一個非常不安全的網路中,可以將認證方式設定為MD5認證
  • 傳送VRRP報文的路由器利用認證字和MD5演算法對VRRP報文進行加密,加密後的報文儲存在Authentication Header(認證頭)中,收到VRRP報文的路由器會利用認證字解密報文,檢查該報文的合法性

2. keepalived

2.1 keepalived概述

1)keepalived的功能

  • 對後端RealServer進行健康狀況檢查,支援4層、5層和7層協議進行健康檢查
  • 對負載均衡器進行高可用,防止Director單點故障

2)keepalived的運作

  • 通過VRRP(Virtual Router Redundancy Protocol)虛擬路由冗餘協議來實現故障轉移。
  • keepalived正常工作時,主節點(master)會不斷的傳送心跳資訊給備節點(backup)
    • 當備節點在一定時間內沒有收到主節點的心跳資訊時,備節點會認為主節點宕了,就會接管主節點上的資源,並繼續向外提供服務保證其可用性
    • 當主節點恢復時,備節點會自動讓出資源並再次自動成為備節點

3)keepalived監控LVS

  • 使用keepalived監控、高可用LVS叢集時(keepalived+lvs),並不需要在Director上使用ipvsadm額外配置ipvs規則。
  • 因為keepalived中集合了管理ipvs規則的元件(ipvs wrapper),可以直接在keepalived的配置檔案中配置ipvs相關規則,在解析配置檔案時會通過特定的元件將規則傳送給到核心中的ipvs模組。

2.2 keepalived軟體結構

1)VRRP協議

  • vrrp協議在Linux主機上以守護程式方式的實現,原生設計目的是為了高可用ipvs服務
  • 能夠根據配置檔案生成ipvs規則,並對各RS的健康做檢測
    • vrrp_script
    • vrrp_track
  • 基於vrrp協議完成地址滾動
  • 為vip地址所在的節點生成ipvs規則(在配置檔案中預先定義)
  • 基於指令碼呼叫介面通過執行指令碼完成指令碼中定義的功能,進而影響叢集事務

2)keepalived的元件

  • keepalived服務啟動時,將產生三個相關程式,一個父程式和兩個子程式
    • 主程式:Watchdog看門狗主程式
    • 子程式1:VRRP Child
    • 子程式2:Healthchecking Child
  • 兩個子程式都會開啟本地套接字Unix Domain Socket
    • 當keepalived服務啟動後,父程式會通過unix domain socket每隔5秒傳送一個hello訊息給子程式
    • 如果父程式無法傳送訊息給子程式,將認為子程式出現問題,於是會重啟子程式
  • 核心元件
    • Watchdog
      • 看門狗,負責fork和監控子程式,對Checkers和vrrp stack進行監控
    • Checkers
      • 負責RealServer的健康狀況檢查,並在LVS的拓撲中移除、新增RealServer
      • 它支援layer4/5/7層的協議檢查,該元件使用獨立的子程式負責,但被父程式監控
    • VRRP Stack
      • 提供Director的故障轉移功能從而實現Director的高可用
      • 該元件可獨立提供功能,無需LVS的支援,該元件使用獨立的子程式負責,但被父程式監控
    • System Call
      • 提供讀取自定義指令碼的功能,該元件在使用時,將臨時產生一個子程式來執行任務
    • IPVS wrapper
      • 負責將配置檔案中的IPVS相關規則傳送到核心的ipvs模組
    • Netlink Reflector
      • 用來設定、監控vrrp的ip地址
  • IO複用器
  • 記憶體管理
  • 配置檔案分析器

3)工作模型

  • 主備:單虛擬路由器
  • 主主:主/備(虛擬路由器1)+ 備/主(虛擬路由器2)

3. keepalived的配置和使用

3.1 使用前的配置

  • 各節點時間要同步
  • 確保iptables和selinux不會成為阻礙
  • 確保各節點的用於叢集服務的介面支援MULTICAST通訊
    • 開啟網路卡的多播功能:ip link set multicast on dev ens33
    • D類地址:224-239(多播地址的範圍)
  • 各節點之間可通過主機名互相通訊(可選)
    • 節點的名稱設定與hosts檔案中解析的主機名都要保持一致
    • uname -n 獲得的主機,與解析的主機名要相同
  • 各節點之間基於金鑰認證的方式通過ssh互相通訊(可選)

3.2 程式環境

  • 主程式檔案
    • /usr/sbin/keepalived
  • Unit file
    • /usr/lib/systemd/system/keepalived.service
    • Unix file 的配置檔案:/etc/sysconfig/keepalived
  • 配置檔案
    • /etc/keepalived/keepalived.conf

3.3 配置檔案概述

# 全域性配置(全域性配置有Global definitions和Static routes/address,全域性定義和靜態路由)
# GLOBAL CONFIGURATION: 
     global_defs                 # Block id
         {
            ...
         }
        
# 配置vrrp例項(VRRP例項和VRRP同步組)
# VRRPD CONFIGURATION:
     vrrp instance               # 虛擬路由器,VRRP例項
         vrrp_instance  NAME {
              ...
         }
     vrrp synchronization group  # VRRP同步組
         vrrp_sync_group  NAME  {
              ...
         }
# ipvs的相關配置
# LVS CONFIGURATION:
      # 叢集服務,服務內的RS
      Virtual server groups 
      Virtual server               #ipvs叢集的vs和rs
  • 如果多個例項同進同退,那麼就要把他們配置成一個同步組(高可用LVS的NAT模式時)
    • 如下圖所示,當vip1在網路卡1上時,vip2必須要在網路卡2上,所以vip1和vip2必須同進同退
    • vip1在哪個節點上,vip2就應該在哪個節點上

3.4 配置檔案詳解

1)全域性配置

### 全域性配置 ###
global_defs {              # 全域性部分定義郵件報警系統,可以不用定義
    notification_email {   # 定義郵件傳送目標,收件人郵箱地址                
        acassen@firewall.loc
        failover@firewall.loc
    } 
    notification_email_from  hgzerowzh@qq.com # 定義發件人郵箱地址
    smtp_server 192.168.200.1    # 定義郵件傳送伺服器IP,本地傳送寫localhost
    smtp_connect_timeout 30      # 定義郵件伺服器建立連線的超時時長
    router_id c7_node_03         # 標識keepalived伺服器的字串,物理節點的識別符號;建議使用主機名

    vrrp_skip_check_adv_addr     # 如果通告與接收的上一個通告來自相同的master路由器,則不執行檢查
    !vrrp_strict                # 嚴格遵守VRRP協議,這一項最好關閉(加感嘆號),若不關閉,可用vip無法被ping通
    vrrp_garp_interval 0.001     # 在一個介面傳送的兩個免費ARP之間的延遲,可以精確到毫秒級(預設是0)
    vrrp_mcast_group4 225.0.0.18 # IPV4多播地址,預設224.0.0.18,要改一改
    # 可以在多播地址上抓包來看vrrp報文:tcpdump -i ens33 -nn host 224.0.0.18
}

2)vrrp例項配置

### VRRP例項配置 ###
vrrp_instance NAME {
    state MASTER          # 定義例項的角色狀態是master還是backup,在當前VRRP例項中此節點的初始狀態
    interface eth0        # 定義vrrp繫結的介面,即接收或傳送心跳通告的介面,即HA監測介面
    virtual_router_id 51  # 虛擬路由標識(VRID),同一例項該數值必須相同,即master和backup中該值要相同
                               # 同一網路卡上的不同vrrp例項,該值一定不能相同,取值範圍為0-255,預設為51
    priority 100          # 該vrrp例項中本機的keepalived的優先順序,優先順序最高的為master(可用範圍0-255)
                               # 該選項的優先順序高於state選項,
                               # 即若state指定的是backup,但這裡設定的值最高,則仍為master
    advert_int 1          # 心跳資訊傳送和接收時間間隔,單位為秒

    authentication {      # 認證方式,同一例項中這個配置必須完全一樣才可通過認證,只建議使用PASS認證
        auth_type PASS         # 使用簡單字元認證的方式
        auth_pass 1111         # 最多支援8字元,超過8字元將只取前8字元
    }

    virtual_ipaddress {   # 設定的VIP,當master出現故障後,VIP會故障轉移到backup
                               # 這些vip預設配置在interface指定的介面別名上,可使用dev選項來指定配置介面
                               # 使用ip add的方式新增,若要被ifconfig檢視,在IP地址後加上label即可
       192.168.200.16 label eth0:1
       192.168.200.17
       192.168.200.19/24 dev eth1
       # 格式:<IPADDR>/<MASK> brd <IPADDR> dev <STRING> scope <SCOPE> label <LABEL>
    }

    # 使用非搶佔模式
    nopreempt   
         
    # 使用延遲搶佔模式
    preempt_delay  TIME     
}

3)定義通知指令碼

  • 定義格式:可以通過notify引數來實現master和backup的切換,且可以附加執行通知指令碼
    vrrp_instance {
        ...
        notify_master  <STRING>|<QUOTED-STRING>  # 當切換到master模式時,執行此指令碼
        notify_backup  <STRING>|<QUOTED-STRING>  # 當切換到backup模式時,執行此指令碼
        notify_fault  <STRING>|<QUOTED-STRING>   # 當切換到fault模式時,執行此指令碼
        notify  <STRING>|<QUOTED-STRING>
    }   
  • 定義示例
    vrrp_instance {
        ...
        notify_master "/etc/keepalived/notify.sh master"
        notify_backup "/etc/keepalived/notify.sh backup"
        notify_fault "/etc/keepalived/notify.sh fault"
    }
  • 指令碼示例
    #!/bin/bash
    # Author: hgzerowzh
    # Description: An notify script
    #
    contact='root@localhost'
    
    notify() {
            mailsubject="$(hostname) to be $1: vip floating"
            mailbody="$(date +'%F %H:%M:%S'): vrrp transition, $(hostname) changed to be $1"
            echo $mailbody | mail -s "$mailsubject" $contact
    }
    
    case $1 in
        master)
        notify master
        exit 0
        ;;
        backup)
        notify backup
        exit 0
        ;;
        fault)
        notify fault
        exit 0
        ;;
        *)
        echo "Usage: $(basename $0) {master|backup|fault}"
        exit 1
        ;;
    esac

3.5 雙主配置示例

1)配置圖示

 2)配置示例

### node1:###
    vrrp_instance VI_1 {
            state MASTER
            interface eno16777736
            virtual_router_id 101
            priority 100
            advert_int 1
            authentication {
                    auth_type PASS
                    auth_pass ZPNnTQ6F
            }
            virtual_ipaddress {
                    172.16.100.9/16
            }
    }
    vrrp_instance VI_2 {
            state BACKUP
            interface eno16777736
            virtual_router_id 102
            priority 99
            advert_int 1
            authentication {
                    auth_type PASS
                    auth_pass IWyijM5Q
            }
            virtual_ipaddress {
                    172.16.100.10/16
            }
    }                                
            
### node2:###
    vrrp_instance VI_1 {
            state BACKUP
            interface eno16777736
            virtual_router_id 101
            priority 99
            advert_int 1
            authentication {
                    auth_type PASS
                    auth_pass ZPNnTQ6F
            }
            virtual_ipaddress {
                    172.16.100.9/16
            }
    }
    vrrp_instance VI_2 {
            state MASTER
            interface eno16777736
            virtual_router_id 102
            priority 100
            advert_int 1
            authentication {
                    auth_type PASS
                    auth_pass IWyijM5Q
            }
            virtual_ipaddress {
                    172.16.100.10/16
            }
    }    

4. keepalived中配置ipvs

4.1 ipvs配置語法格式

1)定義Virtual Server

virutal_server  vip  port  {  # 虛擬服務地址和埠,使用空格分隔,其中地址為VIP
       ...
}

virtual_server fwmark int  {  # 可以使用防火牆標記來定義
        ...
}
        
### 常用的引數 ###
    delay_loop  <INT>                       # 對後端主機做檢測,每隔多長時間發一次請求
    lb_algo   rr|wrr|lc|wlc|lblc|sh|dh      # 排程演算法
    lb_kind   NAT|DR|TUN                    # 叢集型別
    persistence_timeout  <INT>              # 持久連線時長
    protocol TCP                            # 1.3.0版本之前只支援TCP
    sorry_server  <IPADDR>  <PORT>          # 當所有的RS都掛掉,則使用這裡定義的主機提供服務     

2)定義Real Server & 健康狀態檢測

real_server <IPADDR> <PORT>  {
    ### 常用的引數 ###
    weight <INT>                          # 權重
    notify_up  <STRING>|<QUOTED-STRING>   # 上線指令碼
    notify_down  <STRING>|<QUOTED-STRING> # 下線指令碼
    ...

    ### 健康狀態檢測機制(web應用層檢測)
    HTTP_GET|SSL_GET
    {
         # 檢測引數
         url  {     
                 path  <STRING>        # 對哪個url做檢測,使用path指明url
                 status_code <INT>     # 要獲得什麼響應碼才算正確
                 digest <STRING>       # 獲取內容的校驗碼跟所期望的一樣 
         }
         nb_get_retry <INT>            # get請求的重試次數
         delay_before_retry <INT>      # 兩次重試之間的時間間隔
         connect_timeout <INTEGER>     # 連線超時時長,預設為5s
         warmup <INT>                  # 健康狀態檢測延遲
    }
    
    ### 傳輸層健康狀態檢測(tcp協議層)
    TCP_CHECK
    {
         # 檢測引數
         connect_timeout  <INTEGER>    # 每次發起連線時的超時時間
         
         nb_get_retry <INT>            # get請求的重試次數
         delay_before_retry <INT>      # 兩次重試之間的時間間隔
         connect_timeout <INTEGER>     # 連線超時時長,預設為5s
         warmup <INT>                  # 健康狀態檢測延遲
         
         # 其它引數
         connect_ip <IP ADDRESS>       # 向哪個地址的哪個埠做檢測
         connect_port <PORT>
         bindto <IP ADDRESS>           # 自己使用固定的地址當源地址發請求
         bind_port <PORT>
    }
}

4.2 keepalived + LVS(NAT)

1)主節點的配置

! Configuration File for keepalived

global_defs {
   notification_email {
     492540654@qq.com
     2469822904@qq.com
   }
   notification_email_from hgzero@localhost
   smtp_server localhost
   smtp_connect_timeout 30
   router_id c7_node_03
   vrrp_skip_check_adv_addr
   ! vrrp_strict
   vrrp_garp_interval 0
   vrrp_gna_interval 0
   vrrp_mcast_group4 225.0.0.18
}

vrrp_instance VI_1 {
    state MASTER
    interface ens37
    virtual_router_id 66
    priority 100
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass niba
    }
    virtual_ipaddress {  
       172.168.1.99/24   # 這個虛擬ip是流動閘道器地址
    }
}

vrrp_instance VI_2 {
    state MASTER
    interface ens33
    virtual_router_id 67
    priority 100
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass taba
    }
    virtual_ipaddress {
       10.0.0.11/24      # 這個虛擬ip是外網訪問的浮動ip
    } 
}

# 將VI_1和VI_2做成一個同步組,在這個節點上,VI_1和VI_2同進退
vrrp_sync_group VG_1 {   
    group {
        VI_1
        VI_2
    }
}

# 虛擬服務地址和埠,使用空格分隔,其中地址為外網VIP
virtual_server  10.0.0.11 80 {  
    delay_loop 2              # 健康檢查時間間隔
    lb_algo rr                # 定義負載均衡LB的演算法,這裡使用的是rr輪詢排程演算法
    lb_kind NAT               # lvs的模型,有NAT、DR、TUN三種
    ! persistence_timeout 3   # 持久會話保持時長
    protocol TCP              # 監控服務的協議型別,1.3.0版本之前只支援tcp,之後還支援udp

    real_server 172.168.1.101 80 {  # 定義後端的real_server部分,地址和埠使用空格分隔
        weight 1              # lvs權重
        HTTP_GET {            # 監控狀況檢查的檢查方式,常見的有HTTP_GET、SSL_GET、TCP_CHECK、MISC_CHECK
            url {
              path /          # 指定http_get健康狀況檢查的路徑,例如檢查index.html是否正常
                  status_code 200
                         # 健康狀況需要狀態碼,可以是status_code、digest、或者digest+status_code
                         # digest值用keepalived的genhash命令生成,一般使用status_code即可
                         # curl  -s  http://172.168.0.6 |  md5sum
                         # genhash -s 172.168.0.6 -p 80 -u /index.html
            }
            connect_timeout 2
            nb_get_retry 3
            delay_before_retry 1
        }
    }

    real_server 172.168.1.102 80 {
        weight 1
        HTTP_GET {
            url {
              path /
              status_code 200
            }
            connect_timeout 2     # 表示3秒無響應就超時,即此realserver不健康,需重試連線
            nb_get_retry 3        # 表示重試3次,3次之後都超時就是當機,防止誤傷(nb=number)
            delay_before_retry 1  # 重試的時間間隔
        }                         # 時間如果太久,應改小
    }
}

2)備節點的配置

! Configuration File for keepalived

global_defs {
   notification_email {
     492540654@qq.com
     2469822904@qq.com
   }
   notification_email_from hgzero@localhost
   smtp_server localhost
   smtp_connect_timeout 30
   router_id c7_node_04
   vrrp_skip_check_adv_addr
   ! vrrp_strict
   vrrp_garp_interval 0
   vrrp_gna_interval 0
   vrrp_mcast_group4 225.0.0.18

}

vrrp_instance VI_1 {
    state BACKUP
    interface ens37
    virtual_router_id 66
    priority 99
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass niba
    }
    virtual_ipaddress {
       172.168.1.99/24
    }
}

vrrp_instance VI_2 {
    state BACKUP
    interface ens33
    virtual_router_id 67
    priority 99
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass taba
    }
    virtual_ipaddress {
       10.0.0.11/24
    }
}

vrrp_sync_group VG_1 {
    group {
        VI_1
        VI_2
    }        
}

virtual_server  10.0.0.11 80 {
    delay_loop 2
    lb_algo rr
    lb_kind NAT
    ! persistence_timeout 3
    protocol TCP

    real_server 172.168.1.101 80 {
        weight 1
        HTTP_GET {
            url {
              path /
              status_code 200
            }
            connect_timeout 2
            nb_get_retry 3
            delay_before_retry 1
        }
    }

    real_server 172.168.1.102 80 {
        weight 1
        HTTP_GET {
            url {
              path /
              status_code 200
            }
            connect_timeout 2
            nb_get_retry 3
            delay_before_retry 1
        }
    }
}

4.3 keepalived + LVS(DR)

1)主節點的配置

! Configuration File for keepalived

global_defs {
   notification_email {
     492540654@qq.com
     2469822904@qq.com
   }
   notification_email_from hgzero@localhost
   smtp_server localhost
   smtp_connect_timeout 30
   router_id c7_node_03
   vrrp_skip_check_adv_addr
   ! vrrp_strict
   vrrp_garp_interval 0
   vrrp_gna_interval 0
   vrrp_mcast_group4 225.0.0.16
}

vrrp_instance VI_1 {
    state MASTER
    interface ens33
    virtual_router_id 66
    priority 100
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass niba
    }
    virtual_ipaddress {
       10.0.0.10
    }
}

virtual_server  10.0.0.10 80 {
    delay_loop 2
    lb_algo wrr
    lb_kind DR
    ! persistence_timeout 3
    protocol TCP

    real_server 10.0.0.205 80 {
        weight 2
        HTTP_GET {
            url {
              path /
              status_code 200
            }
            connect_timeout 2
            nb_get_retry 3
            delay_before_retry 1
        }
    }

    real_server 10.0.0.206 80 {
        weight 1
        HTTP_GET {
            url {
              path /
              status_code 200
            }
            connect_timeout 2
            nb_get_retry 3
            delay_before_retry 1
        }
    }
}

2)備節點的配置

! Configuration File for keepalived

global_defs {
   notification_email {
     492540654@qq.com
     2469822904@qq.com
   }
   notification_email_from hgzero@localhost
   smtp_server localhost
   smtp_connect_timeout 30
   router_id c7_node_04
   vrrp_skip_check_adv_addr
   ! vrrp_strict
   vrrp_garp_interval 0
   vrrp_gna_interval 0
   vrrp_mcast_group4 225.0.0.16
}

vrrp_instance VI_1 {
    state BACKUP
    interface ens33
    virtual_router_id 66
    priority 99
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass niba
    }
    virtual_ipaddress {
       10.0.0.10
    }
}

virtual_server  10.0.0.10 80 {
    delay_loop 2
    lb_algo wrr
    lb_kind DR
    ! persistence_timeout 3
    protocol TCP

    real_server 10.0.0.205 80 {
        weight 2
        HTTP_GET {
            url {
              path /
              status_code 200
            }
            connect_timeout 2
            nb_get_retry 3
            delay_before_retry 1
        }
    }

    real_server 10.0.0.206 80 {
        weight 1
        HTTP_GET {
            url {
              path /
              status_code 200
            }
            connect_timeout 2
            nb_get_retry 3
            delay_before_retry 1
        }
    }
}

3)在DR模式中各個Real Server上的自定義指令碼

  • 要在每個Real Server上執行此指令碼
#!/bin/bash

vip=10.0.0.10
mask='255.255.255.255'

case $1 in
start)
    echo 1 > /proc/sys/net/ipv4/conf/all/arp_ignore
    echo 1 > /proc/sys/net/ipv4/conf/lo/arp_ignore
    echo 2 > /proc/sys/net/ipv4/conf/all/arp_announce
    echo 2 > /proc/sys/net/ipv4/conf/lo/arp_announce
    ifconfig lo:0 $vip netmask $mask broadcast $vip up
    route add -host $vip dev lo:0
    ;;
stop)
    ifconfig lo:0 down
    echo 0 > /proc/sys/net/ipv4/conf/all/arp_ignore
    echo 0 > /proc/sys/net/ipv4/conf/lo/arp_ignore
    echo 0 > /proc/sys/net/ipv4/conf/all/arp_announce
    echo 0 > /proc/sys/net/ipv4/conf/lo/arp_announce
    ;;
*) 
    echo "Usage $(basename $0) start|stop"
    exit 1
    ;;
esac

5. keepalived高可用nginx

5.1 keepalived高可用其他服務

1)原理

  • keepalived呼叫外部的輔助指令碼進行資源監控,並根據監控的結果狀態能實現優先動態調整

2)步驟

  • 定義一個指令碼
    vrrp_script  <SCRIPT_NAME> {   # 指令碼名,後面要基於指令碼名來進行呼叫
            script  "/script.sh"   # 執行的命令或指令碼
            interval  INT          # 每隔多少時間,這個監控指令碼要執行一次
            weight   -INT          # 萬一失敗了,當前節點的權重要減去多少,一般來講講,減去後的值要小於備用節點
    }
  • 呼叫此指令碼
    # 在某個vrrp的示例中去呼叫指令碼例項
    track_script {
            SCRIPT_NAME_1
            SCRIPT_NAME_2
            ...
    }

5.2 keepalived高可用nginx

1)配置keepalived.conf檔案

global_defs {
    notification_email {
            root@localhost
    }
    notification_email_from  keepalived@localhost
    smtp_server 127.0.0.1
    smtp_connect_timeout 30
    router_id node1
    vrrp_mcast_group4 224.0.100.19
}

# 如果想要調整某個keepalived主機,只需要在keepalived目錄下建立一個down檔案
# 通過監測這個檔案的存在與否,即可將該節點權重降低,從而可以去配置調整它
# 如果不想讓它降權了,就將down檔案刪除
vrrp_script chk_down { 
    # 如果這個檔案存在就錯誤退出,否則就正常退出  
    script  "[[  -f /etc/keepalived/down  ]]  &&  exit 1  ||  exit 0"  
    # 注意,這裡最好將指令碼寫入shell檔案中,然後在這裡呼叫shell指令碼檔案,注意用全路徑
        interval 1          
        weight -5           # 一旦上面的檔案存在(錯誤退出),就將這個節點降權
        fall 1
        rise 1
}

vrrp_script chk_nginx {
    script  "killall  -0  nginx  &&  exit 0 ||  exit 1"  # 這裡killall -0表示檢測nginx程式是否存在
    # 注意,這裡最好將指令碼寫入shell檔案中,然後在這裡呼叫shell指令碼檔案,注意用全路徑
    interval  1             # 每隔一秒檢測一次上面的指令碼是否能成功執行
    weight  -5              # 如果指令碼執行失敗就將權重-2
    fall  3                 # 如果失敗3次失敗,才確認為失敗
    rise  3                 # 需要成功的次數,如果3次檢查都成功,那麼就立即將減去的權重加回去
}

vrrp_instance  VI_1 {
    state  MASTER
    interface eno16777736
    virtual_router_id 14
    priority  100
    advert_int  1
    authentication {
            auth_type  PASS
            auth_pass 571f97b2  # 如果有多個vrrp例項,這裡的密碼一定不能相同
    }
    vritual_ipaddress {
            10.1.0.93/16  dev  eno16777736
    }
    track_script {              # 在這裡來呼叫之前的指令碼
            chk_down
            chk_nginx
    }

    notify_master  "/etc/keepalived/notify.sh  master"
    notify_backup  "/etc/keepalived/notify.sh  backup"
    notify_fault   "/etc/keepalived/notify.sh  fault"
}

2)定義notify指令碼

#!/bin/bash
#
contact='root@localhost'
notify() {
        local  mailsubject="$(hostname) to be $1,  vip floating"
        local  mailbody="$(date  + '%F  %T' ): vrrp  transition, $(hostname)  changed  to  be  $1"
        echo "$mailbody"  |  mail  -s  "$mailsubject"  $contact
}

case  $1  in
master)
        # 噹噹前節點變成主節點的時候,就啟用nginx服務
        systemctl  start  nginx.service  
        notify  master
        ;;
backup)
        # 噹噹前節點變成備用節點的時候,要啟用nginx,防止備節點也被降權,導致vip沒有被轉移
        systemctl  start  nginx.service   
    notify  backup
        ;;
fault)
        # 噹噹前節點出錯時,就停掉nginx服務(但是如果做nginx的雙主,即使fault也不能停掉nginx)
        systemctl  stop  nginx.service  
        notify  fault
        ;;
*)
        echo  "Usage: $(basename  $0) { master|backup|fault}"
        exit  1
        ;;
esac

3)其他相關

# 監控關注的網路介面
    track_interface {
            IFACE_NAME_1
        IFACE_NAME_2
    }

# 在nginx上配置反向代理:
    upstream  websrvs  {
            server  192.168.10.11:80;
            server  192.168.10.12:80;
    }
    location  /  {
            proxy_pass  http:/websrvs;
    }

 

 

 

相關文章