1.Kubernetes边缘节点的单点故障

经过前面几篇对Ingress的学习,我们已经可以在一个Kubernetes中部署nginx ingress,同时可以将集群中的两类服务HTTP和gRPC暴露到集群外部。 本篇将主要关注一下Bare metal环境下Kubernetes Ingress边缘节点高可用相关的问题。我们的线上环境并没有使用公有云,因此无法使用各种共有云提供的ingress controller。

在Bare metal环境中Kubernetes集群,nginx ingress controller负责将集群外部的流量接入到集群内。 实际中需要将边缘路由器或全局统一接入层的负载均衡器将到达公网ip的外网流量转发到nginx ingress controller所在Kubernetes节点(这里成为边缘节点edge节点)的内网ip上,外部通过域名访问集群中以ingress暴露的服务。

Bare metal环境的Ingress的实施往往采用下图所示的形式:

k8s-edge-node.jpg

Kubernetes的Node节点中的Edge节点用于接入集群外部的流量,nginx ingress controller被部署到edge节点上。通过边缘路由器,将公网ip上的流量转到edge节点上。 例如公网ip的80和443端口对应edge节点内网ip的80和443端口。

但是当前的方案中edge节点是存在单点故障的,如果这个edge节点宕机的话,整个Kubernetes集群将无法对集群外部提供服务(所有的ingress都将不可用)。

2.高可用的Kubernetes边缘节点

Kubernetes边缘节点上部署的nginx ingress controller实际上就是一个负载均衡器。因此可以通过热备的形式部署多个边缘节点,多个边缘节点争抢一个VIP的形式。 即基于Keepavlied实现边缘节点的高可用。

k8s-edge-node.jpg

如上图所示,部署了两个边缘节点192.168.61.11192.168.61.12。边缘路由器上公网ip映射到内网的VIP 192.168.61.10上。

3.我们的实践

Kubernetes有个Contrib的kube-keepalived-vip项目是专门来做这件事的,在这个项目中keepalived是以容器的形式部署。 但由于我们线上一些没有部署在Kubernetes的一些服务和中间件都是用ansible部署的,这其中已经包括了keepalived的ansible role(包含keepalived+nginx和keepavlied+haproxy)。 所以我们在做Kubernetes边缘节点的高可用时,直接使用已有的ansible role将keepavlied直接部署在边缘节点上,而不是运行到容器中。

3.1 测试环境

根据前面的内容,一个Kubernetes集群分为三种类型的节点,master节点、跑业务负载的node节点、用于将外部流量接入的边缘节点edge节点。

这里的测试环境只有两个节点:

1kubectl get node -o wide
2NAME      STATUS    ROLES     AGE       VERSION   INTERNAL-IP 
3node1     Ready     master    38d       v1.11.1   192.168.61.11
4node2     Ready     <none>    38d       v1.11.1   192.168.61.12

node1同时作为master、node和edge节点,node2同时作为node和edge节点。

3.2 调度nginx-ingress-controller到边缘节点

这个测试集群的nginx ingress是使用helm部署的,这里调整一下value file ingress-nginx.yaml的内容,externalIPs指定为192.168.61.10这个VIP以及所有边缘节点的内网ip,同时通过nodeAffinity将nginx-ingress-controller调度到集群中所有的边缘节点,这里是node1和node2。

 1controller:
 2  replicaCount: 2
 3  service:
 4    externalIPs:
 5      - 192.168.61.10
 6      - 192.168.61.11
 7      - 192.168.61.12
 8  affinity:
 9      nodeAffinity:
10          requiredDuringSchedulingIgnoredDuringExecution:
11            nodeSelectorTerms:
12            - matchExpressions:
13              - key: kubernetes.io/hostname
14                operator: In
15                values:
16                - node1
17                - node2
1helm upgrade nginx-ingress stable/nginx-ingress \
2 --namespace ingress-nginx \
3 --install \
4 -f ingress-nginx.yaml

3.3 在边缘节点上安装keepalived

接下来在所有边缘节点上安装keepalived和ipvsadmin。 ipvsadm是IPVS的管理命令,VIP由IPVS创建。

我们使用ansible完成各个边缘节点上keepalived的部署和配置。 这里将略过keepalived的安装过程。

各个边缘节点上的keepalived.conf配置如下:

 1! Configuration File for keepalived
 2
 3global_defs {
 4   router_id LVS_DEVEL
 5}
 6
 7vrrp_instance VI_1 {
 8    state MASTER
 9    interface eth0
10    virtual_router_id 51
11    priority 100
12    advert_int 1
13    authentication {
14        auth_type PASS
15        auth_pass 1111
16    }
17    virtual_ipaddress {
18        192.168.61.10
19    }
20}
21
22virtual_server 192.168.61.10 443 {
23    delay_loop 6
24    lb_algo loadbalance
25    lb_kind DR
26    nat_max 255.255.255.0
27    persistence_timeout 50
28    protocol TCP
29
30    real_server 192.168.61.11 443 {
31        weight 1
32        TCP_CHECK {
33          connect_timeout 3
34        }
35    }
36    real_server 192.168.61.12 443 {
37        weight 1
38        TCP_CHECK {
39          connect_timeout 3
40        }
41    }
42
43}

各个边缘节点上的keepalvied启动后,可以在某个边缘节点上运行下面的命令查看到该节点获取到了VIP:

 1ip addr sh etn0
 22: etn0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
 3    link/ether 08:00:27:7a:a0:d5 brd ff:ff:ff:ff:ff:ff
 4    inet 192.168.61.12/24 brd 192.168.61.255 scope global etn0
 5       valid_lft forever preferred_lft forever
 6    inet 192.168.61.10/32 scope global etn0
 7       valid_lft forever preferred_lft forever
 8    inet6 fe80::1f1d:9638:d8f5:c2a5/64 scope link
 9       valid_lft forever preferred_lft forever
10    inet6 fe80::3a95:48aa:a404:4275/64 scope link tentative dadfailed
11       valid_lft forever preferred_lft forever

下面模拟VIP所在边缘节点宕机,将该节点关机。此时在剩余边缘节点上查,确认VIP漂到了剩余边缘节点的某个节点上。

参考