Kubernetes在信也科技的落地实战


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

基本介绍

落地场景

信也科技是在自建机房内部署Kubernetes集群的。我们有自己的机柜、服务器、F5、交换机等设备。我们的Kubernetes是直接部署在物理机之上。我们服务的用户主要是公司内虚拟机转容器的站点。我们的研发团队大概有300~400人,超过1000+的服务数量。

当前规模

我们当前交付了8套Kubernetes集群给我们的用户。涉及到开发环境(DEV)一套、测试环境(FAT)一套、产品验收环境(UAT)一套、预发环境(PRE)一套、生产环境(PRO)四套。目前例数超过7000,累计运行了超过1年6个月的时间。

使用技术

我们目前使用了1.11版本的Kubernetes,1.13版本的Docker。我们使用了Ansible去做一些集群的安装部署工作。使用Prometheus实现了Kubernetes的监控。我们使用Java开发了一个容器发布平台,该平台对用户隐藏了所有Kubernetes和Docker的使用细节,方便用户快速上手。最后我们使用了Go语言优化了Macvlan网络插件以及实现了支持跨环境的DNS服务等小工具。

生产价值

我们集群从开始交付到运行至今还是产生了比较大的价值。首先是资源利用率的提升。从原来一台物理机上只能运行30个虚拟机到现在相同配置的物理机可以运行80个容器。比虚拟机提高了166%。

其次是发布效率的提升。所有的发布操作如部署实例、查看日志、上下线、重启实例、更新版本、删除实例等都自助化了,大大减少了研发和运维的沟通成本。因为资源利用率的提升,我们使用了蓝绿部署这种安全的发布方式。

蓝绿发布比普通的原地更新多使用了1倍的资源。它把资源分成了蓝组和绿组。接流量的只会有一组。更新版本会在没有接流量那组进行。更新完成之后,会把新版本的那组接入流量,老版本的那组下掉流量。
1.png

我们还利用了容器快速创建和销毁的特性,做了些测试环境的治理。我们现在每次迭代都会单独拉起一套环境做测试,互不影响。以前都是在一个测试环境里面做测试,经常遇到上下游服务发版导致测试阻塞,影响交付进度。

落地方案

Macvlan网络

因为我们主要的落地场景是虚拟机转容器。为了能让容器快速融入现有环境,我们使用Macvlan网络和虚拟机网络环境实现了大二层,这样容器和虚拟机可以方便的双向互通,容器也可以复用现有的Nginx做负载均衡。

Macvlan是一种直连网络,数据包通过宿主机网卡传输到硬件链路上,通过交换机路由器等设备最终到达目的地。

使用Macvlan网络的每个实例都有独立的IP和MAC地址,这和虚拟机的网络类似,使用了L2、L3协议的虚机站点也可以方便的迁移过来。

Macvlan网络是Linux内核原生支持,不需要部署额外的组件。本身包含VLAN特性,一台宿主机上面可以虚拟出多块VLAN网卡,支持多个C类地址的IP分配。此时宿主机和交换机的链路必须是trunk模式,同一链路根据不同报文内的vlanID如(10、20、30)组成逻辑信道,互不干扰。
2.png

构建了大二层网络之后,我们在上线初期容器实例可以和虚拟机实例进行混跑。如果容器实例有问题可以快速下线。
3.png

自定义IPAM

Kubernetes为Macvlan提供的原生IPAM功能太弱了。它只能给一台宿主机分配一个网段的IP范围,这样就不能重复利用VLAN的优势了。并且实例一旦从一台宿主机迁移到另外一台宿主机IP就会发生变化。由于原生只提供了配置文件的方式在每台宿主机上分配IP范围,IP资源没法其中管理,导致宿主机增多之后维护困难。

为此我们在容器发布平台里面实现自己的IPAM,替换了原生的IPAM。支持一台宿主机多网段IP分配、跨Kubernetes集群IP分配(多个集群可以共享IP范围)、实例迁移保证IP不变、静态IP功能。

