一键部署kubernetes 1.6高可用集群

2017-09-15  本文已影响602人  jony456123

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

k8s各组件的交互原理

k8s的集群规划

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

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

ansible基本知识

背景

kubernetes是google开源的容器编排框架, 也是最流行的容器编排框架之一, 以下简称k8s。

部署一个k8s集群,特别是一个高可用的k8s集群,往往需要费非常多的时间和精力。

当前关于k8s部署的文章绝大部分是单master的部署,满足不了高可用的需求。 我们使用多master的部署方案来保证k8s控制节点的高可靠。

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

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

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

集群详情

实际生产实践中, 按照系统设计的流程,我们一般会先确定系统的逻辑架构图, 系统组件的调用关系图, 根据架构图确定需要多少机器资源, 需要开通什么样的防火墙策略。另外在部署之前需要考虑集群的规划, 比如需要什么样的网段, 每台主机需要管理多少容器, 只要支撑多少应用。 这些都是需要考虑的。 但是很多讲k8s部署的文章,又都很少涉及这块的内容。 下面听我一一道来。

架构图

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

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

软件版本

组件或系统 版本 备注 Kubernetes 1.6.0 1.6版本支持单集群5000节点, 15万容器(官方数据) Docker 1.12.3 需要系统内核版本3.10以上支持 Etcd 3.1.5 Etcd3的性能优于etcd2,k8s1.6版本使用etcd3做为状态存储组件。 Flanneld 0.7 backend为vxlan网络, 需要系统内核版本3.7以上 支持 CentOS 7.2 建议系统内核3.10及以上

机器配置

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

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

防火墙策略

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

source destination port kubelet / kube-proxy api server 8080 controller-manager / scheduler api server 8080 api server etcd 2379 dockerd docker registry 5000 flanneld etcd 2379 flanneld flanneld 8285

集群规划

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

变量 注解 配置 备注 FLANNEL_NET flannel的网段 192.168.0.0/16 注意不要和现有的网段规划冲突,另外此处掩码为16, 意味着支持2^(26-16),约1024个node节点 FLANNEL_SUBNETLEN flannel的子网掩码 26 掩码26,意味着单个主机可以最多分配2^(32-26) -2 , 约62个容器 SERVICE_CLUSTER_IP_RANGE service 的 ip 网段 10.10.1.0/22 假设每个应用占用1个service ip, 则可以支持约2^(32-22) -2 ,约1022个应用部署 NODE_PORT_RANGE node port的端口范围 30000 ~ 32767 service的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部署失败, 则任务退出,不再进行接下去的部署

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

部署流程

etcd 集群搭建

loadbalance主备搭建

k8s master cluster 搭建

k8s node 部署

给node机器打label

dns 插件部署

dashboard插件部署

部署ingress controller插件

部署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=master01

ETCD_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是无状态的,前端提供负载均衡,暴露vip

controller 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

--master

api server的url地址 controller manager / scheduler

--leader-elect

设置为true时,表示进行leader选举, 一般用于master的高可用部署, 默认值是false controller manager / scheduler

--leader-elect-lease-duration

leader选举过程中非leader等待选举的时间间隔, 默认是15秒 controller manager / scheduler

--leader-elect-renew-deadline

leader选举过程中在定制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

--address

绑定主机的地址, 默认为0.0.0.0, 表示使用主机上的所有网络接口 kubelet

--port

进程侦听的端口 kubelet

--api-servers

api 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 --master api 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镜像默认是从http://gcr.io上拉取的, 但是由于gfw的缘故, 国内无法正常下载。 可以通过--pod_infra_container_image指定私有仓库或者可以访问的仓库镜像地址,让k8s到这些仓库去下载,而不是从http://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/...

外部下载镜像会遇到墙的问题。可以通过灵雀云灵雀云 容器服务 - CaaS的镜像中心来构建或者拉取被墙的镜像, 限于篇幅, 具体实现方法在这里不赘述。

优化和改进

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

增加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

「真诚赞赏,手留余香」

赞赏

还没有人赞赏,快来当第一个赞赏的人吧!

Kubernetes容器

上一篇下一篇

猜你喜欢

热点阅读