Kubernetes Master High Availability 高级实践

才云科技云开源高级工程师唐继元受邀DBAplus社群,在线分享《Kubernetes Master High Availability 高级实践》,介绍如何构建Kubernetes Master High Availability环境。

以下是分享实录:

大家好,我是才云科技的唐继元,今天给大家带来一篇技术分享,本次分享我将为大家介绍如何构建Kubernetes Master High Availability环境。此次分享内容是我在工作中经验总结,如果有不正确的或者需要改进的地方,欢迎各位大神指正。
相信大家对容器、docker和kubernetes这些概念并不陌生。下面进入本次分享的正题。
Kubernetes作为容器编排管理系统,通过Scheduler、ReplicationController等组件实现了应用层的高可用,但是针对Kubernetes集群,还需要实现Master组件的高可用。
本次分享论述的Master高可用方案主要基于社区的高可用方案(链接)的实践,但是社区的高可用方案中采用的GCE的External Loadbalancer,并未论述如何实现External Loadbalancer,而且也并没有将Kubernetes集群组件容器化。所以,我们的高可用方案在社区高可用方案的基础之上进行了如下两个方面的提升:

第一,除了kubelet之外,Kubernetes所有组件容器化;
第二,通过haproxy和keepalived构建Loadbalancer实现Master的高可用。
下面我们分四个章节来详细论述Kubernetes Master High Availability环境的搭建。

  1. HA Master整体架构

  2. 核心技术点和难点

  3. 实践中的遇到的那些坑

  4. 社区关于HA Master的未来发展

HA Master整体架构

我们已经成功将支持Master High Availability的Kubernetes集群部署到企业私有云平台,底层采用的是Ubuntu 14.04操作系统。下面是一个典型的部署环境:

clipboard.png

Static Pods是由其所在节点上的kubelet直接管理,而不需要通过Apiserver来监视它们。Static Pods的资源类型只能是Pod,而且不与任何的Replication Controller相关联,它们完全由kubelet来监视,并且当它们异常停止的时候由该kubelet负责重启它们。

(haproxy, keepalived):这里表示我们将haproxy和keepalived放置在同一个pod中。

1.1.kubelet对static pod高可用的支持

我们需要为kubelet进程配置一个manifests监视目录:

--config=/etc/kubernetes/manifests

如果有新的yaml/manifest文件添加到该目录,kubelet则根据yaml/manifest文件创建一个新的static pod;

如果我们把某个yaml/manifest文件从该目录删除,kubelet则会删除由该yaml/manifest文件所产生的static pod;

如果该目录下的yaml/manifest文件有更新,kubelet则会删除原来的static pod,而根据更新后的yaml/manifest文件重新创建一个新的static pod;

如果manifests目录下的文件没有任何变化,但是其下某个yaml/manifest文件所产生的static pod错误退出或者被误删后,kubelet仍然会根据该yaml/manifest文件重新创建一个新的static pod。

这样,kubelet在一定程度上保证了static pod的高可用。

1.2.kubelet进程的高可用

kubelet通过manifests监视目录保证了staticpod的高可用,但是如果kubelet进程本身错误退出或者被误删后,谁来负责重新启动kubelet进程呢?

在Linux系统中,我们可以通过Monit、Upstart、Systemd、Supervisor等工具实现对服务的监控保证服务的高可用。

在Ubuntu 14.04操作系统中,我们将kubelet做成系统服务,利用Upstart来保证kubelet服务的高可用,下面是kubelet服务基于Upstart的服务启动脚本/etc/init/kubelet.conf:

clipboard.png

其中:
respawn: 该命令设置服务或任务异常停止时将自动启动。除stop命令外的停止都是异常停止。
respawn limit: 该命令设置服务或任务异常停止后重启次数和间隔时间。

1.3.Master High Availability Kubernetes整体架构图

从架构图中我们可以看到:
1) Upstart保证docker服务和kubelet服务的高可用,而Kubernetes的其他组件将以staticpod的方式由kubelet保证高可用。
2)两台lb节点通过haproxy和keepalived构建出一个ExternalLoadbalancer,并提供VIP供客户端访问。
3) Haproxy配置成“SSLTermination”方式,外网client通过HTTPS请求访问集群,而内网client则可以通过HTTPS/HTTP请求访问。
4) Kubernetes高可用集群通过flannelstatic pod构建一个Overlay网络,使集群中的docker容器能够通过Kubernetes Cluster IP进行通信。

