TOP100summit分享实录 | JFrog高欣:Kubernetes is hard!JFrog的Kubernetes实践
本文内容节选*msup主办的第七届TOP100summit,JFrog架构师高欣分享的《Kubernetes is hard!JFrog的Kubernetes实践》实录。
本文为JFrog架构师高欣在TOP100summit上的演讲实录。分享者高欣专注DevOps解决方案,以及企业DevOps 转型,曾在IBM服务近十年,带领团队致力于DevOps领域产品,及公有云服务的研发、运维、服务及推广等,在软件产品和云服务的开发与运维、持续集成及交付、DevOps 等领域具备丰富的技术积累和实践经验。
编者按:2018年11月30日-12月3日,第七届全球软件案例研究峰会在北京国家会议中盛大召开,现场解读2018年「壹佰案例榜单」。本文为JFrog架构师高欣老师分享的《Kubernetes is hard!JFrog的Kubernetes实践》案例实录。
在Kubernetes中部署和运行应用,真不是印象中那么轻松简单。JFrog目前可以做到每周自动化部署100+的不同产品线、任意版本组合的测试环境,而每个环境都要部署50+的微服务。而在达到这样的部署规模的过程中,我们遇到了足够多的问题,也积累了很多的经验和教训。在这次案例分享当中,我们将基于JFrog自身落地实践的总结,介绍JFrog是如何从准备开始,一步一步实现应用在Kubernetes环境中的成功部署的。
希望大家不要在这个领域选择做一个孤胆英雄,我们要学会善用团队的力量、别人的成果、专家的辅助把企业内部的Kubernetes实践做好。
背景回顾
最早我们发布一些应用都是直接发布在服务器上,但这会导致成本过高和服务的扩展、迁移非常困难;接着慢慢的发展到虚机上部署,相比原来在维护性、可迁移性上得到了提高,但因为每个虚机都要维护一个独立的虚拟操作系统,还是有些不方便;接着,容器技术的诞生和使用,使得应用的部署和迁移更加方便快捷;再后来,应用逐步微服务化,应用的部署也就从一个大的容器,变成了多个容器一起提供服务的模式,也就是容器的集群。而容器集群的部署相对复杂,我们需要相应的编排工具、系统支持,Kubernetes就是当前这一领域大家使用比较多的环境,来帮助我们做容器集群化的部署。但是真正把Kubernetes用到生产环境中很难,我们在内部做了Kubernetes的实践,主要目标是把已经做好的应用(包括现在新的开发应用),部署到Kubernetes环境中。今天我分享的实在这个过程中碰到的一些问题以及积累下的实践经验,希望能给大家带来更多的启示。
我先简单解释一下如何真正去做Kubernetes实践。当我们准备应用的时候,并不是简单地把现有应用装到几个docker就好,在部署之前,我们一定要把Kubernetes环境当中运行环境、运行参数,部署方式等问题做一个详细的计划。当我们真正执行的时候,要借助一些工具使整个部署环境更加的方便、可控。当然,在部署完成后,我们要做一个监测以便掌握它的运行状况。整个运行流程需要能够复用,按需自动运转(以流水线的方式)。
JFrog内部的Kubernetes实践
JFrog内部要解决什么样的问题?
•如何能够快速搭建JFro*品的全功能测试环境(无论规模大小)?
•当开发上百个分支时,我们如何为每一个分支提供独立的CI/CD流水线支撑?
•如何利用我们现有的硬件资源?
•如何为JFro*品提供新的交付方式?
下面我们来看看JFrog如何一步步解决以上的这些问题:
1、起步:小处入手
从一个很小的Kubernetes环境入手,先熟悉Kubernetes所有的特性(命令、组件,以及如何工作等)。这些不止可以从生产环境中获得,我们可能会做一些破坏性的实验。我们有很多的资源可以获得一个能够学习、实验的环境,例如,公有服务、私有化部署以及自己探索。
当有了一个真正的Kubernetes环境后,我们要从一个很小的示例应用开始部署。如Nginx,而每次我们可以试验和考察某个具体的特性,如它如何扩容、如何重启,或者对外开放一个API等。这个过程中可以充分利用现有的各种教程和演示材料。
2、准备:调整应用
把应用装进docker是远远不够的,你的应用要做相应的设置和改进去适应Kubernetes部署的特性。首先,要考虑如何处理足够多的日志文件,再分析哪些数据需要持久化存储,然后合理的处理sigterm信号,最后,要保障在上一次运行的遗留数据。
除了应用本身之外,Kubernetes的一个应用部署—高可用是新的标准配置。我们要做到应用改造后,在高负载情况下,让它保持良好的持久性和可用性;在负载均衡下,支持多个实例同时运转,根据实际应用的负载情况,能够非常顺畅地做扩容、缩容;多个应用实例进行滚动升级的过程中,新旧两个版本同时运行不会造成应用的误解或中断,等等。除了应用本身,我们还要考虑Kubernetes环境可能出现的问题。例如,Node正常维护的时间段,应用如何保持高可用,提供持续的服务;Node意外中断了,应用如何处理这些计划外的问题,继续提供服务,这都是我们额外要准备的。
3、规划:配置运行环境
在正式部署前,还要考虑如何规划并配置好运行环境。而运行环境最重要的一个问题就是运行环境的资源,所有的限制都要考虑清楚。一定要限制Pod本身的资源,防止一个Pod占用了整个Node的资源。同时,应用本身也需要资源限制。之前的服务器、虚机、单独的docker部署,大家可以注意到,我需要控制应用部署和限制资源。现在在Kubernetes环境中,应用部署在Pod,Pod部署到Node,如果不做资源限制,当真正运行时就会影响到同一Node上其他的Pod中的应用。此外,应用的运行状态必须有可信的健康数据。在配置应用的时候,我们要通过各种各样的方式,判断应用的运行状态是否正常。因此,我们要安装一个探针,类型根据我们应用的特点,脚本正常反馈是0,说明脚本运行正常,这个探针反馈就是正常,我们也可以用HTTP,回复给我一个正常的return,说明是正常的服务。同时,还可以开放一些特定的端口,连接这个端口,是不是能够很好的连上,能够得到特定的回应,这些都是大家去规划整个Kubernetes部署环境的时候,要去充分考虑的。
4、部署:编排部署
真正部署的时候,要利用yaml文件编排应用,多个组件、模块,对应多个yaml文件;这时候考虑应用的版本化该如何管理?这里给大家推荐一个工具—Helm,
它原来是Kubernetes内部的子项目,现在已升级成为CNCF基金会的专门项目,专门负责协助容器集群化的部署。
上图中左边的饼状图是JFrog和客户做的一个统计,从左图可以看出只有5%的客户在他的生产环境中用的Kubernetes。右边的饼状图是一个关于有多少人用Helm去做Kubernetes部署的统计,也是5%。
这两个数据绝对不是巧合,这是因为Helm大大方便了Kubernetes的部署。
那么,Helm是什么样的呢?
图中可看出,在templates中包含了所有yam,下次部署一个应用到底部署多少yaml,不会多也不会少。刚才讲到版本化专门会有Chart.yaml去描述,整套是哪一个版本,包含哪些东西,当其中一些组件发生了新的变化时,会生成一个新的版本,这样再去部署一个应用的时候,就会非常清晰的知道所有的变化记录。
刚才讲到的配置数据,我们目标环境配置的数据怎么办呢?在部署yaml里,每一个环境都有对应的values.yaml,部署时就可以指定用哪个Values,这样保证了所有应用的yaml,只考虑我的应用该如何去部署,不用考虑特定的目标环境,真正跟目标环境集成是在values.yaml,也就是说一次开发可以做多次部署。
Helm Charts有很多公共的数据库,这样一些公共应用的Kubernetes部署,都有很多成熟的Chart这里,不需要从头拷贝或重写,直接引用就可以了。大家开发编程的时候已经很熟悉外部依赖了,利用Helm,容器化部署的编排也可以作为代码处理,我们有版本、有依赖,可以很方便的应用别人已经成熟做好的Charts,不需要重复这些工作了。
Helm专门有一个仓库,存储公共的Charts。使用这个公共仓库,就可以把已经成熟的Charts直接做部署或引用到你的Helm Chart中。如果想建立一个私有化的Helm仓库也可以,JFrog本身有一个全语言的制品仓库——Artifactory,各种开发语言的交付包、依赖包,包括Helm Charts,都可以存储在本地的Artifactory当中。有了这个本地仓库之后,我们就可以把这些公共的Helm Chart带回本地,下次使用的时候,你的代码、依赖、编排都可以直接在一个仓库当中拉取。
Helm也提供了很多很好地客户端命令,以方便我们使用。
上图中列出了一些命令。这些命令其实不是真正部署环境时使用的Helm命令,而是辅助大家做一些检查的命令。在使用Helm Charts部署时,可以利用这些命令做验证,检验部署是否正常。
5、监测:跟踪部署
部署应用就要像放风筝一样,虽然飞的很高、很远,甚至可能看不见了,但我手中还是有根线,我能够知道现在的状态和位置,当有问题时,我能够收回并处理。Kubernetes应用部署也是一样。在Kubernetes环境中,很多情况都是自动处理的,如扩容、重启、迁移等,所以监控是非常重要的,要能正确地掌握应用的运行状态。大家可能会说,应用监控谁不会啊,我做了这么多年应用部署。但在Kubernetes环境中,有一个重要的问题,就是很多原有的监测手段不适用了。如传统的运维手段是直接ssh到有问题的服务器上去查看,但是在Kubernetes环境里ssh已经无法使用了,因为IP是动态分布的,根本不知道机器布在哪里,无法跟踪到具体的哪一个pod,哪一个docker上。所以,在Kubernetes环境下,我们要用一些新的监控手段,我们要让开发、运维能够随时访问到应用的运行数据和状态信息,以便更好地看到目前的运行态、时序化的数据,同时可以看到日志,出问题时可以记录下来。
另外,还要注意的是,我们尽可能要提供一个Out-of-Band这样的工具帮助检测。让应用只是做应用相关的东西,监测的工具是用其他的方式来提供给开发和运维。
监视是给大家提供应用运行态的时序化数据(一些具体的参数)。最基本的是运行状态、内存、存储、性能等数据。这个很直观,但是,我们应用要去考虑如何把状态传递出去。我们有很多探针,很多日志文件,包括我们一些状态,也应该提供一些时序化的方式,随时把运行状态信息传递出来。不仅仅是周边环境的状态、应用自身的状态,也应该提供这种时序化的方式,比如当前流量进来的多少,应用自身性能的高低等。这就对应到我们前面设计的探针,才能把时序化的数据拿出来。
如何传递数据?放在pod或docker都不合适,因为它们很可能会自动销毁或迁移。那么,我们辅助的方式要如何跟监测系统连接起来呢?首先,把需要的数据取出来。时序化监测用的比较多的是Prometheus、Grafana,提供时序化的数据和进行可视化的展示。这是我们监视的方式之一,能够随时随地了解应用运行的状态,包括整个运行环境中的关键数据。
除了运行态的时序数据外,我们讲了日志也是非常重要的,但这个地方日志就能再放在原来的docker或pod中,我们要把它传出来放在一个集中的系统中展示,这也回应到刚才应用改造的部分。我们在最开始改造应用的时候,我们规划部署环境时就要考虑日志如何记录、
扩/缩容后如何记录等问题。这并不是记录几个文件的问题,而是要考虑哪些内容需要记录下来,如何展示给开发、运维使用。
EFK是比较主流的方式,Fluented做数据的收集,Elastic Search做数据的存储和索引,Kibana做日志的显示;另一个更传统的方式是,日志收集比较多时,我们在EFK之前放一些Kafka,提供数据的缓存。
这些架构有很多成熟的案例,大家可以详细参考。不管时序化数据还是日志,都要从应用的改造,到规划环境,再到这个监视的系统,结合Kubernetes各种环境,做好充分的规划与考虑。
我们应用的目标是建立测试环境,所以采用了上述的监测方案。而在最终的生产环境中,我们可能还要监测微服务,即对应用最终的服务状态进行监测。这里我们要注意的一些问题,大家可以参考一下:
第一点,做监测,不仅仅是监测Kubernetes环境,容器内部运行的应用同样去监测。刚才讲到的探针,监测的时序化数据、日志等都在监测范围之内。
第二点,业务自身的性能。这些性能要从数据中体现,Kubernetes开发环境、pod系统只是一个参考,不代表应用自身的性能,我们要考虑应用自身性能如何监测。
第三点,监测具有弹性,以及多地部署的服务。这样的服务该如何设计监测,需要充分考虑。
第四点,服务之间通过API沟通和连接的。API的状况如何监测,使用情况、性能情况、有没有不可达等问题,都是需要关注的。
第五点,微服务的监测体系要匹配组织架构。真正把微服务提供给客户时,我们要做监测。如何呈现所有的监测数据,这是跟整个组织架构的管理方式、管理原则紧密相关的。大家应该都听过康威定律,所有的研发工作最后呈现出的内容都是和组织架构相关的。这不是说一种方式所有的企业都要适用,而是要根据自身的需求和管理要求去调整。
6、流程:复用、自动
这一步要考虑的是让流程能够复用,而且一定要让整个流程自动地运转起来。我们做了一个Kubernetes流水线,刚才讲的所有相关这些规划、环境的设置以及我们的应用(用Helm Charts去描述),如何部署环境和应用配置,集成所有的内容,我们都把它们串联成一个流水线。这样,包括每一个分支开发后,都可以自动生成CI/CD流水线。而有了测试需求之后,也能够快速部署相应的测试环境。
整个流水线的搭建,核心是自动化流程和编排驱动的工具,包括了JFrog的全语言制品仓库Artifactory,和安全漏洞扫描工具Xray。JFrog的这些产品本身就是为CI/CD流水线服务的,其能力在我们的实践中也得到了考验和验证。
使用全语言制品仓库Artifactory,所有涉及的代码包、依赖包以及编排的Helm Charts都放在一个仓库里处理,从运维、管理、使用方面来讲非常简便。而且,Artifactory仓库本身是支持企业级高可用的,高可用、高并发、异地复制同步、容灾备份等都有成熟、可靠的方案,能够保证流水线正常、可靠、持续地运转,对整个后台的测试和开发非常有益。
目前,我们能够为JFrog每个产品、每个分支,按需提供完全独立的测试环境;每周部署100+不同产品线、任意版本组合的测试环境,每次部署超过50种微服务。
7、协作:善用社区
现在的开发是一个协作的时代,不可能一个人把所有事情搞定。所以,要善于用社区的力量。
①在社区里你遇到的问题,很多人早就碰到并解决了。你不需要重复的从头解决了,要多和他人沟通,了解他们是如何解决难题的。
②在社区里有非常多的专家和高手。善用社区就能充分借助高手的力量帮你解决问题。
结语
大家既然选择了IT这个行业,就要做好一切的准备。Kubernetes既是趋势也是挑战,目前为止还没有出现像插头插上去就有电这样方便快捷的应用。我希望能通过JFrog的案例实践,带给大家更多的思考!
上一篇: 自己eclipse中遇到的问题记录贴
下一篇: 一些java二进制的相关基础知识