前言
master的HA,實際是apiserver的HA。Master的其他組件controller-manager、scheduler都是可以通過etcd做選舉(--leader-elect),而APIServer設計的就是可擴展性,所以做到APIServer很容易,只要前面加一個負載均衡輪訓轉發請求即可。下面簡單描述下haproxy和keepalive。
注意⚠️便於大家使用,所以先碼部署,有興趣的可以看下后面的原理。
一、實操篇
1. haproxy部署
1.1. 安裝haproxy
yum -y install haproxy
生產環境可以用二進制包部署
1.2. 修改配置文件
cp /etc/haproxy/haproxy.cfg /etc/haproxy/haproxy.cfg-back
vim /etc/haproxy/haproxy.cfg
global
log 127.0.0.1 local2
chroot /var/lib/haproxy
pidfile /var/run/haproxy.pid
maxconn 4000
user haproxy
group haproxy
daemon
stats socket /var/lib/haproxy/stats
defaults
mode tcp
log global
option httplog
option dontlognull
option http-server-close
option forwardfor except 127.0.0.0/8
option redispatch
retries 3
timeout http-request 10s
timeout queue 1m
timeout connect 10s
timeout client 1m
timeout server 1m
timeout http-keep-alive 10s
timeout check 10s
maxconn 3000
frontend main *:16443
acl url_static path_beg -i /static /images /javascript /stylesheets
acl url_static path_end -i .jpg .gif .png .css .js
use_backend static if url_static
default_backend kube-apiserver
backend static
balance roundrobin
server static 127.0.0.1:4331 check
backend kube-apiserver
balance roundrobin
server k8s1-matser1 10.8.4.91:6443 check
server k8s1-matser2 10.8.4.92:6443 check
server k8s1-matser3 10.8.4.93:6443 check
⚠️注意
- defaults 模塊中的 mode http 要改為 tcp(或者在下面的 frontend 和 backend 模塊中單獨定義 mode tcp )如果不改,后續 kubectl get node 會處於 NotReady 狀態。
- frontend 端口需指定非 6443 端口,要不然其他 master 節點會啟動異常(如果 haproxy 單獨主機,則可用 6443 端口)
- 配置文件可以拷貝其他節點,配置文件保持一樣。
1.3.啟動haproxy
systemctl start haproxy && systemctl enable haproxy && systemctl status haproxy
2. keepalive部署
2.1. 安裝keepalive
yum install -y keepalived
2.2. 修改配置文件
cp /etc/keepalived/keepalived.conf /etc/keepalived/keepalived.conf-back
vim /etc/keepalived/keepalived.conf
! Configuration File for keepalived
global_defs {
router_id LVS_1
}
vrrp_instance VI_1 {
state MASTER
interface eth0
virtual_router_id 51
priority 100
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
10.8.4.55/24
}
}
⚠️注意
- global_defs 只保留 router_id(每個節點都不同);
- 修改 interface(vip綁定的網卡),及 virtual_ipaddress(vip地址及掩碼長度);
- 刪除后面的示例
- 其他節點只需修改 state 為 BACKUP,優先級 priority 低於100即可。
2.3. 啟動keeplive
systemctl start keepalived && systemctl enable keepalived && systemctl status keepalived
2.4. 查看狀態
ip addr show eth0
如圖
可以看到vip只在一台機器上;如果兩個機器都有vip,可能是防火牆攔截了vrrp協議。
二、概述篇(作者摘抄整理)
1.haproxy+keepalived實現高可用負載均衡
軟件負載均衡一般通過兩種方式來實現:基於操作系統的軟負載實現和基於第三方應用的軟負載實現。LVS就是基於Linux操作系統實現的一種軟負載,HAProxy就是開源的並且基於第三應用實現的軟負載。
HAProxy相比LVS的使用要簡單很多,功能方面也很豐富。當前,HAProxy支持兩種主要的代理模式:"tcp"也即4層(大多用於郵件服務器、內部協議通信服務器等),和7層(HTTP)。在4層模式 下,HAProxy僅在客戶端和服務器之間轉發雙向流量。7層模式下,HAProxy會分析協議,並且能通過允許、拒絕、交換、增加、修改或者刪除請求 (request)或者回應(response)里指定內容來控制協議,這種操作要基於特定規則。
1.1.Haproxy簡介
反向代理服務器,支持雙機熱備支持虛擬主機,但其配置簡單,擁有非常不錯的服務器健康檢查功能,當其代理的后端服務器出現故障, HAProxy會自動將該服務器摘除,故障恢復后再自動將該服務器加入。自1.3引入了frontend,backend;frontend根據任意 HTTP請求頭內容做規則匹配,然后把請求定向到相關的backend.
1.2.keepalived簡介
keepalived是一個類似於layer3, 4 & 5交換機制的軟件,也就是我們平時說的第3層、第4層和第5層交換。Keepalived的作用是檢測web服務器的狀態,如果有一台web服務器死機,或工作出現故障,Keepalived將檢測到,並將有故障的web服務器從系統中剔除,當web服務器工作正常后Keepalived自動將web服務器加入到服務器群中,這些工作全部自動完成,不需要人工干涉,需要人工做的只是修復故障的web服務器。
⚠️類似的HA工具還有heatbeat、drbd等,heatbeat、drbd配置都較為復雜。
1.2.1. keepalived理論工作原理
keepalived可提供vrrp以及health-check功能,可以只用它提供雙機浮動的vip(vrrp虛擬路由功能),這樣可以簡單實現一個雙機熱備高可用功能。
keepalived是一個類似於layer3, 4 & 5交換機制的軟件,也就是我們平時說的第3層、第4層和第5層交換。Keepalived的作用是檢測web 服務器的狀態。 Layer3,4&5工作在IP/TCP協議棧的IP層,TCP層,及應用層,原理分別如下:
- Layer3:Keepalived使用Layer3的方式工作式時,Keepalived會定期向服務器群中的服務器發送一個ICMP的數據包(既我們平時用的Ping程序),如果發現某台服務的IP地址沒有激活,Keepalived便報告這台服務器失效,並將它從服務器群中剔除,這種情況的典型例子是某台服務器被非法關機。Layer3的方式是以服務器的IP地址是否有效作為服務器工作正常與否的標准。
- Layer4:如果您理解了Layer3的方式,Layer4就容易了。Layer4主要以TCP端口的狀態來決定服務器工作正常與否。如web server的服務端口一般是80,如果Keepalived檢測到80端口沒有啟動,則Keepalived將把這台服務器從服務器群中剔除。
- Layer5:Layer5就是工作在具體的應用層了,比Layer3,Layer4要復雜一點,在網絡上占用的帶寬也要大一些。Keepalived將根據用戶的設定檢查服務器程序的運行是否正常,如果與用戶的設定不相符,則Keepalived將把服務器從服務器群中剔除。
vip即虛擬ip,是附在主機網卡上的,即對主機網卡進行虛擬,此IP仍然是占用了此網段的某個IP。
1.2.2.tcp層的keepalive原理(本文所用)
tcp的keepalive是側重在保持客戶端和服務端的連接,一方會不定期發送心跳包給另一方,當一方端掉的時候,沒有斷掉的定時發送幾次心跳包,如果間隔發送幾次,對方都返回的是RST,而不是ACK,那么就釋放當前鏈接。設想一下,如果tcp層沒有keepalive的機制,一旦一方斷開連接卻沒有發送FIN給另外一方的話,那么另外一方會一直以為這個連接還是存活的,幾天,幾月。那么這對服務器資源的影響是很大的。
tcp的keepalive就是為了檢測鏈接的可用性。主要調節的參數有三個:
- tcp_keepalive_time // 距離上次傳送數據多少時間未收到判斷為開始檢測
- tcp_keepalive_intvl // 檢測開始每多少時間發送心跳包
- tcp_keepalive_probes // 發送幾次心跳包對方未響應則close連接
基本上的流程:
- 在客戶端和服務端進行完三次握手之后,客戶端和服務端都處在ESTABLISH狀態,這個時候進行正常的PSH和ACK交互,但是一旦一方服務中斷了,另一方在距離上次PSH時間tcp_keepalive_time發現對方未發送數據,則開始心跳檢測。
- 心跳檢測實際就是發送一個PSH的空心跳包,這里說的空心跳包就是包的數據為空,但是TCP包的頭部的數據和標識和正常包一樣。如果這個包獲取到的是RST返回的話,下面就會繼續每隔tcp_keepalive_intval的時長發送一個空心跳包,如果tcp_keepalive_probes次心跳包對方都是返回RST而不是ACK,則心跳發起方就判斷這個連接已經失效,主動CLOST這個連接。
這三個參數可以每個TCP連接都不同,使用tcp設置變量的函數可以設置當前tcp連接的這三個對應的值。int setsockopt(int s, int level, int optname, const void *optval, socklen_t optlen)
⚠️ http層的keepalive原理
http的keep-alive一般我們都會帶上中間的橫杠,普通的http連接是客戶端連接上服務端,然后結束請求后,由客戶端或者服務端進行http連接的關閉。下次再發送請求的時候,客戶端再發起一個連接,傳送數據,關閉連接。這么個流程反復。但是一旦客戶端發送connection:keep-alive頭給服務端,且服務端也接受這個keep-alive的話,兩邊對上暗號,這個連接就可以復用了,一個http處理完之后,另外一個http數據直接從這個連接走了。