核心技术点和难点

2.1.运行在特权模式的组件
Kubernetes集群中的一些组件需要通过内核模块来为集群提供服务,因此这些组件需要运行在特权模式下,以便能访问相应的内核模块。

2.1.1.开启特权模式
为了支持docker容器在特权模式下运行,我们需要开启Kubernetes集群的特权模式权限:

--allow-privileged=true

这里主要体现在kubelet服务和apiserver服务。
1) Kubelet service
kubelet服务需要开启特权模式权限,以便允许docker容器向kubelet请求以特权模式运行。
2) Apiserver static pod
apiserver static pod需要开启特权模式权限,以便运行在特权模式下的docker容器能够访问apiserver服务。

2.1.2.运行在特权模式下的docker容器
运行在特权模式下的docker容器,在yaml文件中需要添加如下字段:

securityContext:privileged: true   

这里主要体现在kubeproxy服务、flannel服务和keepalived服务。
1) Kubeproxy static pod
kubeproxy需要通过Iptables设置防火墙规则。
2) Flannel static pod
flannel需要访问vxlan、openvswitch等路由数据报文。
3) Keepalived static pod
keepalived需要访问IP_VS内核模块来建立VIP。

2.2.Static pod必须运行在主机网络下
如上所述的这些以static pod形式存在的Kubernetes集群组件,必须工作在主机网络下:

hostNetwork: true 

虽然Overlay网络是为了让不同节点间的docker容器进行通信,而上述以staticpod形式存在的组件也都是docker容器,但是它们之间的心跳和信息交流都需要通过主机网络而不是类似于flannel等的Overlay网络。理由如下:
1)这些static pods不同于应用的pods,它们的稳定保障了Kubernetes集群的稳定性,它们之间的心跳和信息交流都是通过它们配置文件中的静态IP地址进行的,而docker/flannel网络是动态的,我们无法保证docker/flannel网络中IP地址的稳定性,同时也无法事先知道IP地址。
2) kubeproxy、flannel、haproxy需要通过主机网络修改路由规则,从而使主机上的服务能被其他主机访问。
3) haproxy需要将外网请求重定向到内网后端服务器上,也必须需要主机网络。

2.3.External Loadbalancer部署要点
对于如何配置haproxy和keepalived,网络上有非常多的资源,所以这里不在论述。下面我们来分析一下部署过程中的一些要点。
External Loadbalancer由至少两台lb node组成,通过haproxy和keepalived pod实现Master的负载均衡,对外提供统一的VIP。
我们可以将haproxy和keepalived分别放置在不同的pod中,也可以将它们放置在同一个pod中。考虑到keepalived需要监测haproxy的状态,我们会把haproxy和keepalived放在一起做成一个loadbalancerpod。

2.3.1.lb node配置
1)使能内核IPVS模块
由于keepalived需要通过IPVS模块实现路由转发,所以我们需要使能内核IPVS模块。
从Linux内核版本2.6起,ip_vs code已经被整合进了内核中,因此,只要在编译内核的时候选择了ipvs的功能,Linux即能支持LVS。因此我们只需要配置操作系统启动时自动加载IPVS模块:

echo "ip_vs" >> /etc/modules
echo "ip_vs_rr" >> /etc/modules
echo "ip_vs_wrr" >> /etc/modules

我们可以通过如下命令查看ip_vs模块是否成功加载:

lsmod | grep ip_vs

如果没有加载,我们可以通过modprobe命令加载该模块:

modprobe ip_vs
modprobe ip_vs_rr
modprobe ip_vs_wrr

2)修改内核参数
为了使keepalived将数据包转发到真实的后端服务器,每一个lb node都需要开启IP转发功能

echo "net.ipv4.ip_forward = 1" >> /etc/sysctl.conf

另外,keepalived设置的VIP有可能为非本地IP地址,所以我们还需要使能非本地IP地址绑定功能:

echo "net.ipv4.ip_nonlocal_bind = 1" >> /etc/sysctl.conf

2.3.2.keepalived监测haproxy状态的方法
对于普通进程来说, keepalived进程可以通过“killall -0 haproxy”命令检测haproxy进程是否正常运行(注: Sending the signal 0 to a given PID just checksif any process with the given PID is running)。
然而在docker容器环境下,各容器都有自己的PidNamespace和NetworkNamespace,我们就需要开启haproxy的健康检查页面,然后keepalived通过健康检查页面的URL来检测haproxy目前是否正常运行。
haproxy健康检查页面配置:

