一键部署kubernetes1.6高可用集群

请关注DeveloperQ公众号

DeveloperQ公众号

本文适合于有一定 k8s基础的人,通过本文你将学到:

  • k8s各组件的交互原理

  • k8s的集群规划

  • k8s系统配置,各组件主要启动参数含义

  • k8s部署过程可能出现的问题及解决方案

  • ansible基本知识


字数:3500 ,预计阅读时间:10min


背 景


kubernetes是google开源的容器编排框架,也是最流行的容器编排框架之一,以下简称k8s。部署一个k8s集群,特别是一个高可用的k8s集群,往往需要费非常多的时间和精力。

当前关于k8s部署的文章绝大部分是单master的部署,满足不了高可用的需求,本文将为您介绍平安云使用多master的部署方案来保证k8s控制节点高可靠的实操案例。

考虑到当前文章大多介绍的比较简单,只是罗列了安装步骤,对集群规划、组件交互原理、遇到的问题及优化的手段等介绍的较少。本文会通过介绍使用二进制部署k8s集群的步骤、各组件的启动参数、含义、可能遇到的问题以及简单介绍系统各组件的交互原理,来帮助大家理解和解决实际问题。

后面会有一系列的文章来介绍k8s概念原理和生产实践。那些日子开过的路段,踩过的坑,都会毫无保留的分享。

这是kubernetes实践系列的第一篇:一键部署kubernetes 1.6高可用集群


集群详情


实际生产实践中, 按照系统设计的流程,我们一般会先确定系统的逻辑架构图, 系统组件的调用关系图, 根据架构图确定需要多少机器资源, 需要开通什么样的防火墙策略。另外在部署之前需要考虑集群的规划, 比如需要什么样的网段, 每台主机需要管理多少容器, 支撑多少应用。


架构图

放一张官方的高可用逻辑部署图。我们会按照这个部署图来构建整个k8s集群。


另外放一张k8s各组件之间交互调用的原理图,有助于大家理解每个组件的启动参数和防火墙策略的设定。

软件版本

组件或系统版本
Kubernetes1.6.01.6版本支持单集群5000节点, 15万容器(官方数据)
Docker1.12.3需要系统内核版本3.10以上支持
Etcd3.1.5Etcd3的性能优于etcd2,k8s1.6版本使用etcd3做为状态存储组件。
Flanneld0.7backend为vxlan网络,需要系统内核版本3.7以上支持
CentOS7.2建议系统内核3.10及以上


机器配置


下面的配置是POC环境的机器配置情况。实际生产部署可以选择更好的机器,目前没有最优建议,可以根据成本预算和使用应用承载量而定。


组件机器配置
ETCD建议4核CPU, 4G内存及以上配置, 3台可以和k8s master组件共用机器混合部署,如果机器资源充足,建议分开部署
K8S Master建议4核CPU, 4G内存及以上配置, 3台同上建议
LoadBalance建议4核CPU, 4G内存及以上配置, 2台主备,注意这个不要和master,node组件混合部署,影响稳定性和可用性
Node4核CPU, 4G内存, 1台以上配置需求与运行的容器数量和应用类型相关


防火墙策略

如果k8s不是在一个扁平的大二层网络里,如果跨了多个网段,且网段之间有防火墙隔离,那么还需要考虑防火墙问题(以下不考虑加密传输的情况下,且使用默认启用的端口, 如果你修改了默认的端口,那么相应的修改防火墙即可)


sourcedestinationport
kubelet/kube-proxyapi server8080
controller-manager/schedulerapi server8080
api serveretcd2379
dockerddocker  registry5000
flanneldetcd2379
flanneldflanneld8285
集群规划

网络和端口规划,以下针对的是单个k8s集群的情况

注解配置
FLANNEL_NETflannel的网段192.168.0.0/16注意不要和现有的网段规划冲突,另外此处掩码为26,意味着支持2^(26-16),约1024个node节点
FLANNEL_SUBNETLENflannel的子网掩码26掩码26,意味着单个主机可以最多分配2^(32-26) -2 ,约62个容器
SERVICE_CLUSTER_IP_RANGEservice 的 ip 网段10.10.1.0/22假设每个应用占用1个service ip,则可以支持约2^(32-22) -2 ,约1022个应用部署
NODE_PORT_RANGEnode port的端口范围30000 ~ 32767service的node port 可以使用主机上2767个端口


部署详情


整个部署中,所有k8s的组件都用了编译好的二进制包进行安装,启动参数都写在单独的配置文件里。 进程使用systemd管理, 且加入开机自启动, 同时增加一个crontab任务,定时启动进程,确保进程在挂掉时能够及时拉起。 Ansible用来做任务编排。接下来会对ansible做一个简单的介绍,每个组件具体用到的启动参数和注意事项也会简要说明。

ansible介绍


整个k8s集群的部署是用ansible进行任务编排的。这里简单介绍下ansible,更加详细的ansible介绍可以参考ansible文档。

架构图


