kubernetes haproxy+keepalive实现master集群高可用
前言
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数据直接从这个连接走了。