listen  admin_statsbind  0.0.0.0:80log  globalmode  httpmaxconn  10stats  enable#Hide  HAPRoxy version, a necessity for any public-facing sitestats  hide-versionstats  refresh 30sstats  show-nodestats  realm Haproxy\ Statisticsstats  auth caicloud:caicloudstats  uri /haproxy?stats

keepalived对haproxy的状态检测:

vrrp_script check_script {script  "/etc/keepalived/check_haproxy.py  http://caicloud:caicloud@127.0.0.1/haproxy?stats"interval 5 # check every 5 secondsweight 5fall 2 # require 2 fail for KOrise 1 # require 1 successes for OK
}

2.3.3.haproxy SSL配置
haproxy代理ssl配置有两种方式:
1) haproxy本身提供SSL证书,后面的web服务器走正常的http协议;
2) haproxy本身只提供代理,直接转发client端的HTTPS请求到后端的web服务器。注意:这种模式下“mode”必须是“tcp”模式, 即仅支持4层代理。
考虑到:第一,用户亲和性访问需要7层代理的支持;第二,loadbalancer和master走的都是集群内网。所以本实践采用了第一种方式,配置如下:

frontend frontend-apiserver-https#  Haproxy enable SSLbind  *:443 ssl crt /etc/kubernetes/master-loadblancer.pemoption  forwardfordefault_backend  backend-apiserver-http

2.3.4.haproxy配置:haproxy.cfg

clipboard.png
clipboard.png

2.3.5.keepalived配置:keepalived.conf
1) lb-1上keepalived配置

clipboard.png
clipboard.png

2) lb-2上keepalived配置
lb-2跟lb-1的配置差不多,除了下面两个字段:

 state BACKUPpriority 97

2.4.flannel网络设置
2.4.1Master节点flannel网络设置
对于Master节点,需要等待Etcd Pod集群启动完后,先在Master上创建Flannel网络,然后Flannel Pod客户端才可以从Etcd中获取到各个Master节点的IP网段,获取到IP网段后会在主机上产生文件:“/var/run/flannel/subnet.env”,然后根据该文件修改docker启动参数:

.  /var/run/flannel/subnet.env 
DOCKER_OPTS="$DOCKER_OPTS  --bip=${FLANNEL_SUBNET} --mtu=${FLANNEL_MTU}"

并重启docker服务。

2.4.2非Master节点flannel网络设置
对于非Master节点,待Loadbalancer起来之后,Node节点能够访问Apiserver之后,Flannel Pod客户端才能从Etcd获取到该Node节点的IP网段,并且同样会在主机上产生文件:“/var/run/flannel/subnet.env”。然后修改docker启动参数,并重启docker服务。

3.实践中的遇到的那些坑

3.1.官网“haproxy docker image”的坑
Docker Hub上“haproxy image”的“docker-entrypoint.sh”内容如下:

clipboard.png

问题就出在“haproxy-systemd-wrapper”。如果运行命令:“haproxy -f/etc/haproxy/haproxy.cfg”, 而实际上运行的是经过“haproxy-systemd-wrapper”包装后的命令:

clipboard.png

执行命令“haproxy -f /etc/haproxy/haproxy.cfg”时,真正执行的是:“/usr/local/sbin/haproxy -p /run/haproxy.pid -f /etc/haproxy/haproxy.cfg -Ds”,对于“-Ds”选项, 官网是这么描述的:

clipboard.png

原来,“haproxy”经过“haproxy-systemd-wrapper”包装后在后台执行,而docker container不允许进程后台执行,否则docker容器将该启动命令执行完后就退出了。官网image的这个坑很大。
所以,当我们用官网“haproxy image”的时候,就需要用haproxy的完全路径来执行。比如在yaml文件中:

clipboard.png

3.2.haproxy container exited with 137
首先137退出码表示,其他进程向haproxy container发起了“kill”信号,导致haproxy container退出,容器日志如下

[WARNING] 155/053036 (1) : Setting tune.ssl.default-dh-param to 1024 by  default, if your workload permits it you should set it to at least 2048.  Please set a value >= 1024 to make this warning disappear.

