云原生开发经验分享:迈向云原生的10个步骤

作者:三年k班2021.10.19 15:22浏览量:404

简介:对于一个开发者团队来说,云原生意味着什么?它又能给他们的客户带来什么?

作者丨 Sarah Saunders
译者丨屠灵
策划丨辛晓亮
我们是凯捷咨询公司的开源云工程部门,主要做云原生开发。我们的一个重要挑战是帮助人们了解什么是云原生。云原生已经成了一个无处不在的热词,那么对于一个开发者团队来说,它意味着什么?它又能给他们的客户带来什么?

1 什么是云原生

作为一家托管定制软件或“COTS”(商业成品软件)的企业,只是简单地把软件部署到由云供应商提供的服务器上,并非成本效益最高的解决方案。云端的服务器通常更贵,因为其成本需要涵盖负责安装和管理硬件的工程团队以及负责管理应用程序的软件团队。云供应商会为客户提供多种不同的成本选项,让客户使用资源的方式最终是有利于供应商的。例如,如果你要了一台配备了 2 个插槽和 48 物理核心的专有 Linux 服务器,但并没有全天候或每天都使用它,那么对于供应商来说,这就是一种资源浪费。如果你同意供应商在服务器空闲的时候使用它,并增加一些外围设备,那么供应商就可以向其他使用这些资源的客户收取费用,这样效益就更高了。在这方面,有很多新奇的计费方式,比如 AWS Spot Instances,它是按需和使用量收费的。

在我们看来,云原生应用程序是部署在云端的以最大化效益为目的的应用程序。这里所说的效益指的是成本效益,就是以最低的成本稳定且可伸缩地运行应用程序逻辑,同时又能最大化处理能力。我们也考虑到了开发管道的效益——你有没有一些测试环境,即使没有在用它们,也一直在耗费成本?那些用来运行管道代码的服务器,没有在用时有没有把它们停掉?所有这些考量都与云原生开发有关。

基于这样的定义,可以说云原生应用程序就是函数即服务(Function as a Service,FaaS),或者说“Serverless”。如果你正在启动一个新项目,或者在已有的架构中加入额外的功能,那么 FaaS 有可能是成本最低且交付速度最快的解决方案。你有很多理由不选择 FaaS,其中一个最常见的理由是你不希望自己的业务逻辑只能在某一家云供应商的平台上运行。你可能希望业务逻辑也能在自有数据中心里运行,你可能不想基于某一家供应商的框架或语言重构自己的业务逻辑,你担心被供应商锁定。况且,一个无服务器函数就只是一个函数,它们需要经过编排,输入和输出也需要被管理起来,它们本身并非一个完整的应用程序。

也有一种观点认为,从部署的方式来看,容器也是一种无服务器架构。确实,容器里面有很多服务器特性的东西,但当你把它们部署到云平台上,比如 Google GKE、Azure AKS 或 Amazon EKS,你并不关心它们是如何运行的。那么,该怎么定义云原生呢?

云原生应用程序就是部署到云端,在保留灵活性和可移植性的同时最大化效益的应用程序。

2 凯捷的云原生解决方案

我们部门提供了几种云原生产品。一个是云原生成熟度评估,帮助客户了解他们离最大化云效益还有多远,另一个就是我们的开源云原生开发平台。

云原生成熟度评估

当人们在考虑将应用程序迁移到云端时,容易忽略掉一些东西。以下十个步骤帮你检查在向云端迁移的过程中你的业务利益是否得到最大化。

1、构建服务器

首先,你该怎么把应用程序移动到云端?在向云端迁移之前,你需要回到最基本的东西,看一看你的交付管道。在失去了对部署环境的控制权之后,你要确保每一个步骤都是可自动重现的。构建服务器是自动化部署流程的开始。你要能够重复创建和测试被部署到云端的工件。但话说回来,构建服务器本身应该部署在哪里?也把它放在云端吗?

2、可访问的工件仓库

构建服务器构建了很多 Docker 镜像,然后呢?怎么把它们传到云端?很多公司启用了复杂的防火墙来阻止这种访问通道,所以,你需要思考一下如何管控好这个过程。可以先从最小化访问权限开始,比如,部署管道只需要仓库的读取权限。确保每一个访问都有经过审计。如果你的工件仓库位于云端,那么你需要一系列单独的密钥,让你的构建服务器可以读取和写入。你要考虑是否需要启用密钥管理器来保管这些密钥,并告知如何传输这些密钥。

3、补丁流程

