DockOne微信分享(二三九):Kubernetes在信也科技的落地实战


【编者的话】信也科技(拍拍贷)是一家服务于全球的金融科技平台,总注册用户数超过1亿。国内业务覆盖全国97%的城市和乡村,国际业务覆盖有印尼、菲律宾、越南和新加坡等国。为了更好的支撑信也科技业务的高速迭代,我们在2018年底上线了基于Kubernetes和Docker的容器云平台。截止到目前,已经超过有430多个应用采用了容器部署,总实例超过4000,总共维护了8套Kubernetes集群。本文主要介绍Kubernetes在信也科技落地的一些经验和思考。

信也科技容器化背景

信也科技(拍拍贷)在2016年前大部分使用的技术都是微软.net平台的技术栈,这个时期部署的都是那些巨大而且笨重的单体应用。这些应用通常都没有明确的业务领域划分、系统耦合太严重。随着公司规模和业务体量的快速增长,那些笨重的单体应用由于结构复杂、迭代周期长、部署缓慢、无法进行回滚以及灰度发布等问题,已经无法满足业务的高速迭代的要求。
1.png

所以从2016年开始,信也科技内部开始做系统拆分,同时开始进行.net转Java的技术栈转型。系统拆分之后,各应用的业务领域划分更加明确,应用也更加的瘦身。各个应用通过明确的接口定义进行交互。每次业务的迭代只需更新部分应用,迭代周期可以控制在周甚至是天。
2.png

但是系统拆分也不是银弹。拆分之后,应用数都会有个显著的上升。有时甚至每周都会有创建新应用和销毁旧应用。在应用数上升到一定规模后,发布效率开始下降。
3.png

信也科技之前如果有新应用上线,需要在测试环境、预发环境和生产环境各配置一套Jenkins发布脚本。发布脚本里面都是些繁琐复杂的shell指令。同时在测试和预发环境,每个团队都要维护自己的一套Nginx,供自己的服务给其他人访问。研发和测试人员的大量时间花在了应用部署上面,而且这些都是低价值的事情,给公司造成人力资源的浪费。
4.png

为此,一个好的应用交付系统迫在眉睫。在2018年,容器技术已经发展了5年多,技术日趋成熟。同时Kubernetes在容器调度领域有一统江湖之势。公司决定使用Kubernetes和Docker技术构建基于容器的下一代交付系统。

网络选型

Kubernetes落地首先要解决的就是网络的选型。Kubernetes支持的网络插件有很多,比如:Flannel、Calico、Weavenet等。刚入门的人可能无从下手。选择哪种网络需要考虑到现有应用的部署构架以及应用的使用网络的方式。比如:容器部署的应用如何和现有的应用进行网络互访?网络是否可以满足每个应用实例使用需求?

从网络本身来讲主要分为underlay网络和overlay网络。这2种网络有如下特点:
5.png

信也科技在网络选型的时候考虑到之前的应用都是部署在虚拟机上面,大多数的应用都要从虚拟机迁到容器。网络需要兼容应用在虚机的使用方式以及支持虚拟机和容器的互访。同时考虑到信也科技在Kubernetes项目投入的人力资源只有3人,简单和高效也是我们考虑的因素。为此我们决定使用Macvlan作为Kubernetes的网络模式。Macvlan最大的特点就是每个容器都有自己独立的IP和MAC地址,这样可以很好的兼容应用在虚拟机里面对网络的使用方式。
6.png

而且Macvlan的设置简单,使用一行命令即可完成创建。采用VLAN方式创建之后,一台宿主机可同时支持多个网段。如果使用了VLAN的话,宿主机一定要接到交换机的trunk端口。
7.png

镜像仓库

镜像仓库我们使用的是Docker官方提供的镜像仓库,镜像存储用的是Ceph。我们额外开发了一个代理服务,拦截了镜像仓库的所有API请求。在代理服务里面我们做了用户认证以及对上传和拉取镜像做了权限的控制和操作审计。 同时记录了各个应用每次上传镜像的名称和版本。用户可以使用docker login登入镜像仓库后手动docker push进行镜像的推送。也可以使用token集成到CI系统里面进行推送。

我们对镜像的命名采用的是应用名+代码分支名+打包自增ID,可以很方便的选择哪个分支、哪次构建的镜像进行部署。
8.png

CI / CD

CI就是把代码打包成可以运行的镜像。由于我们大多数的应用都是Java应用,我们改造了Spotify公司开源的Maven打包插件进行镜像打包。添加了上传权限控制、默认使用分支名作为镜像版本、自动添加打包序号等功能。用户只需在pom文件里面填了的插件,就可以直接使用mvn打包命令进行镜像打包和上传了。方便用户在本地或者使用Jenkins构建镜像。
9.png

