码蚁

打码改变人生

使用 keepalived 部署高可用 Kubernetes Master

Posted at — Feb 15, 2017

前言

Keepalived 在双机热备的用途上使用广泛,适合在功能不需要太复杂的场合,它拥有心跳检测功能和快速切换。Kubernetes 是 Docker 的集群管理软件,无论功能性和管理的便利性都深得管理人员喜爱。但 Kubernetes Master 节默认是单节点,一旦失效则整个集群丧失管理能力。Master 高可用方案显的尤为重要,官方提供的方案是 Master 组件 Docker 化,使用 kubelet 进行守护。此文使用 Keepalived 构建高可用 Master 节点。

介绍

Kubernetes controller、scheduler 组件高可用在启动 controller、scheduler 时在 options 里面加入 --leader-elect=true 参数,确保同一时间仅仅有一个 controller 或者 scheduler 生效。

Kubernetes api-server 高可用则使用 KeepAlived 实现,并且需要 api-server 绑定 ip 为 0.0.0.0

KeepAlived 是一个高可用方案,通过 VIP(即虚拟 IP)和心跳检测来实现高可用。其原理是存在一组(两台)服务器,分别赋予 Master,Backup 两个角色,默认情况下Master会绑定VIP到自己的网卡上,对外提供服务。Master,Backup会在一定的时间间隔向对方发送心跳数据包来检测对方的状态,这个时间间隔一般为 2 秒钟,如果 Backup 发现 Master 宕机,那么 Backup 会发送 ARP 包到网关,把 VIP 绑定到自己的网卡,此时 Backup 对外提供服务,实现自动化的故障转移,当 Master 恢复的时候会重新接管服务。非常类似于路由器中的虚拟路由器冗余协议(VRRP)。

环境

开启路由转发

# 编辑配置文件
$ vi /usr/lib/sysctl.d/00-system.conf 

# 添加以下内容
net.ipv4.ip_forward = 1

# 验证并生效
$ sysctl -p

# 验证是否生效
$ cat /proc/sys/net/ipv4/ip_forward
1

安装配置 Keepalived

使用 yum 进行安装

$ yum install -y keepalived

Master 修改配置文件

# Keepalived 配置文件
$ vi /etc/keepalived/keepalived.conf
! Configuration File for keepalived

global_defs {

}

vrrp_script check_k8s {
    # 自身状态检测
    script "/etc/keepalived/chk_k8s_master.sh"
    interval 3
    weight 5
    }

vrrp_instance VI_1 {
    # 使用单播通信,默认是组播通信
    unicast_src_ip  10.78.170.65
    unicast_peer {
                    10.78.170.63
    }
    # 初始化状态
    state MASTER
    # 虚拟 ip 绑定的网卡
    interface ens32
    # 此 ID 要与 Backup 配置一致
    virtual_router_id 80
    # 默认启动优先级,要比 Backup 大点,但要控制量,保证自身状态监测生效
    priority 100
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 1111
    }
    virtual_ipaddress {
        # 虚拟 ip 地址
        10.78.170.101
    }
    track_script {
        check_k8s
    }
}

# 自身状态监测脚本,这里通过 api-server 是否在监听端口(9899 端口)来判断状态。
$ vi /etc/keepalived/chk_k8s_master.sh
#!/bin/bash

count=`ss -tnl | grep 9899 | wc -l`

if [ $count = 0 ]; then
    exit 1
else
    exit 0
fi

Backup 修改配置文件

# Keepalived 配置文件
$ vi /etc/keepalived/keepalived.conf
! Configuration File for keepalived

global_defs {

}

vrrp_script check_k8s {
    script "/etc/keepalived/chk_k8s_master.sh"
    interval 3
    weight 5
    }

vrrp_instance VI_1 {
    unicast_src_ip  10.78.170.63
    unicast_peer {
                    10.78.170.65
    }
    state BACKUP
    interface ens32
    virtual_router_id 80
    priority 99
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 1111
    }
    virtual_ipaddress {
        10.78.170.101
    }
    track_script {
        check_k8s
    }
    # 状态切换 执行脚本
    notify_backup "/etc/keepalived/back_k8s.sh"
}

# 自身状态监测脚本,这里通过 api-server 是否在监听端口(9899 端口)来判断状态。
$ vi /etc/keepalived/chk_k8s_master.sh 
#!/bin/bash

count=`ss -tnl | grep 9899 | wc -l`

if [ $count = 0 ]; then
    exit 1
else
    exit 0
fi

# 因我生产中 Master 节点又是 Minion,Backup 节点切换回 Backup 状态时,Kubelet 连接不会断开,需要重启 kubelet。编写此状态切换脚本
$ vi /etc/keepalived/back_k8s.sh
#!/bin/bash
systemctl stop kube-apiserver.service
sleep 5s
systemctl restart kube-kubelet.service
systemctl start kube-apiserver.service

启动和设置开机启动

# 启动
$ systemctl start keepalived.service

# 设置开机自启动
$ systemctl enable keepalived.service

# 查看日志
$ journalctl -f -u keepalived.service

Keepalived 验证

验证虚拟 IP

虚拟机 ip 地址使用 ifconfig -a 命令是查看不到,而要使用 ip addr 命令才能看到

$ ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN 
    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: ens32: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
    link/ether 00:50:56:bd:e7:03 brd ff:ff:ff:ff:ff:ff
    inet 10.78.170.65/24 brd 10.78.170.255 scope global ens32
       valid_lft forever preferred_lft forever
    inet 10.78.170.101/32 scope global ens32
       valid_lft forever preferred_lft forever
    inet6 fe80::250:56ff:febd:e703/64 scope link 
       valid_lft forever preferred_lft forever

验证 api-server 高可用

关闭 10.78.170.65 上的 api-server 进程,然后查看虚拟 ip 是否飘移到 10.78.170.63

$ ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN 
    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: ens32: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
    link/ether 00:50:56:bd:d2:4c brd ff:ff:ff:ff:ff:ff
    inet 10.78.170.63/24 brd 10.78.170.255 scope global ens32
       valid_lft forever preferred_lft forever
    inet 10.78.170.101/32 scope global ens32
       valid_lft forever preferred_lft forever
    inet6 fe80::250:56ff:febd:d24c/64 scope link 
       valid_lft forever preferred_lft forever

后记

Kubernetes 集群数据全部放置在 etcd 中,api-server 节点切换只要 Minion 节点连接正确则不会对集群产生任何影响。目前的配置考虑了 Master 主机掉电或损坏脱离网络的情况,以及 Kubernetes api-server 组件失效的因素。

comments powered by Disqus