在将应用程序迁移到云端之前,想一下该如何打补丁。你不能再像以前那样,直接登录到某一台机器,然后换掉一个 JAR 包。你也不希望因为一个针对某个 Docker 镜像的紧急更新拖垮了整个云环境。现在,想一想你的补丁流程应该是怎样的,这样可以为将来省下很多麻烦。从好的方面来看,现在并行运行多个环境,并在它们之间来回切换要容易得多,所以,这或许是最好的方法之一。

4、微服务架构

我们不妨想一下,微服务真的是云原生的一个必要前提吗?我认为是的。当然,如果你的架构是一个“大泥球”,你可以直接租一个足够强大的云端服务器,然后把所有东西都丢上去,但这样无法获得弹性方面的成本效益。如果你的架构是分模块部署的,并且可以根据需要进行水平伸缩,那就可以获得较好的成本效益。

5、 谨慎选择抽象级别

将应用程序迁移到云端,涉及好几个抽象层。我们已经提到过最简单的基础设施即服务(Infrastructure-as-a-Service),以及最终的服务器架构,但如何在这两者之间划一个清晰的界限呢?我们选择 Kubernetes 即服务(Kubernetes-as-a-Service)作为我们的抽象层。我们构建并测试 Docker 容器,并把它们部署到云端的 Kubernetes 服务。为什么要这样?我也问了我们团队这个问题,得到了以下这些回答。

  • 容器编排。我们需要容器编排工具。微服务的一个优势是它们可以单独部署,而这种模块化代码并非新鲜事物,在面向对象编程范式之前,我们的函数已经是“只做一件事情,并做到最好”了。单独部署意味着可以水平伸缩,可以重启失败的实例,可以杀掉长时间运行的实例,或者管理 IP 地址。我们获得了可靠性和效率,但我们需要把这个过程自动化。这方面的工具并不多,Kubernetes 显然是我们的一个绝佳选择。
  • 快速上线。人们知道如何在本地搭建 Docker 环境并运行容器,可以很快地迁移到云端的 Kubernetes 环境。Docker 镜像几乎可以用来运行所有东西,不过,如果你要让使用老古董编程语言 COBOL 开发的东西变成无服务器的,需要先用其他语言重写。
  • 助力开发人员。让开发人员管理 Docker 容器并不是件坏事。我们已经有定义容器的语言,都是与操作系统相关的概念,而且有很多模板可以用。但 Kubernetes 是另一码事,配置一个 Kubernetes 集群需要很多网络方面的知识,而这些可能是开发人员所不具备的。这很好地满足了开发人员对于自我效率的愿望:构建应用程序,而不是平台。
  • 节约成本。Kubernetes 有一个好处,就是你不需要运行自己的主节点,因为服务已经包含了,所以你只需要支付工作节点的费用。

Kubernetes 即服务有一个小小的不足,就是你可能会觉得被某个特定的 Kubernetes 供应商锁定。你可以降低这种锁定程度,就是选择一个核心的 Kubernetes,这样迁移就不会太困难。或者,借助来自另一个团队的名言:“避免锁定本身就是反效率的。你只从少量服务中选择,但错失了一些非常有用的新产品所提供的好处。从一个供应商迁移到另一个供应商,这种事情很少会发生,但希望你们可以用一些好的服务提供商,让它们来完成迁移工作。我们团队使用的是谷歌的开源工具 KNative。KNative 运行在 Kubernetes 上,我们可以用它无缝构建 Docker,并部署到 Kubernetes 上,不需要知道底层的 Kubernetes Pod 在哪里。不管是在云平台 A 还是云平台 B 上,又或者是在自有数据中心或本地开发机上,都没有关系。

6、日志聚合

为云端的应用程序提供支持服务与其他有很大不同。你不能只像往常一样,登录服务器,获取某个进程的输出,然后看看是什么东西挂起了。相反,你需要事先想好所有可能出错的情况,并做好计划。所幸的是,云供应商在这方面帮了大忙,他们提供了一些非常好的日志 API,但你要确保自己通过正确的方式使用它们。首先,你要选择一个可通过网络访问的日志仓库,提供安全的读写方式,然后把所有日志都写到仓库里。你还需要一个健壮的框架,用于创建关联 ID,这样就可以追踪服务之间相关的函数调用。然后,你可以看一下你所选择的云平台提供了哪些云原生产品,看看哪些地方可以节约成本。

7、基础设施即代码