实现这些功能我们改造了下原生的Macvlan网络插件,容器发布平台在发布实例的时候会给每个Pod分配一个IP。这个IP会打到Pod的label上面。改造过后的Macvlan网络会根据Pod上面的IP标签直接分配IP。

Macvlan的不能访问ClusterIP

由于采用Macvlan网络模式之后,容器里面的网络协议栈和宿主机是完全独立。这就导致容器不能使用宿主机的iptables规则从而容器里面无法通过ClusterIP去访问Service。我们目前采用的Multus-CNI网络插件在Pod里面使用Bridge模式添加了第二块网卡,并设置路由如果访问ClusterIP就走Bridge模式的网卡。
4.png

服务发现、负载均衡和流量调控

由于容器网络和现有基础设施已经打通了,我们直接复用了之前虚拟机通过DNS域名的服务发现机制,负载均衡使用了现有的Nginx。我们在Nginx集成了新浪微博的UpSync模块。UpSync模块会从Consul同步Upstream下面的实例信息。这样调节每个实例的流量就不需要执行Nginx reload命令了。

我们容器发布平台会根据用户的上下线操作,同步实例的状态到Consul集群。这样我们就可以在发布平台自助进行流量调控。
5.png

资源控制

我们目前定义了2C2G、2C4G和4C8G这三种容器部署规格。一台40C256G的宿主机上面Pod数量控制在80个。由于我们目前在Kubernetes上面运行的都是微服务Java站点,对CPU资源使用不高,我们统一对容器CPU资源做了Request=100m的资源超售。内存方面我们对副本集里面50%的实例进行了内存超售。由于80个的Pod数上限,我们对宿主机内存使用控制在85%左右。
6.png

Java 8应用上容器注意事项

在JDK8u212版本之前,JVM在容器里面识别到的是宿主机的内存。如果没有手动调整堆大小的话JVM默认会使用1/4的宿主机内存。这样会远远大于容器规格限制的内存,导致内存爆了之后容器自动重启。JVM在容器里面识别到CPU核数也是宿主机的,如果代码里面使用Runtime.getRuntime().availableProcessors()的数量去创建线程的话会使线程数过多,造成频繁CPU上下文影响程序性能。JDK8u212之后的版本对容器的支持就比较好了,可以正确识别到容器里面的内存和CPU数量。

另外我们在容器上面统一设置了编码以及时区,避免乱码和时间紊乱给程序造成BUG。

我们还在Pod上设置了net.ipv4.ip_local_port_range=1024 65535扩大可用端口范围,减少因为端口耗尽造成无法连接的问题。

稳定性保障

我们在生产总共有四套Kubernetes集群,分散在2个机房。容器平台在发布应用的时候会把副本集里面的实例均衡部署到各个Kubernetes集群中,这样防止一个集群不可用之后剩余集群可以继续提供服务。
7.png

我们的容器平台是以Pod为粒度进行发布的,因为容器平台提供了以实例为粒度的部署、版本更新、重启、上下线和删除操作。由于k8s里面单个Pod没有提供宕机恢复机制,所以我们在容器平台里面用JAVA实现了Pod高可用控制器,容器和物理机宕机自动恢复。原理很简单,我们要求使用容器部署的应用提供一个健康检测接口作为readinessProbe。容器平台监听Service下面的Endpoints事件,一旦发现Pod状态变成NotReady,我们会再次调用一下健康检测接口做一个二次检测,防止因为kubelet停止造成的误迁移。当二次检测失败之后,我们会对Pod做一个删除和重新部署操作。
8.png

这套高可用机制已在生产完成了多次实例、物理机宕机的自动恢复,表现良好。同时我们已完成了多次Kubernetes证书升级和版本升级。在升级的过程中,该机制有效地阻止了实例误迁移的发生,保障了集群的稳定运行。

容器发布平台

为什么需要有容器发布平台

我们知道在Kubernetes里面部署一个应用门槛是比较高的,需要掌握知道怎么写Deployment、Service以及Ingress的部署yaml文件。里面涉及到镜像版本选择、端口如何暴露、如何设置副本数、网络如何选择、资源如何限制、负载均衡如何设置等等。如果让开发人员去做这件事情,那么无论从学习成本或者维护成本都是非常大的。