CD的话我们在Kubernetes上面开发了一个容器发布平台,对用户封装了所有的Kubernetes使用细节。我们的容器发布平台支持从开发、测试、预发和生产的全环境部署。支持按应用维度进行容器的创建、重启、销毁,以及实例维度的上下线操作。用户在测试环境打包镜像并且测试通过之后在预发和生产就可以使用该镜像进行发布。
10.png

容器发布平台支持蓝绿部署和滚动更新的方式进行版本升级。蓝绿部署可以在我们平台里面可以创建2个发布组作为蓝绿组,流量在2组间切换可以方便的进行版本更新和回滚。滚动更新就跟Deployment的更新方式一样,按批次对实例进行升级。
11.png

容器发布平台都是基于Kubernetes中的Pod进行部署的。各个Pod通过发布组或应用进行分组。我们之所以没有使用Deployment进行部署是因为Deployment的控制逻辑过于复杂和限制。因为我们需要经常针对单个Pod进行重启、上下线、销毁以及版本更新等操作。如果使用Deployment的话这些就无法做到了。Pod也是Kubernetes中最简单的部署单位,并且也足够静态,不用担心Kubernetes在有些情况自动对Pod进行操作,这些操作有些可能不是我们所期望的,甚至会带来生产的故障。

使用Java自研高可用组件

上文中已提到我们只使用了Kubernetes中的pod进行部署,虽然简单但是也无法享有Kubernetes带来的自动恢复特性。同时我们需要定制化符合我们操作习惯的自动恢复逻辑。由于团队成员都是Java出身,我们就使用了Java语言实现了一个高可用组件,支持容器的宕机恢复和物理机的宕机迁移。该组件集成在了我们的容器发布平台中。

高可用组件使用fabric8提供的kubernetes-client去向apiserver监听endpoints事件。信也科技要求所有的应用都必须实现一个健康检测接口,这样我们可以在Pod上面添加一个Readiness探针。kubelet就会不断地调用健康检测接口并上报结果到apiserver。我们根据endpoints中的NotReady实例状态,去触发一个删除Pod和重新部署Pod的任务。我们使用了推拉结合的方式获取endpoints事件的方式,这样就保证事件不会丢失。同时如果用户正在操作实例的话,那我们就对该实例忽略高可用的处理。目前该组件已经在生产完成了实例宕机和物理机宕机的考验,表现良好。
12.png

虚拟环境支持

在信也科技,我们有多个测试环境用来支持同时多个业务的并行迭代测试。如果对每个测试环境都单独部署一套Kubernetes集群,这样成本太大。为此我们在一个Kubernetes集群上构建出了多个虚拟环境,每个虚拟环境包含了部分或所有应用。由于信也科技中的大多数应用都是通过域名和Nginx的方式对外提供服务的,为此我们基于CoreDNS,实现了一个MySQL的DNS记录维护插件。每个虚拟环境启动一个CoreDNS服务和Nginx服务,在这个环境下的所有pod启动时都会绑定这个DNS服务器的IP。本环境下所有的域名都会解析到该环境下的Nginx的IP,从而达到环境隔离访问的效果。
13.png

其他

在实践的过程中我们还是遇到了蛮多问题,给大家依次分享下:
  • Java程序无法正确识别到容器内存和CPU数量。如果没有手动设置堆大小的话,默认会使用宿主机内存的四分之一,超过容器内存规格大小的会直接造成容器宕机。同时JVM获取到的CPU核数也是宿主机的,这样如果有根据CPU核数创建线程的代码都会根据错误的数量来创建,造成程序运行的不稳定。这2个问题可以通过使用LXCFS文件系统和把JDK的版本升级到8u212以上版本解决。
    有些应用使用短连接去请求,如果调用量很大的话会造成端口的不够用,需要在容器里面调下tcp的内核参数扩大可用端口数量。
    使用LXCFS和修改内核参数可以在Pod上面添加如下设置:
    14.png
  • Kubernetes证书过期问题。我们当时安装Kubernetes的时候证书的过期时间设置成了1年,造成1年之后因为证书过期造成整个集群的不可用。需要重新生成证书,在Master和Node节点上依次更新证书。证书更新过程会中会造成集群的不可用,但不会影响已运行的实例。信也科技已经在生产更新过证书。
  • 宿主机高负载运行触发了Docker 1.13的bug。由于对测试环境开启了资源超配,一台宿主机经常会运行超过200的实例,由于测试环境需要不断地发版测试,操作频率也比较频繁。所以就触发了Docker 1.13的各种奇怪的问题,比如:containerd挂了无法自动恢复、容器进程停止但是docker ps容器实例还在等问题。 目前我们是通过把测试环境Docker版本升级最新版本解决的。
  • 宿主机CPU load莫名飙升,有大量的kworker进程使用CPU高达80%以上,造成机器无法使用。这个在我们的测试和生产环境的机器上都有出现,当时困扰了我们好久。我们发现问题都出现在HP的一批物理机上面,排查来下是跟CPU的运行模式有关。这些机器会根据当前使用情况动态修改cpu的主频,造成机器的不稳定。我们通过修改/sys/devices/system/cpu/cpu0/cpufreq/scaling_governor内容为performance,将CPU频率固定工作在其支持的最高运行频率上,不动态调节。


