共计 6289 个字符,预计需要花费 16 分钟才能阅读完成。
本文内容节选自由 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 内部要解决什么样的问题?
•如何能够快速搭建 JFrog 产品的全功能测试环境(无论规模大小)?
•当开发上百个分支时,我们如何为每一个分支提供独立的 CI/CD 流水线支撑?
•如何利用我们现有的硬件资源?
•如何为 JFrog 产品提供新的交付方式?
下面我们来看看 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 的案例实践,带给大家更多的思考!
以上内容来自高欣老师的分享。
声明:本文是由 msup 原创,转载请联系 meixu.feng@msup.com.cn