其次,当通过“docker run”命令执行haproxy container,使用的命令与yaml文件中的一样,而且照样输出上述的“WARNING”,但是容器却不退出。

然后,无奈之下,我试着先将这个“WARNING”解决:这个错误是由于haproxy.cfg中添加了SSL证书导致的, 可以通过设置参数“default-dh-param”解决:

global...# turn  on stats unix socketstats  socket /run/haproxy.statstune.ssl.default-dh-param  2048
frontend frontend-apiserver-https#  Haproxy enable SSLbind  *:443 ssl crt /etc/kubernetes/master-loadbalancer.pem...

当我解决这个“WARNING”之后,奇迹出现了,haproxy container奇迹般的正常运行了。原来在容器的世界,一个“WARNING”也不能疏忽。

社区关于HA Master的未来发展

熟悉kubelet配置参数的都知道,我们在给kubelet配置apiserver的时候,可以通过“--api-servers”指定多个:

--api-servers=http://m1b:8080,http://m1c:8080,http://m2a:8080,http://m2b:8080,http://m2c:8080

这看起来似乎已经做到apiserver的高可用配置了,但是实际上当第一个apiserver挂掉之后, 不能成功的连接到后面的apiserver,也就是说目前仍然只有第一个apiserver起作用。
如果上述问题解决之后, 似乎不需要额外的loadbalancer也能实现master的高可用了,但是,除了kubelet需要配置apiserver,controllermanager和scheduler都需要配置apiserver,目前我们还只能通过“--master”配置一个apiserver,无法支持多个apiserver。
社区后续打算支持multi-master配置,实现Kubernetes Master的高可用,而且计划在Kubernetes 1.4版本中合入。
即使将来社区实现了通过multi-master配置的高可用方式,本次分享的MasterHigh Availability仍然非常有意义,因为在私有云场景中,ExternalLoadbalancer除了实现Master的高可用和负载均衡外,还可以针对Worker Node实现Nodeport请求的负载均衡,从而不仅实现了应用的高可用访问,同时也大大提高了应用的访问速度和性能。
参考链接:
链接
链接
好了,以上是本次分享的所有内容,欢迎大家批评指正,同时也希望能为大家带来些收益。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/543024.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

pythonmysqldb_python中MySQLdb的使用

