kubernetes-handbook/practice/master-ha.md

179 lines
8.9 KiB
Markdown
Raw Blame History

This file contains invisible Unicode characters!

This file contains invisible Unicode characters that may be processed differently from what appears below. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to reveal hidden characters.

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

# Master 节点高可用
经过部署 Kubernetes 集群章节我们已经可以顺利的部署一个集群用于开发和测试,但是要应用到生产就就不得不考虑 master 节点的高可用问题,因为现在我们的 master 节点上的几个服务 `kube-apiserver`、`kube-scheduler` 和 `kube-controller-manager` 都是单点的而且都位于同一个节点上,一旦 master 节点宕机,虽然不应答当前正在运行的应用,将导致 kubernetes 集群无法变更。本文将引导你创建一个高可用的 master 节点。
在大神 gzmzj 的 ansible 创建 kubernetes 集群神作中有讲到如何配置多个 Master但是在实践过程中还是遇到不少坑。需要将坑填上才能工作。 参考[集群规划和基础参数设定](https://github.com/mendickxiao/kubeasz/blob/master/docs/00-集群规划和基础参数设定.md)。
按照神作的描述,实际上是通过 keepalived + haproxy 实现的,其中 keepalived 是提供一个 VIP通过 VIP 关联所有的 Master 节点;然后 haproxy 提供端口转发功能。由于 VIP 还是存在 Master 的机器上的,默认配置 API Server 的端口是 6443所以我们需要将另外一个端口关联到这个 VIP 上,一般用 8443。
![Master HA架构图](../images/master-ha.JPG)
根据参考文章的实践我发现需要在Master手工安装keepalived, haproxy。
```bash
yum install keepalived
yum install haproxy
```
需要将 HAProxy 默认的配置文件 balance 从 source 修改为 `roundrobin` 方式。haproxy 的配置文件 `haproxy.cfg` 默认路径是 `/etc/haproxy/haproxy.cfg`。另外需要手工创建 `/run/haproxy` 的目录,否则 haproxy 会启动失败。
**注意**
- bind 绑定的就是 VIP 对外的端口号,这里是 8443。
- balance 指定的负载均衡方式是 `roundrobin` 方式,默认是 source 方式。在我的测试中source 方式不工作。
- server 指定的就是实际的 Master 节点地址以及真正工作的端口号,这里是 6443。有多少台 Master 就写多少条记录。
```ini
# haproxy.cfg sample
global
log /dev/log local0
log /dev/log local1 notice
       chroot /var/lib/haproxy
       *stats socket /run/haproxy/admin.sock mode 660 level admin
stats timeout 30s
user haproxy
group haproxy
daemon
nbproc 1
defaults
log global
timeout connect 5000
timeout client 50000
timeout server 50000
listen kube-master
**bind 0.0.0.0:8443**
mode tcp
option tcplog
**balance roundrobin**
       server s1 **Master 1的IP地址**:6443 check inter 10000 fall 2 rise 2 weight 1
       server s2 **Master 2的IP地址**:6443 check inter 10000 fall 2 rise 2 weight 1
```
修改 keepalived 的配置文件,配置正确的 VIP。keepalived 的配置文件 `keepalived.conf` 的默认路径是 `/etc/keepalived/keepalived.conf`
**注意**
- priority 决定哪个 Master 是主,哪个 Master 是次。数字大的是主,数字小的是次。数字越大优先级越高。
- `virtual_router_id` 决定当前 VIP 的路由号,实际上 VIP 提供了一个虚拟的路由功能,该 VIP 在同一个子网内必须是唯一。
- virtual_ipaddress 提供的就是 VIP 的地址,该地址在子网内必须是空闲未必分配的。
- `state` 决定初始化时节点的状态,建议 `priority` 最高的节点设置为 `MASTER`
```ini
# keepalived.cfg sample
global_defs {
router_id lb-backup
}
vrrp_instance VI-kube-master {
state BACKUP
**priority 110**
dont_track_primary
interface eth0
**virtual_router_id 51**
advert_int 3
virtual_ipaddress {
**10.86.13.36**
}
}
```
配置好后,那么先启动主 Master 的 keepalived 和 haproxy。
```bash
systemctl enable keepalived
systemctl start keepalived
systemctl enable haproxy
systemctl start haproxy
```
然后使用 ip a s 命令查看是否有 VIP 地址分配。如果看到 VIP 地址已经成功分配在 eth0 网卡上,说明 keepalived 启动成功。
```bash
[root@kube32 ~]# ip a s
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP qlen 1000
link/ether 00:50:56:a9:d5:be brd ff:ff:ff:ff:ff:ff
inet 10.86.13.32/23 brd 10.86.13.255 scope global eth0
valid_lft forever preferred_lft forever
**inet 10.86.13.36/32 scope global eth0**
valid_lft forever preferred_lft forever
inet6 fe80::250:56ff:fea9:d5be/64 scope link
valid_lft forever preferred_lft forever
```
更保险方法还可以通过 `systemctl status keepalived -l` 看看 keepalived 的状态
```bash
[root@kube32 ~]# systemctl status keepalived -l
● keepalived.service - LVS and VRRP High Availability Monitor
Loaded: loaded (/usr/lib/systemd/system/keepalived.service; enabled; vendor preset: disabled)
Active: active (running) since Thu 2018-02-01 10:24:51 CST; 1 months 16 days ago
Main PID: 13448 (keepalived)
Memory: 6.0M
CGroup: /system.slice/keepalived.service
├─13448 /usr/sbin/keepalived -D
├─13449 /usr/sbin/keepalived -D
└─13450 /usr/sbin/keepalived -D
Mar 20 04:51:15 kube32 Keepalived_vrrp[13450]: VRRP_Instance(VI-kube-master) Dropping received VRRP packet...
**Mar 20 04:51:18 kube32 Keepalived_vrrp[13450]: (VI-kube-master): ip address associated with VRID 51 not present in MASTER advert : 10.86.13.36
Mar 20 04:51:18 kube32 Keepalived_vrrp[13450]: bogus VRRP packet received on eth0 !!!**
```
然后通过 systemctl status haproxy -l 看 haproxy 的状态
```bash
[root@kube32 ~]# systemctl status haproxy -l
● haproxy.service - HAProxy Load Balancer
Loaded: loaded (/usr/lib/systemd/system/haproxy.service; enabled; vendor preset: disabled)
Active: active (running) since Thu 2018-02-01 10:33:22 CST; 1 months 16 days ago
Main PID: 15116 (haproxy-systemd)
Memory: 3.2M
CGroup: /system.slice/haproxy.service
├─15116 /usr/sbin/haproxy-systemd-wrapper -f /etc/haproxy/haproxy.cfg -p /run/haproxy.pid
├─15117 /usr/sbin/haproxy -f /etc/haproxy/haproxy.cfg -p /run/haproxy.pid -Ds
└─15118 /usr/sbin/haproxy -f /etc/haproxy/haproxy.cfg -p /run/haproxy.pid -Ds
```
这个时候通过 kubectl version 命令,可以获取到 kubectl 的服务器信息。
```bash
[root@kube32 ~]# kubectl version
**Client Version: version.Info{Major:"1", Minor:"9", GitVersion:"v1.9.1", GitCommit:"3a1c9449a956b6026f075fa3134ff92f7d55f812", GitTreeState:"clean", BuildDate:"2018-01-03T22:31:01Z", GoVersion:"go1.9.2", Compiler:"gc", Platform:"linux/amd64"}
Server Version: version.Info{Major:"1", Minor:"9", GitVersion:"v1.9.1", GitCommit:"3a1c9449a956b6026f075fa3134ff92f7d55f812", GitTreeState:"clean", BuildDate:"2018-01-03T22:18:41Z", GoVersion:"go1.9.2", Compiler:"gc", Platform:"linux/amd64"}**
```
这个时候说明你的 keepalived 和 haproxy 都是成功的。这个时候你可以依次将你其他 Master 节点的 keepalived 和 haproxy 启动。 此时,你通过 ip a s 命令去查看其中一台 Master*非主 Master*)的时候,你看不到 VIP这个是正常的因为 VIP 永远只在主 Master 节点上,只有当主 Master 节点挂掉后,才会切换到其他 Master 节点上。
```bash
[root@kube31 ~]# ip a s
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP qlen 1000
link/ether 00:50:56:a9:07:23 brd ff:ff:ff:ff:ff:ff
inet 10.86.13.31/23 brd 10.86.13.255 scope global eth0
valid_lft forever preferred_lft forever
inet6 fe80::250:56ff:fea9:723/64 scope link
valid_lft forever preferred_lft forever
```
在我的实践过程中,通过大神的脚本快速启动多个 Master 节点,会导致主 Master 始终获取不了 VIP当时的报错非常奇怪。后来经过我的研究发现主 Master 获取 VIP 是需要时间的,如果多个 Master 同时启动,会导致冲突。这个不知道是否算是 Keepalived 的 Bug。但是最稳妥的方式还是先启动一台主 Master等 VIP 确定后再启动其他 Master 比较靠谱。
Kubernetes 通过 Keepalived + Haproxy 实现多个 Master 的高可用部署,你实际上可以采用其他方式,如外部的负载均衡方式。实际上 Kubernetes 的多个 Master 是没有主从的都可以提供一致性服务。Keepalived + Haproxy 实际上就是提供了一个简单的负载均衡方式。
---
注:本文来自 [mendickxiao](https://github.com/mendickxiao) 的贡献。