所以我们使用Java语言自研了一个容器发布平台,对使用者隐藏了所有Kubernetes以及Docker的细节。用户只需知道镜像版本、服务端口以及副本数量就可以在我们容器平台完成一次发布。容器平台对用户提供环境选择、实例部署、配额管理以及流量调控等能力。Kubernetes提供网络通信、容器创建以及资源限制等能力。
9.png

平台特点

  • 简单:用户只需了解环境、应用和实例的概念就可以进行部署,支持全环境、多Kubernetes集群混合部署
  • 灵活:用户可以在平台自主扩容缩容实例,对任意实例进行流量调节、重启、销毁、查看日志、进入终端等操作
  • 稳定:利用Kubernetes的事件通知机制,支持实例宕机自动恢复、物理机宕机自动迁移


平台设计

10.png

发布平台里面集成了用户和组织管理,在信也科技内部我们对接了公司内部的LDAP系统,同步用户和组织信息。这样就可以方便地实现操作权限限制、资源使用审计等功能。

应用管理里面我们登记了应用的ID、名称、域名、负责人等相关信息。

在镜像管理中容器发布平台自带了一个镜像仓库服务。该服务拦截了Docker原生的镜像仓库服务的所有请求,把推送到仓库的镜像、tag和应用之间的关系保存在了数据库中。通过http接口提供按应用查询镜像版本的功能给发布平台使用。

实例管理对接了Kubernetes的Pod相关的API接口,实现了单个实例的创建、重启、更新和删除操作。同时提供终端日志的查询以及进入终端的操作。

流量管理通过Consul对接了Nginx,实现了实例级别的流量动态调节。

环境管理支持了从开发、测试、预发到生产的全环境发布。

集群管理里面我们支持一个环境下面可以把实例发到多个Kubernetes集群中,为了保证稳定性,生产环境我们把实例发到了多个Kubernetes集群中。

配额管理中我们按环境和应用的维度分配了固定数量的部署规格,每个应用在某个环境下面可以部署最多不超过配额数量的实例。

最后IP管理下面我们管理了Macvlan网络可分配的IP,这里面的IP都是属于某个VLAN网段。VLAN网段我们是在交换机那里分配的。

平台架构

11.png

容器发布平台主要有四个核心系统组成。由于容器发布平台设计到多个系统,每个系统都需要登录。为此我们基于OAuth2.0协议,实现了一个统计登录平台Pauth,它和公司的LDAP服务进行对接提供用户登录的实现。

Atlas系统主要负责管理应用、用户、组织、配额、环境以及Kubernetes集群的信息。

Dockeryard是镜像仓库,它提供应用维度的镜像上传、拉取以及查询。
Pauth、Atlas和Dockeryard都是后台系统,真正给用户展示的是Stargate这个系统。Stargate提供如下核心功能:
12.png

首先用户可以在Stargate的页面上进行蓝绿和滚动发布。上层应用也可以使用我们提供的OpenAPI实现自己的发布逻辑。实例管理是Stargate的核心功能,所有的发布操作都是利用创建、销毁、更新、重启、上下线等能力实现。Stargate直接和kube-apiserver的Pod相关的API接口对接实现容器的发布。

回馈社区

开源组件

目前我们已在GitHub(https://github.com/ppdaicorp)上面把我们容器平台的核心组件Pauth、Atlas、Dockeryard、Stargate以及我们改造过的Macvlan插件进行了开源。
13.png

访问http://stargate.icu可以立即体验我们平台的功能。在Stargate界面的Header栏里面选择一个环境之后,就可以选择应用进行发布了。下图是通过部署了2个发布组实现了蓝绿发布。
14.png

进入每个发布组,都可以对实例进行详细的操作:
15.png


作者:张轶丛,信也科技基础架构资深专家。全程参与了Kubernetes在信也科技的落地,目前支撑了超过7000的实例运行。目前专注于公司内容器云的推广和支持。

0 个评论

要回复文章请先登录注册