Q&A

Q:DNS记录是如何维护的,还有Macvlan的记录的维护?
A:DNS系统我们实现了2个服务,一个是监听在53端口提供DNS查询的服务,一个是前台管理站点,前台站点负责DNS记录的增删改查。支持单独设置和批量导入功能。这2个服务共享同一个数据库。内容的话是由信也科技各个研发团队共同维护的。Macvlan是在每台宿主机上创建的。我们一般会在每台宿主机上创建多个Macvlan网段。

Q:Macvlan是没有Service,选择Macvlan是基于哪些考虑呢?Macvlan使用过程中,对于不同的内核版本,不同的高可用组网,是存在兼容性问题的,这一块实践能分享下么?
A:选择Macvlan一是因为它的简单,使用docker命令就可以创建出来,不需要其他配套的服务或数据库来管理。二是因为它有独立的IP和MAC地址,这样可以让信也科技之前跑在虚拟机上的服务能够快速的迁移到容器。我们对于宿主机的内核版本是严格控制的,不存在内核版本不同的情况。但是Macvlan的缺点也比较明显,它依赖于硬件,宿主机需要连到交换机trunk口。并且它的灵活性也不够高,不适合大规模的组网。由于目前信也科技内部的网络结构还是比较简单的,并没有遇到兼容性的问题。

Q:为什么不试着对Kubernetes自动更新呢,每一次手动更新都需要一定的时间成本吧?
A:目前我们认为手动更新比较稳妥,并且更新不是一个频繁的操作,时间成本还好。

Q:请问下,这个是自建机房环境上的集群?是否适用公有云环境?外部访问流量是如何接入的呢?Ingress Controller基于什么考虑来选择的,谢谢。
A:这个是自建机房环境上的集群。外部的流量会先经过F5,然后经过Nginx集群,所有的容器实例和虚拟机都是通过Nginx负载均衡的。在Nginx上面我们使用了新浪微博的nginx-upsync-module模块,可以从Consul同步upstream中的实例。我们并没有使用Ingress Controller,而是通过用户在我们的容器发布平台上去手动的拉入和拉出流量。用户拉入流量的操作会在Consul里面添加实例的IP和端口,Nginx自动从Consul同步实例后该实例就接入流量了。

Q:直接使用Pod的话,副本控制是如何做的?
A:副本控制目前是比较静态的。用户在容器发布平台部署可以选择副本数。此后如果用户不添加和删除实例那么副本数是不会变的。

Q:如何更新证书?
A:先重新生成证书,然后先在Master节点上更新,需要依次重启etcd、apiserver、controller-manager和scheduler服务。Master更新完毕后,再把所有的Node节点上证书更新一下,需要重启kubelet。证书的更新过程中除了造成集群的短暂不可用之外不会影响已经运行的容器的,所以是安全的。

Q:蓝绿发布和灰度发布是如何实现的?
A:这2个都是通过我们的容器发布平台实现。蓝绿发布是通过创建2个发布组,每个发布组含有相同的实例数。通常一个发布组含有当前版本的实例并且是接入流量的,另外一个发布组包含上一版本的实例或者是即将上线版本的实例。通过在2个发布组切换流量来上线新版本或回滚到旧版本。灰度发布可以先上线一个实例的流量,没问题之后可以把剩下的实例都接入流量。这些操作目前都是平台上用户手动操作实现的。

Q:集群平台的高可用是怎么做了?有没有做多集群多活或者灾备?
A:我们生产环境有部署多个Kubernetes集群,也有2个不同的机房部署。我们的容器发布平台会把实例均衡分发到不同的Kubernetes集群。

Q:开发测试环境的镜像仓库如何同步到生产镜像仓库?
A:镜像仓库我们测试和生产用的是同一套。

Q:问一个细节问题,请问Kubernetes集群扩容是通过什么手段实现的?
A:我们实现了一套Ansible脚本去实现自动添加Node节点。

Q:想问下你们目前是前后端完全分离的么?目前的前端应用部署方式是怎样的?如何控制一些前端的发布工作流?以及与前端相关的后端微服务部分,是如何保证发布顺序以及关联性的。
A:目前我们上容器的还是以Java为主的后端服务偏多。目前能了解到的是前端应用都是放到Nginx中来对外提供服务的。对于前端发布的工作流以及如何保证发布顺序以及关联性的目前都是通过人肉去控制和完成的,没有做到自动化。

以上内容根据2019年12月3日晚微信群分享内容整理。 分享人张轶丛,信也科技基础框架部架构师。DockOne每周都会组织定向的技术分享,欢迎感兴趣的同学加微信:liyingjiese,进群参与,您有想听的话题或者想分享的话题都可以给我们留言。

0 个评论

要回复文章请先登录注册