基本的使用如上,还是很简单的,进一步使用还没操作,先从网上找点资料放上来,以备后续查看1.引入MySQLdb库import MySQLdb2.和数据库建立连接connMySQLdb.connect(host"localhost",user"root",passwd"sa&q…

分布式系统的唯一ID

2019独角兽企业重金招聘Python工程师标准>>> 需求 为什么需要唯一ID 让分布式系统中的需要辨别的元素,都能有唯一的辨识标志。 几乎所有的业务系统,都有生成一个记录标识的需求,例如: 消息标识:message-id订…

python程序跨平台桌面_Python中的跨平台桌面通知程序

在2010年的Pycon大会上有一个presentation on cross-platform Python development。还有一个关于它的html页面,其中包含一些跨平台通知的建议。但是,我在网上找不到它了,但我保存了一个本地副本,这是关于通知的部分:Th…

python去掉html标签_python 去除html标签的几种方法

#! /usr/bin/python# -*- coding:utf-8 -*-created on 2013-12-18author: javaimport refrom htmlparser import htmlparserclass filtertag():def __init__(self):passdef filterhtmltag(self,htmlstr):过滤html中的标签:param htmlstr:html字符串 或是网页源码self.htmlstr …

检查字符串是否包含数字的Python程序

Given a string and we have to check whether it contains only digits or not in Python. 给定一个字符串,我们必须检查它在Python中是否仅包含数字。 To check that a string contains only digits (or a string has a number) – we can use isdigit() functio…

android放微信@功能,Android仿微信语音消息的录制和播放功能

一、简述效果:实现功能:长按Button时改变Button显示文字,弹出Dialog(动态更新音量),动态生成录音文件,开始录音;监听手指动作,规定区域。录音状态下手指划出规定区域取消录音,删除生…

Golang Clearing slice

//first method :slice nil// second method :slice slice[0:0]Source page : https://www.socketloop.com/tutorials/golang-clearing-slice转载于:https://www.cnblogs.com/Jim-william/p/5630096.html

python multithreading_操作系统OS,Python - 多进程(multiprocessing)、多线程(multithreading)...

多进程(multiprocessing)参考:1. 多进程概念multiprocessing is a package that supports spawning processes using an API similar to the threading module. The multiprocessing package offers both local and remote concurrency, effectively side-stepping …

微信 android兼容性问题怎么解决方案,微信小程序兼容性问题

本文我们来谈谈微信小程序系统兼容性的那些坑。微信小程序兼容性问题微信小程序发布一周多了,兼容性问题,特别是 Android 平台兼容性问题特别严重。据我观察,好多小程序掉到兼容性的坑里。掉坑里不要紧,更让人捉急的是&#xff0c…

sap中泰国有预扣税设置吗_泰国的绘图标志| Python中的图像处理

sap中泰国有预扣税设置吗A colored image can be represented as a 3 order matrix. The first order is for the rows, the second order is for the columns and the third order is for specifying the color of the corresponding pixel. Here we use the BGR color format…

Attach Volume 操作(Part II) - 每天5分钟玩转 OpenStack(54)

上一节我们讨论了 attach volume 操作中 cinder-api 的工作,本节讨论 cinder-volume 和 nova-compute 如何将 volume attach 到 Instance。 cinder-volume 初始化 volume 的连接 cinder-volume 接收到 initialize_connection 消息后,会通过 tgt 创建 ta…

python编码示例_python urllib中的编码处理示例

复制代码 代码如下:>>> import urllib>>> data 丽江>>> print data丽江>>> data\xe4\xb8\xbd\xe6\xb1\x9f>>> urllib.quote(data)%E4%B8%BD%E6%B1%9F那我们想转回去呢?复制代码 代码如下:>>> urllib.unquot…

android 网络程序下载,Android之网络文件下载

环境搭建:本地服务器(下载wamp【Windows, Apache, MySQL, PHP 】,安装即可,然后将网页或文件放进 www directory)虚拟机(访问本地服务器的ip:10.0.2.2)注意事项:权限相关网络访问 存储卡访问 文件权限 如:c…

FMDB的介绍

2019独角兽企业重金招聘Python工程师标准>>> FMDB方法的介绍 1.首先我们需要创建一个FMDatabase实例: (FMDatabase*)DataBaseSigonInstance { //数据库初始化 NSString *homeDir NSHomeDirectory(); //NSLog("%",homeDir); NSString *dbPath …

python 打印列表元素_Python程序以不同方式打印列表元素

python 打印列表元素In this program – we are going to learn how can we print all list elements, print specific elements, print a range of the elements, print list multiple times (using * operator), print multiple lists by concatenating them, etc. 在此程序中…

网络克隆软件_网文生成器,克隆的是骗钱“病毒”

文章克隆器页面。图据北京晚报如今不论男女老少,多半喜欢用手机收集信息、浏览自己关注的话题。有的时候,人们会发现,不少亲朋发来的链接或者公众号推送的文章,长得特别像,但多少有那么些微不同。其实,不是…

c#读取指定字符后的字符_在C#中读取字符的不同方法

c#读取指定字符后的字符As we know that, Console.ReadLine() is used for input in C#, it actually reads a string and then we convert or parse it to targeted type. 众所周知, Console.ReadLine()用于C#中的输入,它实际上是读取一个字…

使用python 对图片进行水印,保护自己写的文章

1,关于文章被爬 说起来挺桑心的,好不容易写的文章,被爬走。 用个搜索引擎搜索都不是在第一位,写的文章全给这些网站提供流量了。 这种网站还居多广告。 还是抱怨少点吧。csdn对于这些事情也是无所作为啊。 最起码的防盗链也不…

r语言descstats_一条命令轻松绘制CNS顶级配图-ggpubr

Hadley Wickham创建的可视化包ggplot2可以流畅地进行优美的可视化,但是如果要通过ggplot2定制一套图形,尤其是适用于杂志期刊等出版物的图形,对于那些没有深入了解ggplot2的人来说就有点困难了,ggplot2的部分语法是很晦涩的。为此…

android layout_width 属性,android:layout_weight属性详解

在android开发中LinearLayout很常用,LinearLayout的内控件的android:layout_weight在某些场景显得非常重要,比如我们需要按比例显示。android并没用提供table这样的控件,虽然有TableLayout,但是它并非是我们想象中的像html里面的t…