基本概念

  • ansible core:ansible自身核心模块

  • host inventory:主机库,定义可管控的主机列表

  • connection plugins:连接插件,一般默认基于ssh协议连接

  • modules:core modules(自带模块)、custom modules(自定义模块)

  • playbooks:剧本,按照所设定编排的顺序执行完成安排任务

  • files/:此角色中用到的所有文件均放置于此目录中

  • templates/:Jinja2模板文件存放位置

  • tasks/:任务列表文件;可以有多个,但至少有一个叫做main.yml的文件

  • handlers/:处理器列表文件;可以有多个,但至少有一个叫做main.yml的文件

  • vars/:变量字典文件;可以有多个,但至少有一个叫做main.yml的文件

  • meta/:此角色的特殊设定及依赖关系;


常用命令

  • ansible-playbook -i hosts site.yml --list-hosts   列出要被执行任务的远程主机,不执行任务

  • ansible-playbook -i hosts site.yml--list-tasks   列出要执行的任务,不执行任务

  • ansible-playbook -i hosts site.yml--syntax-check   进行语法检查,不执行任务

  • ansible-playbook -i hosts site.yml    执行任务


任务优化

  • 增加失败重试

  • 增加失败检查,比如etcd部署失败,则任务退出,不再进行接下去的部署

  • 执行操作前会先对旧的配置进行备份,方便出错时回滚配置。


部署流程

1.  etcd 集群搭建

2.   loadbalance主备搭建

3.   k8s master cluster 搭建

4.   k8s node 部署

5.   给node机器打label

6.    dns 插件部署

7.   dashboard插件部署

8.   部署ingress controller插件

9.   部署efk插件

ps:因为公司有一套完整的es集群, docker registry私有仓库和监控系统,所以在部署中没有再额外构建这些环境。不过以后会根据需要在部署过程中加入这些组件的构建。


ETCD集群

默认搭建一个有3个节点的ETCD集群

启动参数参数说明
ETCD_NAME节点名称
ETCD_DATA_DIRS指定节点的数据存储目录,这些数据包括节点ID,集群ID,集群初始化配置,Snapshot文件等
ETCD_LISTEN_PEER_URLS监听URL,用于与其他节点通讯
ETCD_INITIAL_ADVERTISE_PEER_URLS告知集群其他节点url‍‍‍‍‍
ETCD_INITIAL_CLUSTER集群中所有节点
ETCD_INITIAL_CLUSTER_STATE初始化集群状态
ETCD_INITIAL_CLUSTER_TOKEN集群的ID
ETCD_ADVERTISE_CLIENT_URLS告知客户端url, 也就是服务的url


Tips建议和提示

ETCD_NAME=master01ETCD_INITIAL_CLUSTER="master01=http://1.1.1.1:2380,master02=http://2.2.2.2:2380,master03=http://3.3.3.3:2380"这里ETCD_NAME和ETCD_INITIAL_CLUSTER对应的name要一致,否则可能会启动失败。


Master节点

部署考虑了master组件的高可用, 由三个节点构成一个集群。apiserver是无状态的,前端提供负载均衡,暴露vipcontroller manager 和 scheduler 是有状态的,需要进行leader elect,同一时间只能有一个实例对集群信息进行读写。

组件名参数参数
api server--etcd-servers以逗号分隔的etcd服务url列表, etcd服以http://ip:port格式表示
api server--insecure-bind-address 绑定不安全的ip地址,默认且localhost,设置为0.0.0.0就可以侦听所有网络接口
api server--insecure-port提供非安全认证的监控端口,默认为8080
api server--kubelet-port kubelet侦听的端口
api server--service-node-port-range Service的node port 能使用的主机端口范,默认为30000 ~ 32767,包括30000和32767
api server--allow-privileged允许pod允许具有系统特权的容器,默认值为false
api server--service-cluster-ip-range  service的cluster ip (虚拟ip)池,这个不能和集群所在物理网络重合
controller manager / scheduler--masterapi server的url地址
controller manager / scheduler--leader-elect 设置为true时,表示进行leader选举,一般用于master的高可用部署,默认值是false
controller manager / scheduler--leader-elect-lease-durationleader选举过程中非leader等待选举的时间间隔,默认为15秒
controller manager / scheduler--leader-elect-renew-deadlineleader选举过程中在定制leading角色之前再次renew的时间间隔,应小于等于eader-elect-lease-duration,默认为10秒
controller manager / scheduler--leader-elect-retry-period leader选举过程中,获取leader角色和renew之间的等待时间,默认为2秒


Tips建议和提示

controller manager和scheduler的启动参数一致,将 --leader-elect 设置为true,其它elect参数保持默认即可。


