作者简介:高泗俊,平安云平台高级开发工程师,监控系统大神
转自:订阅号「平安科技金融云」
为什么说平安云安全?
因为我们有独到的监控体系
open-falcon是目前国内最流行的监控系统, kubernetes是最流行的容器编排框架, 两者在一起会碰出什么样的火花呢?
备注:文中提到的Argus是在open-falcon的基础上进行二次开发的一个监控系统。
kubernetes简介
kubernetes相信很多人都会或多或少有听过或者了解。 它是谷歌开源的,最流行的容器集群管理平台和编排框架, 负责对应用容器进行跨主机的自动化的部署,扩容,管理,回滚,升级。kubernetes中间正好是8个字母, 所以又有一个昵称叫k8s, 以下都简称k8s。
大家应该都知道容器编排界目前是三足鼎立, 除了k8s之外,还有mesos, swarm, 其中mesos是一个资源调度框架,需要配合marathon才能管理容器集群。 我列了个表格,是5月20日当天的数据, 数据来源于全球最大开源代码网站github,从github的数据来一窥这三者在开源界的影响力和流行度。
可以看出,无论从社区的喜爱度, 关注度,代码贡献人数, 代码提交量,他都是遥遥领先的。 社区活跃的好处就是文档比较完善, 软件出现的问题一般情况下也会很快会被修复,你遇到的问题也可以在社区得到很快的响应。 这也是我们选择k8s作为集群管理系统的原因之一。
这是K8S系统架构。它有两类节点,master节点和node节点。 master节点是集群的大脑,负责pod的调度和状态更新。node就是工作节点, 通常是一台物理机或者虚拟机.etcd是k8s集群的后端存储, 用来存储状态信息。
open-falcon简介
open-falcon是小米在2015年开源的监控系统, 无论是水平扩展性,还是其性能都优于zabbix。 目前已经超过100家的公司在使用这套系统。
上面是open-falcon的一个架构图。我们平安云在开源的open-falcon的基础上开发了自己的监控系统,叫Argus. Argus监控系统结合了平安的场景,比如vmware监控,字符串监控, 中间件监控等做了很多的二次开发。 改造后的架构图如下:
在架构设计上,我们实现的是三地两中心的部署方式。
kubernetes + open-falcon
从open-falcon的架构图我们可以看到open-falcon的组件比较多,企业在实际使用中还会围绕着它开发更多的组件出来。比如平安云的Argus监控系统就对open-falcon做了大量的改造, 并增加了pa-portal, query-proxy, config-server, emp-notify等组件。每个组件都要保证高可用,都要进行管理, 监控,升级,部署。另外实际生产中不止部署一个集群, 我们会在每个地区都部署一套甚至多套集群。 如果用传统的方式, 这个工作量和运维成本是比较高的。对open-falcon进行容器化不但是必要的,而且可行。open-falcon大部分组件都是无状态的,可以用k8s来保证其水平扩展,还有保证可用性。另外k8s的调度方式也可以帮助提高服务器的资源利用率。k8s集群搭建起来后,其它内部的运维工具也可以容器化, 用k8s集群管理起来,这样可以最大限度的发挥k8s集群的功能。
讨论完可行性和必要性之后, 接下来的内容,我会讲下如何从头构建这样一套系统。这是一张我们的整套系统的架构图。 底层是IAAS层, 用的是我们的云平台的IAAS服务。中间的容器平台就是我们构建的K8S集群,负载均衡用的是Nginx和LVX, 其中LVX是平安云自研的高性能高可扩展的负载均衡器。 再往上是运行在k8s集群上的应用系统,如Argus监控系统,还有运维工具及运维系统。 最上层是我们构建应用系统用的一些上层服务, 如代码和镜像管理,CI/CD服务, 集群管理服务等。
组件容器化
在构建argus k8s 集群过程中, 我们做的第一个事情是实现监控系统的容器化。
为20~30个组件编写dockerfile和k8s 编排文件, 当然也不是傻傻的一个一个写, 我们对Argus的组件做了分类,分成了golang组件和python组件。然后抽离了组件之间有差异的地方,做成了两类模版,把有差异的地方写在配置文件, 这样可以用脚本很方便的生成Argus的dockerfile和k8s 的编排文件。在组件容器化过程中, 有几个地方需要提一下:
1. 所有的Argus组件的配置文件转化成k8s的Configmap对象,用k8s做集中的管理( k8s对configmap的大小有1M的限制,建议配置大小不要超过1M.不过正常情况下也不会超过)
2. 对于需要访问的外部服务,如邮件网关,电话网关等, 都分别创建对应Service,并自定义Endpoint, 实现服务的发现
3. 有状态的组件,如数据落地组件graph, 每个实例都使用单个副本(replica设置为1)的ReplicaSet+独立的Service来管理,没有使用StatefulSet。
4. 对于MySQL, Redis这类有状态的数据库组件, 容器化的优势不明显,且k8s对这类应用的管理方案并不成熟,所以没有容器化, 而是以类似DBaaS的方式运行。
我们来看一张流程图, 这是我们从开发到发布镜像的整个过程。从开发,打包, 镜像制作上传等,我们用工具实现了基本的自动化。
集群规划
容器化的工作做完之后, 我们开始规划集群。 集群的规划有几个方面:包括要用什么样的软件版本和系统环境, 分配什么样的网段, 要开什么样的防火墙策略。首先是版本选择。
k8s的版本我们选择的是1.6版本。 选择1.6版本主要也是考虑到它的性能相比之前有成倍的提升。 选择了1.6版本, 就要选择etcd3. 这个没什么可说的。至于flannel的版本的选择建议选0.7版本, 因为这个版本有针对广播风暴的情况做优化。docker选择了1.12.3,目前运行比较稳定。 系统选择了centos7.2,内核在3.10以上, 主要考虑到docker和systemd的支持。其次是防火墙策略规划和网段规划。
实际生产环境是有防火墙隔离的。需要根据实际的网络情况,还有各个组件的交互情况,开放对应的防火墙策略。k8s集群内部有两类ip, 一个是pod的ip,即容器的真实ip, 一个是service cluster ip, 是一个虚拟的ip。 所以需要两个网段, 给它分配的网段不能和现有的物理网络的规划有冲突。否则可能会有各种不可预期的问题。 此外一个集群的节点规模是怎么样的, 每个机器最大要容纳多少容器, 每个集群要支持多少的应用,这个都是实际上生产部署前要考虑的。举个例子,对于使用了flannel网络模型的k8s集群,每个物理主机会占用一个子网, 因此设置的子网掩码决定了每个主机能够分配多少个ip地址, 即能启动多少个pod,多少个容器。如果你设置掩码为26, 那么单台工作节点最大能启动62个pod。
网络模型
k8s集群支持cni网络模型,可选的网络插件包括flannel, calico, weave等, 当然也可以自己开发。我们对几种常用的网络模型做了分析对比。
· flannel 支持两种backend, udp 和vxlan。 udp在用户空间进行数据转发, 相比其它方案性能较差,不考虑。
· weave虽然构建简单,和其它两个插件比,但是性能较差,不考虑。 (weave支持fast datapath的模式,可以提升网络通信性能,但是这个模式需要linux内核3.12以上支持,需要进行内核升级才行)。
· calico 是纯3层的SDN方案,走的是传统的tcp/ip协议栈, 无需NAT, 也无需额外的vxlan封装, 转发性能最好,且支持各种安全策略。 但是物理网络需要适配该方案并且当宿主机规模扩大(传统已有环境不可能无缝支持这种方式),路由收敛、拓扑学习需要占用大量的计算资源和时间。
· 最终选定了flannel vxlan模式,考虑到我们是在内网管理的集群,无需复杂的隔离, 而且flannel的性能也够用, 配置起来也相对简单,因此选择了flannel vxlan模式。
存储方案存储上我们目前生产上用本地盘,分布式存储用的NAS,Ceph rbd我们正在调研和测试。 对于读写吞吐量大, 性能和稳定性要求较高的,比如argus的数据落地组件, 我们用本地盘做存储,直接挂载本地磁盘。其它有状态的组件如mysql, redis, meta, gitlab, 用nas盘作为数据盘,但是未来可能会用ceph rbd或者ceph fs替代nas。存储这块,还有一个方面需要考虑。 为了保证docker的可用性, 最好再单独挂一个逻辑卷作为docker数据和元数据的存储。 docker默认启动时device mapper使用的是loopback设备, 这种方式官方仅推荐用于开发环境, 生产环境建议使用device mapper的direct-lvm模式,在负载较高时能获得更高的存储性能。 我们在生产环境用的是direct-lvm模式。
高可用方案
组件容器化,集群规划, 网络和存储这些确定之后, 还不够。 作为生产系统,上线前必须考虑系统的高可用问题。argus系统的可用性由k8s保证, 而k8s自身的高可用需要通过合理的架构设计来保证。架构图如下:
k8s的master组件分为两类,一类是无状态的,如apiserver, 可以水平扩展,前端挂一个负载均衡, 对外暴露vip即可。 一类是有状态的, 同一时刻只能有一个实例工作, 否则调度的状态会乱掉,比如controller manager, scheduler组件。 这类组件可以启动三个组件, 让其自主选主。 每次由选出的主实例来对pod进行调度。目前无论是master还是node的进程都是用systemd来管理和启停的。 也就是说用linux系统的systemd进程来保证进程的可用性。 如果进行被杀掉或者意外退出或者主机重启, systemd会自动将其进程拉起。
监控和日志
生产系统上线我们都会配置监控,k8s集群也不例外。监控这边分为性能监控和可用性监控两部分。 对于k8s集群主机的基础指标监控,容器的基本指标,我们用argus来监控, 而k8s核心组件和argus核心组件的可用性监控,用一个独立的工具来监控。我们这个工具会部署在多个数据中心的多台主机上进行探测。对监控系统的监控不能再依赖于监控系统, 使用独立工具的好处在于没有依赖,简单稳定,可用性高。而多中心多主机的部署也是为了保证工具的可用性。
日志的话用的elk + filebeat。对于另外一个常用的方案fluentd我们也做过调研。 为什么不用fluentd,而用filebeat呢?有三个理由:
1. 我们内部有一个elk集群,filebeat和elk几乎是配套的, 他的升级和elk是同步的, 兼容性比fluentd好(fluentd默认不支持输出到logstash,一般都是直接输出到es集群)
2. filebeat的功能也一样很强大,足够轻量级, 能够满足我们的日志采集和分割需求。
3. 我们对filebeat的配置比较熟悉 ,因此我们没有必要再去维护一个fluentd。
部署与管理
在部署上, 我们用了ansible写了编排脚本,即playbook。在资源准备ok的情况下, 我们半个小时就可以搭建一套k8s集群, 如果忽略镜像下载的时间, 我们可以基本上可以在10分钟内, k8s集群上构建一套argus监控系统。对于k8s集群的管理, 目前用社区的kubernetes dashboard来做简单的可视化管理。
虽然目前5套k8s集群已经在线上稳定运行了。但是还是有许多需要优化的地方。针对应用自身的优化有配置动态加载,这样的话,每次修改完配置,就不需要重启pod, 有时候重启pod会出现tcp连接断掉,造成一些数据丢包。 针对组件自身的健康检查也可以加上, 这样能够及时处理程序hang死的情况。对应用实例要进行规划资源请求的限额,防止某些应用容器请求过多资源影响到其它应用的正常运行。另外我们也开始着手做一些开发的工作。 首先我们计划做一个集群管理平台。通过这个平台我们可以管理多个区域的k8s集群,展示集群的状态, 比如多少节点失联,各个服务的健康情况等, 另外我们考虑和我们内部的智能运维平台alphaops做对接,实现对集群的自动化扩容, 应用系统的容灾切换等。我们有一个集群一开始是以传统方式部署的, 现在也准备迁移到k8s平台上面。 我们也准备了一套平滑的迁移方案。请关注我们后续的文章。