基于kubernetes自研容器管理平台的技术实践
一、容器云的背景
伴随着微服务的架构的普及,结合开源的Dubbo和Spring Cloud等微服务框架,宜信内部很多业务线逐渐了从原来的单体架构逐渐转移到微服务架构。应用从有状态到无状态,具体来说将业务状态数据如:会话、用户数据等存储到中间件中服务中。
微服务的拆分虽然将每个服务的复杂度降低,但服务实例的数目却呈现出爆炸式增长,这给运维增加难度,一方面是服务部署、升级,另一方面是服务的监控故障恢复等。
在2016年,容器技术尤其是Docker迅速流行起来,公司内部开始尝试将容器放到容器内运行,虽然通过容器解决了服务发布问题,但很多容器的运维仍然让运维捉襟见肘。宜信是一家金融科技公司,在引入开源组件的时候,稳定可靠是作为考量的最重要标准,在2017年初kubernetes慢慢成熟,成为容器的管理标准,并且被国内外很多公司采用,在这种背景下,宜信借鉴开源社区和商业PAAS平台产品,基于kubernetes自研一套容器管理平台。
二、整体架构
整个架构围绕kubernetes构建,分为四个层级,最底层主要是基础资源,包括网络、计算、存储,所有的容器都是部署在物理服务器上,容器挂载商业NAS存储,网络通过vxlan互连;中间层核心的是资源调度层,主要完成多集群的管理、发布部署、智能调度、自动伸缩等,这层主要是资源管理和服务编排;左侧面是提供系统安全,主要是为了系统安全和容器镜像安全,右侧面是一套代码自动编译、自动构建、自动部署系统;中间件层主要提供常用的中间件服务,Nginx配置和监控告警等;最上层的是用户接入层,主要提供用户的操作入口。整体架构如下图所示:
三、Nginx自助管理
公司大部分的服务都是通过Nginx反向代理对外提供服务,为了服务的隔离和负载均衡,总计十几套的Nginx集群,这些nginx的版本、配置方式各有不同,导致单纯靠人工去运维的成本非常高而且容易出错,并且容器的IP地址不固定,无法直接配置到nginx后端。自研了一套nginx管理系统,主要是为了解决nginx的模板化配置,如下图所示:
Nginx-mgr提供HTTP请求,负责接收nginx配置请求,并更新到etcd,每个nginx-agent通过watch Etcd批量刷新nginx的配置。在实际的生产环境里,部署的是阿里开源的Tengine而并非nginx,由于配置基本相同不做区分。每个服务都配置了健康检查,这样能够保障在后端故障中自动切换。如果有虚拟机场景需要手动切换,下图展示了手动切换nginx的页面:
由于很多业务都是虚拟机和容器混跑的情况下,如果后端是容器,我们通过kubernetes的API获取容器的IP地址动态刷新。
四、多集群管理
虽然kubernetes本身存在采用高可用的部署架构,避免单点故障,但这远远还不够,一方面是因为单个kubernetes集群部署在一个机房,如果发生机房级别的故障,将会导致服务中断,另一方面由于单个kubernetes集群本身故障,如集群的网络配置错误导致整个网络故障等,都将会影响业务的正常使用,在宜信将kubernetes部署在多个机房内,机房之间通过专线互连。那么多集群的管理将成为主要难点:第一是如何分配资源,当用户选择多集群部署后,系统根据每个集群的资源用量,决定每个集群分配的容器数量,并且保证每个集群至少有一个容器。集群自动伸缩时,也会按照此比例创建和回收容器。第二是故障迁移,如图中的集群控制器主要为了解决多集群的自动伸缩和集群故障时的容器迁移,控制器定时检测集群的多个节点,如果多次失败后将触发集群容器迁移的操作,保障服务可靠运行。
第三是网络和存储的互连,由于跨机房的网络需要互连,我们采用vxlan的网络方案实现,存储也是通过专线互连。容器的镜像仓库采用Harbor,多集群之间设置同步策略,并且在每个集群都设置各自的域名解析,分别解析到不同的镜像仓库。
五、DNS解析
由于业务人员对容器技术还存在疑虑,所以大部分应用都是虚拟机和容器的混合部署,容器通过域名访问虚拟机和虚拟机通过域名访问容器都是普遍存在的,为了统一管理域名,我们没有采用kubernetes自带的kube-dns(coreDns)而采用bind提供域名解析。通过kubernetes支持的Default DNS策略将容器的域名指向公司的DNS服务器,并配置域名管理的API动态添加。
六、网络方案
kubernetes的CNI的网络方案有很多种,主要分为二层、三层和overlay方案。一方面机房并不允许跑BGP协议,并且需要跨机房的主机互连,所以我们采用了flannel的vxlan方案,为了实现跨机房的互通,两个集群的flannel连接到同一个etcd集群,这样保障网络配置的一致性。老版本的Flannel存在很多问题,包括:路由条数过多,ARP表缓存失效等问题。建议修改成网段路由的形式,并且设置ARP规则永久有效,避免因为etcd等故障导致集群网络瘫痪。
Flannel的使用还需要注意一些配置优化,默认情况下每天都会申请Etcd的租约,如果申请失败会删除etcd网段信息。为了避免网段变化,可以将etcd数据节点的ttl置为0(永不过期);Docker默认是会masq所有离开主机的数据包,导致flannel中无法获取源容器的IP地址,通过设置Ipmasq添加例外,排除目标地址为flannel网段数据包;由于flannel使用vxlan的方式,开启网卡的vxlan offloading对性能提升很高。Flannel本身没有网络隔离,为了实现kubernetes的network policy我们采用canal,它是calico实现kubernetes的网络策略的插件。
七、CICD
为了支持Devops流程,在最初的版本我们尝试使用Jenkins的方式执行代码编译,但Jenkins对多租户的支持比较差。在第二版通过kubernetes的Job机制,每个用户的编译都会启动一个编译的Job,首先会下载用户代码,并根据编译语言选择对应的编译镜像,编译完成后生成执行程序,如果jar或者war文件。通过Dockerfile打成Docker镜像并推送到镜像仓库,通过镜像仓库的webhook触发滚动升级流程。
八、服务编排
系统设计了应用的逻辑概念,kubernetes虽然有服务的概念,但缺少服务的关联关系,一个完整的应用通常包括前端、后端API、中间件等多个服务,这些服务存在相互调用和制约的关系,通过定义应用的概念,不仅可以做到服务启动先后顺序的控制,还可以统一规划启停一组服务。
九、日志
容器的日志归集使用公司自研的watchdog日志系统,每台宿主机上通过DaemonSet方式部署日志采集Agent,Agent通过Docker API获取需要采集的容器和日志路径,采集日志并发送到日志中心,日志中心基于elasticsearch开发,提供多维度日志检索和导出。
十、监控
容器本身资源监控的性能监控通过Cadvisor + Prometheus的方式,容器内业务的监控集成开源的APM监控系统uav(https://github.com/uavorg/uavstack),完成应用的性能监控。uav的链路跟踪基于JavaAgent技术,如果用户部署应用勾选了使用uav监控,系统在构建镜像时将uav的agent植入到镜像内,并修改启动参数。
除了上述几个模块外,系统还集Harbor完成容器镜像的多租户管理和镜像扫描功能;日志审计是记录用户在管理界面的操作,webshell提供用户的web控制台接入,为了支持安全审计,后台会截获用户所有在webshell的操作命令并记录入库;存储管理主要是集成公司商业的NAS存储,为容器直接提供数据共享和持久化;应用商店主要是通过kubernetes的operator提供开发和测试使用的场景中间件服务。
十一、落地实践
11.1 docker不是虚拟机
在容器推广的初期业务开发人员对容器还不是很熟悉,会下意识认为容器就是虚拟机,其实他们不仅是使用方式的区别,更是实现方式和原理的差异,虚拟机是通过模拟硬件指令虚拟出操作系统的硬件环境,而容器是在共享内核的前提下提供资源的隔离和限制。下图展示了4.8内核中linux支持的7种namespace。
换句话说,其他的都没有差异,譬如,时钟,所有容器和操作系统都共享同一个时钟,如果修改了操作系统的时间,所有容器都时间都会变化。除此之外,容器内proc文件系统也是没有隔离,看到的都是宿主的信息,这给很多应用程序带来困扰,JVM初始的堆大小为内存总量的1/4,如果容器被限制在2G的内存上限,而宿主机通常都是200+G内存,JVM很容易触发OOM, 解决方案通常是启动时根据内存和CPU的限制设置JVM,或者借助lxcfs等。
Cgroup的资源限制目前对网络和磁盘IO的限制比较弱,v1的cgroup只支持direct IO的限制,但实际的生产环境都是些缓存的。目前我们也在测试cgroup v2关于IO的限制。当最新的CNI已经支持网络限速,结合tc可以很好的达到这个效果。
11.2 Kubernetes优化
Kubernetes自带了很多调度算法,在启动容器之前会通过调度的算法,这些算法都是需要过滤所有的节点并打分排序,大大增加了容器的部署时间,通过删除一些无用的调度算法,从而提高部署的速度。容器采用反亲和的策略,降低物理机故障对服务造成的影响。
虽然kubernetes开启了RBAC,但kubernetes token还是不建议挂载到业务容器内,通过关闭ServiceAccountToken提升系统的安全。
Docker镜像存储使用direct-lvm的方式,这样性能更优,在部署的时候划分单独的vg,避免因为Docker问题影响操作系统。通过devicemapper存储限制每个容器系统盘为10G,避免业务容器耗尽宿主机磁盘空间,容器运行时需要限制每个容器的最大进程数量,避免fork炸弹。
Etcd里面记录了kubernetes核心数据,所以etcd个高可用和定时备份是必须的,在kubernetes集群超过一百个节点以后,查询速度就会降低,通过SSD能够有效提升速度。本系统在kubernetes之外通过数据库保存服务和
关注证书的有效期,在部署kubernetes集群时候,很多都是自签的证书,在不指定的情况下,openssl默认一年的有效期,更新证书需要非常谨慎,因为整个kubernetes的API都是基于证书构建的,所有关联的服务都需要修改。
十二、总结
Docker容器加K8S编排是当前容器云的主流实践之一,宜信容器集群管理平台也采用这种方案。本文主要分享了宜信在容器云平台技术上的一些探索和实践。本文主要包含了Nginx自助管理、 多集群管理、DNS解析、网络方案、CICD服务编排、 日志监控、kubernetes 优化一些技术工作,以及宜信内部容器云平台化的一些思考,当然我们还有很多不足,欢迎各路英雄来宜信进行深入沟通和交流!
作者:陈晓宇
来源:宜信技术学院
基于kubernetes自研容器管理平台的技术实践的更多相关文章
- 腾讯基于Kubernetes的企业级容器云平台GaiaStack (转)
GaiaStack介绍 GaiaStack是腾讯基于Kubernetes打造的容器私有云平台.这里有几个关键词: 腾讯:GaiaStack可服务腾讯内部所有BG的业务: Kubernetes:Gaia ...
- [转帖]两大容器管理平台,Kubernetes与OpenShift有什么区别?
两大容器管理平台,Kubernetes与OpenShift有什么区别? https://www.sohu.com/a/327413642_100159565 原来openshift 就是 k8s的一个 ...
- 容器云平台No.1~基于Docker及Kubernetes构建的容器云平台
开篇 最近整理笔记,不知不觉发现关于kubernetes相关的笔记已经达99篇了,索性一起总结了.算是对这两年做容器云平台的一个总结,本文是开篇,先介绍下所有用到的组件.首先来看下架构图(实在画的太丑 ...
- Rancher 容器管理平台-免费视频培训-链接及内容-第三季
Rancher 容器管理平台-免费视频培训-链接及内容 第三季 第5期-2018年05月10日-持续集成的容器化实践回放网址:http://www.itdks.com/liveevent/detail ...
- 【原创】基于Docker的CaaS容器云平台架构设计及市场分析
基于Docker的CaaS容器云平台架构设计及市场分析 ---转载请注明出处,多谢!--- 1 项目背景---概述: “在移动互联网时代,企业需要寻找新的软件交付流程和IT架构,从而实现架构平台化,交 ...
- 企业级rancher搭建Kubernetes(采用rancher管理平台搭建k8s)
一.简介 Rancher简介 来源官方:https://www.cnrancher.com/ Rancher是一个开源的企业级容器管理平台.通过Rancher,企业再也不必自己使用一系列的开源软件去从 ...
- 企业级容器管理平台 Rancher 介绍入门及如何备份数据
企业级容器管理平台 Rancher 介绍入门及如何备份数据 是什么 Rancher 是一个为 DevOps 团队提供的完整的 Kubernetes 与容器管理解决方案的开源的企业级容器管理平台.它解决 ...
- Docker容器管理平台Rancher高可用部署——看这篇就够了
记得刚接触Rancher时,看了官方文档云里雾里,跟着官网文档部署了高可用Rancher,发现不管怎么折腾都无法部署成功(相信已尝试的朋友也有类似的感觉),今天腾出空来写个总结,给看到的朋友留个参考( ...
- 一个简单易用的容器管理平台-Humpback
什么是Humpback? 在回答这个问题前,我们得先了解下什么的 Docker(哦,现在叫 Moby,文中还是继续称 Docker). 在 Docker-百度百科 中,对 Docker 已经解释得很清 ...
随机推荐
- python 参考知识点
本笔记仅作为有编程基础的童鞋在学习python时的参考资料,不适合零基础小白,并假设在你的电脑上已经正确安装了python环境,windows下需要配置环境变量,可以在终端窗口中执行以下命令 set ...
- Python|网页转PDF,PDF转图片爬取校园课表~
import pdfkit import requests from bs4 import BeautifulSoup from PIL import Image from pdf2image imp ...
- Python自学day-8
一.SocketServer 简化了编写网络服务器的难度. SocketServer一共有如下几个类型: socketserver.TCPServer :提供一个TCP的socketserver. s ...
- ssm中mapper注入失败的传奇经历
最近因为要测试一个功能,需要用最短的时间来启动服务,开启测试程序,但平常所用的框架中已经集成了各种三方的东西,想着那就再重新搭建一个最简单的ssm框架吧. 搭建可参考:简单ssm最新搭建 搭建过程并不 ...
- php对象在内存中创建于释放
<?php /** * 1.对象的创建占用内存, * 对象内存释放,析构方法就是在对象释放前运行最后的一步.可以自动释放和手动释放 * 手动释放:通过unset($p);来释放对象,在这个时候会 ...
- Spring Bean 生命周期之“我从哪里来?” 懂得这个很重要
Spring bean 的生命周期很容易理解.实例化 bean 时,可能需要执行一些初始化以使其进入可用 (Ready for Use)状态.类似地,当不再需要 bean 并将其从容器中移除时,可能需 ...
- resolv.conf 的超时(timeout)与重试(attempts)机制
/etc/resolv.conf 有两个默认的值至关重要,一个是超时的 timeout,一个是重试的 attempts,默认情况下,前者是 5s 后者是 2 次.这个估计很多工程师都不是很在意,一般情 ...
- ORA-06502:at "WMSYS.WM_CONCAT_IMPL",line 30 解决方法整理
之前数据量少的时候,用:select wm_concat(字段) from 表 拼接数据量小的话,没有问题,数据量超出4000个就会爆以下错误信息: 解决方法(Oracle 函数xmlagg拼接): ...
- python数据库-安装问题总结(48)
一.ERROR1698(28000):Access denied for user root@localhost错误 我的操作系统是ubuntu: 我的MySQL版本是: 安装完成后,登录mysql的 ...
- Jenkins+GitLab+Docker+SpringCloud+Kubernetes实现可持续自动化微服务
现有混合云平台的场景下,即有线下和线上的环境,又有测试与正式的场景,而且结合了Docker,导致打包内容有所区分,且服务的发布流程复杂起来,手工打包需要在编译阶段就要根据环境到处更改配置,因此纯手工发 ...