Node节点
组件名参数参数
kubelet--addresss   绑定主机的地址,默认为0.0.0.0,表示使用主机上的所有网络接口
kubelet--port   进程侦听的端口
kubelet--api-serversapi server地址列表,以ip:port 格式表示,以逗号分隔
kubelet--allow-privileged 是否允许以特权模式启动容器,默认是false
kubelet--cluster_dns 集群内dns服务的ip地址
kubelet--cluster_domain集群内dns服务所用域名
kubelet--pod_infra_container_image用于pod内网络命名空间共享的基础的pause镜像, 默认值为gcr.io/google_containers/pause-amd64:3.0
kube-proxy--masterapi server的url地址
flannel-etcd-endpoints以逗号分隔的etcd服务url列表, etcd服务以http://ip:port格式表示
flannel-etcd-prefix etcd的前缀,默认是/coreos.com/network
docker--insecure-registry 设置私有仓库url地址
docker --bip  绑定的bridge网卡地址
docker--ip-masq 启用ip伪装技术,一般用于NAT ,默认为false
docker--mtu 网络包的大小,默认为 1450

Tips建议和提示

pause镜像默认是从gcr.io上拉取的,但是由于gfw的缘故,国内无法正常下载。

可以通过--pod_infra_container_image指定私有仓库或者可以访问的仓库镜像地址,让k8s到这些仓库去下载,而不是从gcr.io如果集群中有的node节点位于非dmz区域,有的node节点位于dmz网络区域, 那么dmz区的docker启动的时候一定要设置--ip-masq 为true,同时flanneld启动的时候要指定-public-ip 为nat转换后的ip,否则无法和非dmz区的docker容器正常通信,具体原理涉及flannel和vxlan网络原理,限于篇幅,不在这里赘述。


相关插件


使用的相关插件有nginx ingress controller, kubernetes dashboard, kubedns, fluentd ,都是使用k8s的方式进行编排,启动并加载


插件名称
kubedns启动1个replication  controller,副本数为1, pod里包含了三个container,分别为kube-dns, kube-dnsmasq,  exechalhz,此外还会启动一个service,注意在kube-dns容器的启动参数中指定--kube-master-url
nginx ingress controller动2个replication  controller ,分别为default-http-backend  和 nginx ingress controller,启动一个service。注意在ginx ingress  controller容器的启动过程设置环境变量  KUBERNETES_MASTER, 指定api server的url 及端口
kubernetes dashboard启动一个 replication  controller, 一个service, 一个ingress,注意在kubernetes-dashboard容器的启动参数中指定--apiserver-host
fluentd启动一个daemonset,一个configmap,通过挂载configmap的方式可以修改fluent.conf


Tips建议和提示

根据插件互相之间的依赖关系,可以确定插件的加载顺序是 kubedns -> nginx ingress controller-> kubernetes dashboard / fluentd/...外部下载镜像会遇到墙的问题。可以通过灵雀云http://www.alauda.cn/的镜像中心来构建或者拉取被墙的镜像,限于篇幅,具体实现方法在这里不赘述。



优化和改进


由于时间匆忙,本人水平又有限,也有一些需要改进和完善地方。如:

  • 增加prometheus+grafana插件

  • 增加私有的docker registry或harbor插件

  • 增加安全相关配置, 如TLS 认证通信 (所有组件,如 etcd、kubernetes master 和 node) ,RBAC 授权等

  •  docker的后端存储修改为overlayfs或者devicemapper的direct-lvm模式,以提高性能

  • ansible playbook 增加回滚步骤,可以进行一键回滚

  •  针对负载均衡vip和vrid是否占用的自动检测,防止网络冲突,导致 loadbalance无法正常启用

  • etcd前面暴露vip, flannel, api-server连接时使用vip进行连接

  •  ansible每个task都进行检查,以校验是否成功

  • 调整kubelet的日志级别,防止日志量过大,撑爆磁盘

  • 除docker, kubelet之外,其它组件全部用k8s static pod的方式实现

  •  提供web界面,提供部署,动态修改参数等功能


总 结


kubernetes集群的整个部署过程是比较复杂的,涉及的知识栈也比较多,特别是在出现问题的时候,需要查阅大量的资料,包括源码。

另外值得一提的是, ansible 是一个非常棒的自动化工具。我们使用ansible来编排自动化部署的任务,提高部署效率。原来3天甚至1个星期的部署工作,现在用半个小时的时间就可以部署一套功能相对完备的,高可靠的k8s集群。

限于篇幅有限,有些细节可能叙述得不是很清楚。如有谬误的地方,也恳请指出。附上我的个人微信号和个人公众号,欢迎关注和交流。

个人公众号:云时代的运维开发

个人微信号:paranoiakevin


后 续

众所周知,open-falcon是一个优秀的开源监控系统,它的功能,性能,可扩展性能力都很强,但是由于模块众多,部署和管理这些模块变得比较复杂。我们尝试利用k8s来管理open-falcon,并成功在生产中运行起来。


open-falcon的容器化过程中,遇到了不少问题,实际部署又涉及了ingress以及有状态应用的问题,更多的细节,请期待kubernetes实践系列的第二篇文章:《当open-falcon遇上k8s》



平安金融云,专业成就金融客户的云平台!








相关问题推荐