我们不是已经脱离了基础设施了吗?是的,但你仍然需要控制和定义你的环境。这个时候,Terraform 和 Helm 这类工具就派上用场了。你可以定义特定于云供应商的基础设施定义,并在需要的时候停止或启动,包括你的工具平台。

8、漏洞扫描

在这个列表里有一个隐藏项——也就是安全。一旦你离开了局域网,进入互联网,你立马面临被攻击的风险。漏洞扫描和入侵检测软件就变得至关重要,它们应该成为构建管道的一部分。你可以自己安装和运行像 Snyk 这样的软件,可以在本地运行,也可以在云端运行,但为了节约成本,可以考虑使用第三方服务。

9、临时环境

我很喜欢这个东西。它是这样的:你有了基础设施即代码(Infra as Code)之后,在不使用它们时可以随意停止,在需要的时候可以随意启动运行。对于构建管道来说,这是个好东西。因为构建管道里有很多软件,它们需要消耗很大的处理能力,但只是偶尔这样。临时环境对于 UAT、负载测试、集成测试来说都是个好东西。我们超喜欢它!

10、低延迟

现在,我们可以在云端飞翔了,可以真正开始考虑性能问题了。我们要在意微服务之间的 HTTP 开销吗?我们需要 JSON 吗?或许层与层之间可以使用二进制的 API?现在我们已经是云原生了,我们可以开始把精力集中在如何简化我们的架构上。

图片.jpg

  • 我们的云原生成熟度评估雷达。中间表示本地数据中心,我们加入了各种技术和流程,帮你做到效益最大化。

3 为什么不是无服务器

之前我有提到为什么我们的团队没有在我们的默认云原生架构中采用无服务器抽象级别,即使是对于全新的项目也是如此。最主要的原因是我们看的是大局,而一个无服务器函数本身并不是一种架构。首先,考虑到状态问题。无服务器函数是无状态的,为了实现模块化,我们需要多个互相交互的函数,并管理好它们之间的数据。于是,我们就需要某种框架来协调函数调用和参数,需要某种类型的队列或事件流,需要某种复杂的规则来管理每一个函数是基于哪个事件或数据触发的。

你可能需要重度调整你的架构,以便能够使用这些无服务器函数,但你将面临架构失去原本作用的风险。现在有很多用于管理无服务器函数的框架,比如 AWS Step Functions,你也参考一些我们使用的一些无服务器框架,虽然它们是特定于某些供应商的。无服务器函数也有很多特定的约束,比如每次执行 N 秒固定时间、只支持有限的几种编程语言以及非常陡峭的学习曲线。例如,有谁会知道 AWS Lambda Functions 在某些特定的故障条件下会重试 10000 次?Lambda 架构仍然是一项非常前沿的技术,所以这些问题还是会在你最不经意的时候出现,给你带来麻烦。

但有一种担忧是合理的,即业务会被绑定到单一的云供应商。供应商有可能会停止运营,或者大幅改变他们的收费策略。或者反过来,假设我们的应用程序开发流程是基于 AWS Elastic Beanstalk,然后突然发现 Amazon 实际上是我们公司最大的竞争者,那该怎么办?你怎么能确定 Amazon 就不会利用你部署的架构和应用程序来获得一些竞争信息?可以想象,在现代商业环境中,这种情况经常发生!企业希望对自己的应用程序有一定程度的控制和自主权,与某个供应商的关系捆绑得太过紧密会让他们感到不安。尽管如此,无服务器函数仍然可以作为首选,特别是对于那种位于主架构之外的小型任务。最近,DataDog 的一项调查表明,人们正是这么做的。使用无服务器最多的群体正是那些部署容器的公司,所以,如果他们已经有容易,那么无服务器就变成了外围功能,帮助他们管理和监控(还有日志和告警)那些运行在容器中的应用程序。

“冷启动”问题一直被认为是无服务器函数的一个大问题,但我感觉现在应该有办法解决了。这个问题的关键在于,在一个高效的架构中,函数的运行时环境只在需要的时候启动,用完后再销毁。对于像 Java 这样带有 JVM 的编程语言,这个过程就特别慢。常见的解决方案是减小运行函数的最小数量,因为如果一个函数可以处理大部分的请求,那很有可能只有一个函数在运行。或者,你也可以多付点费用,让一个实例运行长一点时间,在其他实例启动过程中先承担初始的负载。选择合适的编程语言也很重要,例如,Node 运行时比 Java 启动更快。这篇文章介绍了我们如何降低 Java 应用程序的资源占用。

原文链接:

https://capgemini.github.io/cloud/cloud-native-steps/