Kubernetes高可用性的考虑
高可用性考虑因素
本文档包含了社区提供的关于设置高可用性Kubernetes集群的注意事项。如果有什么地方不完整、不清楚或者需要更多的信息,请随时留言。
概述
当创建生产集群时,高可用性是必须的(集群在某些控制平面或工作节点失效时仍能保持运行的能力)。对于工作节点,假设有足够多的节点。也要在规划和设置集群时,需要考虑到控制平面节点和etcd
实例的冗余。
kubeadm
支持设置多个控制平面
和多etcd
集群。 但仍有一些方面需要考虑和设置,这些方面并不是Kubernetes本身的一部分,因此项目文档中没有涉及。本文档提供了一些额外的信息和例子,在用kubeadm
规划和引导HA集群时很有用。
软件负载均衡的选项
当创建一个具有多个控制平面的集群时,可以将API Server实例
放在负载均衡后面,可以在运行kubeadm init
时使用--control-plane-endpoint
选项让新集群使用它来实现更高的可用性。
当然,负载均衡器本身也应该是高度可用的。这通常是通过给负载均衡器增加冗余来实现的。为此,设置一个管理虚拟IP的主机集群,每台主机运行一个负载均衡器的实例,这样在其他主机处于待机状态时,总是使用当前持有vIP的主机上的负载均衡器。
在某些环境中,例如在具有专用负载均衡组件(例如由某些云提供商提供)的数据中心中,该功能可能已经可用。如果没有,可以使用用户管理的负载均衡。在这种情况下,在启动集群之前需要做一些准备工作。
由于这不是Kubernetes或kubeadm
的一部分,所以必须单独处理。在下面的章节中,我们给出了一些例子,当然也有可能是其他几十种可能的配置。
keepalived 和 haproxy
对于从虚拟IP提供负载均衡,keepalived和haproxy的组合已经存在了很长时间,可以说是众所周知、久经考验。
keepalived
提供了一个由可配置的健康检查管理的虚拟IP。由于虚拟IP的实施方式,协商虚拟IP的所有主机必须在同一IP子网中。haproxy
服务可以配置为简单的基于流的负载平衡,从而允许TLS终止由其后面的API服务器实例处理。
这种组合既可以作为操作系统上的服务运行,也可以作为控制平面主机上的静态Pods运行。两种情况下的服务配置是相同的。
keepalived配置
keepalived
配置由两个文件组成:服务配置文件和健康检查脚本,该脚本将定期被调用,以验证持有虚拟IP的节点是否仍在运行。
这些文件位于/etc/keepalived
目录中。但请注意,有些 Linux 发行版可能会把它们放在其他地方。下面的配置已经成功地用于keepalived
1.3.5版本。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
! /etc/keepalived/keepalived.conf ! Configuration File for keepalived global_defs { router_id LVS_DEVEL } vrrp_script check_apiserver { script "/etc/keepalived/check_apiserver.sh" interval 3 weight -2 fall 10 rise 2 } vrrp_instance VI_1 { state ${STATE} interface ${INTERFACE} virtual_router_id ${ROUTER_ID} priority ${PRIORITY} authentication { auth_type PASS auth_pass ${AUTH_PASS} } virtual_ipaddress { ${APISERVER_VIP} } track_script { check_apiserver } } |
bash
变量样式中有一些占位符需要填写:
${STATE}
设置一个主机是MASTER
,其他主机是BACKUP
,因此虚拟IP最初将分配给MASTER
。${INTERFACE}
是参与协商虚拟IP的网络接口,例如eth0
。${ROUTER_ID}
对于所有keepalived
集群主机来说,应该是相同的,同时在同一子网的所有集群中是唯一的。许多发行版将其值预先配置为51
。${PRIORITY}
master上的优先级应高于backups。因此,101
和100
就足够了。${AUTH_PASS}
对所有keepalived
集群主机而言,应该是相同的,例如42
。${APISERVER_VIP}
是keepalived
集群主机之间协商的虚拟IP地址。
上面的 keepalived
配置使用了一个健康检查脚本/etc/keepalived/check_apiserver.sh
,负责确保在持有虚拟IP的节点上,API服务器是可用的。这个脚本可以是这样的。
1 2 3 4 5 6 7 8 9 10 11 |
#!/bin/sh errorExit() { echo "*** $*" 1>&2 exit 1 } curl --silent --max-time 2 --insecure https://localhost:${APISERVER_DEST_PORT}/ -o /dev/null || errorExit "Error GET https://localhost:${APISERVER_DEST_PORT}/" if ip addr | grep -q ${APISERVER_VIP}; then curl --silent --max-time 2 --insecure https://${APISERVER_VIP}:${APISERVER_DEST_PORT}/ -o /dev/null || errorExit "Error GET https://${APISERVER_VIP}:${APISERVER_DEST_PORT}/" fi |
bash
变量样式中有一些占位符需要填写:
${APISERVER_VIP}
是keepalived
集群主机之间协商的虚拟IP地址。${APISERVER_DEST_PORT}
Kubernetes与API服务器对话的端口。
haproxy配置
haproxy
配置由一个文件组成:服务配置文件,它在/etc/haproxy
目录中。但请注意,有些Linux发行版可能会把它们放在其他地方。以下配置已经成功地用于haproxy
2.1.4版本
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 |
# /etc/haproxy/haproxy.cfg #--------------------------------------------------------------------- # Global settings #--------------------------------------------------------------------- global log /dev/log local0 log /dev/log local1 notice daemon #--------------------------------------------------------------------- # common defaults that all the 'listen' and 'backend' sections will # use if not designated in their block #--------------------------------------------------------------------- defaults mode http log global option httplog option dontlognull option http-server-close option forwardfor except 127.0.0.0/8 option redispatch retries 1 timeout http-request 10s timeout queue 20s timeout connect 5s timeout client 20s timeout server 20s timeout http-keep-alive 10s timeout check 10s #--------------------------------------------------------------------- # apiserver frontend which proxys to the masters #--------------------------------------------------------------------- frontend apiserver bind *:${APISERVER_DEST_PORT} mode tcp option tcplog default_backend apiserver #--------------------------------------------------------------------- # round robin balancing for apiserver #--------------------------------------------------------------------- backend apiserver option httpchk GET /healthz http-check expect status 200 mode tcp option ssl-hello-chk balance roundrobin server ${HOST1_ID} ${HOST1_ADDRESS}:${APISERVER_SRC_PORT} check # [...] |
同样,在bash
变量样式中有一些占位符需要替换:
${APISERVER_DEST_PORT}
Kubernetes与API服务器对话的端口。${APISERVER_SRC_PORT}
API服务器实例使用的端口。${HOST1_ID}
第一个负载均衡的API服务器主机的符号名称。${HOST1_ADDRESS}
第一个负载均衡API服务器主机的可解析地址(DNS名、IP地址)。- 额外的
server
行,每一个负载平衡的API服务器主机。
Option 1: 在操作系统上运行服务
为了在操作系统上运行这两个服务,可以使用各自发行版的包管理器来安装。如果它们将在不属于Kubernetes集群的专用主机上运行,这可能是有意义的(因为可以在k8s内运行)。
安装好上述配置后,就可以启用和启动服务了。在基于RedHat的最新系统中,将使用systemd
来实现。
1 2 |
# systemctl enable haproxy --now # systemctl enable keepalived --now |
有了服务,现在可以使用kubeadm init
来启动Kubernetes集群了。
Option 2: 以静态 pods 运行服务
如果 keepalived
和 haproxy
将在控制平面节点上运行,它们可以被配置为静态pods运行。这里需要做的就是在引导集群之前,将各自的清单文件放在/etc/kubernetes/manifests
目录中。在引导过程中,kubelet
会将这些进程带上来,这样集群在启动时就可以使用它们。这是一个优雅的解决方案,特别是与堆栈控制平面和etcd节点下描述的设置。
对于这个设置,需要在/etc/kubernetes/manifests
中创建两个清单文件(先创建目录)。
keepalived
的清单, /etc/kubernetes/manifests/keepalived.yaml
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
apiVersion: v1 kind: Pod metadata: creationTimestamp: null name: keepalived namespace: kube-system spec: containers: - image: osixia/keepalived:1.3.5-1 name: keepalived resources: {} securityContext: capabilities: add: - NET_ADMIN - NET_BROADCAST - NET_RAW volumeMounts: - mountPath: /usr/local/etc/keepalived/keepalived.conf name: config - mountPath: /etc/keepalived/check_apiserver.sh name: check hostNetwork: true volumes: - hostPath: path: /etc/keepalived/keepalived.conf name: config - hostPath: path: /etc/keepalived/check_apiserver.sh name: check status: {} |
haproxy
的清单, /etc/kubernetes/manifests/haproxy.yaml
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
apiVersion: v1 kind: Pod metadata: name: haproxy namespace: kube-system spec: containers: - image: haproxy:2.1.4 name: haproxy livenessProbe: failureThreshold: 8 httpGet: host: localhost path: /healthz port: ${APISERVER_DEST_PORT} scheme: HTTPS volumeMounts: - mountPath: /usr/local/etc/haproxy/haproxy.cfg name: haproxyconf readOnly: true hostNetwork: true volumes: - hostPath: path: /etc/haproxy/haproxy.cfg type: FileOrCreate name: haproxyconf status: {} |
请注意,这里同样需要填写一个占位符。${APISERVER_DEST_PORT}
需要与/etc/haproxy/haproxy.cfg
中的值相同(见上文)。
这个组合已经成功地用于例子中使用的版本。其他版本可能也可以使用,或者需要修改配置文件。
有了服务,现在可以使用kubeadm init
来启动Kubernetes集群了。
kube-vip
作为”传统”的keepalived
和haproxy
方法的替代方案,kube-vip在一个服务中实现了虚拟IP的管理和负载平衡。与上述方案2类似,”kube-vip “将作为控制平面节点上的静态pod运行。
与 keepalived
一样,协商虚拟IP的主机需要在同一个IP子网中。同样,和haproxy
一样,基于流的负载均衡允许TLS终止由后面的API Server实例处理。
配置文件/etc/kube-vip/config.yaml
是这样的:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
localPeer: id: ${ID} address: ${IPADDR} port: 10000 remotePeers: - id: ${PEER1_ID} address: ${PEER1_IPADDR} port: 10000 # [...] vip: ${APISERVER_VIP} gratuitousARP: true singleNode: false startAsLeader: ${IS_LEADER} interface: ${INTERFACE} loadBalancers: - name: API Server Load Balancer type: tcp port: ${APISERVER_DEST_PORT} bindToVip: false backends: - port: ${APISERVER_SRC_PORT} address: ${HOST1_ADDRESS} # [...] |
“bash”式的占位符如下:
${ID}
当前主机的符号名称。${IPADDR}
当前主机的IP地址。${PEER1_ID}
第一个vIP对等体的符号名称。${PEER1_IPADDR}
第一个vIP同伴的IP地址。- 其他vIP对等体的条目(
id
,address
,port
)可以按照以下步骤进行。 ${APISERVER_VIP}
是kube-vip
集群主机之间协商的虚拟IP地址。${IS_LEADER}
对一个leader来说是true
,对其余的来说是false
。${INTERFACE}
是参与协商虚拟IP的网络接口,例如eth0
。${APISERVER_DEST_PORT}
Kubernetes与API服务器对话的端口。${APISERVER_SRC_PORT}
API服务器实例使用的端口。${HOST1_ADDRESS}
第一个负载均衡API服务器主机的IP地址。- 附加的负载平衡API服务器主机的条目(
port
、address
)可以如下所示
为了让服务与集群一起启动,现在需要将清单kube-vip.yaml
放在/etc/kubernetes/manifests
中(先创建目录)。可以使用kube-vip
docker镜像生成。
1 2 3 |
# docker run -it --rm plndr/kube-vip:0.1.1 /kube-vip sample manifest \ | sed "s|plndr/kube-vip:'|plndr/kube-vip:0.1.1'|" \ | sudo tee /etc/kubernetes/manifests/kube-vip.yaml |
结果,/etc/kubernetes/manifests/kube-vip.yaml
,会像这样:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
apiVersion: v1 kind: Pod metadata: creationTimestamp: null name: kube-vip namespace: kube-system spec: containers: - command: - /kube-vip - start - -c - /vip.yaml image: 'plndr/kube-vip:0.1.1' name: kube-vip resources: {} securityContext: capabilities: add: - NET_ADMIN - SYS_TIME volumeMounts: - mountPath: /vip.yaml name: config hostNetwork: true volumes: - hostPath: path: /etc/kube-vip/config.yaml name: config status: {} |
有了服务,现在可以使用kubeadm init
来启动Kubernetes集群。
引导集群
现在可以按照使用 kubeadm 创建 k8s)中的描述进行集群安装了。
请注意,如果${APISERVER_DEST_PORT}
在上面的配置中被配置为与6443
不同的值,需要告诉kubeadm init
为API服务器使用该端口。假设在一个新的集群中,API服务器的负载均衡端口为8443,虚拟IP的DNS名称为vip.mycluster.local
,则需要向kubeadm
传递一个参数--control-plan-endpoint
,如下所示。
1 |
kubeadm init --control-plane-endpoint vip.mycluster.local:8443 [additional arguments ...] |
FROM: https://www.orchome.com/10034
0 Comments