本文发表已超过一年。较旧的文章可能包含过时内容。请确认页面中的信息自发布以来没有发生错误。

Kyma - 轻松扩展和构建 Kubernetes

根据最近完成的CNCF 调查,云原生技术在生产环境中的采用率正在迅速增长。Kubernetes 是这场技术革命的核心。自然而然,云原生技术的增长伴随着其生态系统的壮大。当然,云原生技术的复杂性也增加了。只需在 Google 搜索“Kubernetes is hard”(Kubernetes 很难),你会找到大量解释这个复杂性问题的文章。CNCF 社区最好的地方在于,像这样的问题可以通过聪明的人构建新工具来赋能 Kubernetes 用户来解决:例如,像 Knative 及其构建资源 (Build resource) 扩展这样的项目,旨在减少各种场景下的复杂性。尽管增加的复杂性可能看起来是最重要的问题需要解决,但这并不是你向云原生转型时面临的唯一挑战。

需要解决的问题

选择合适的技术很难

既然你已经了解 Kubernetes,你的团队也接受了培训,并且你已经开始在其上构建应用,现在是时候面对新一层的挑战了。云原生不仅仅意味着为开发者部署一个可供构建的平台。开发者还需要存储、备份、监控、日志记录和服务网格来强制执行数据传输策略。这些独立的系统中的每一个都必须正确配置和部署,并且需要有自己的日志记录、监控和备份。CNCF 在这里提供帮助。我们提供了所有云原生技术的全景图 (landscape) 概览,但列表巨大,可能让人不知所措。

这就是Kyma 将让你的生活更轻松的地方。它的使命宣言是提供一种灵活简便的方式来扩展应用。

Kyma in center

该项目旨在为你提供构建端到端、生产级云原生应用所需的工具。Kyma 由在编写生产级云原生应用方面拥有丰富经验的公司 SAP 捐赠给开源社区。这就是为什么我们如此兴奋地宣布 Kyma 1.0 的第一个主要版本!

决定从单体走向云原生的路径很难

试试在 Google 上搜索 monolith to cloud nativemonolith to microservices,你会得到大量讨论这个挑战的演讲和论文列表。将单体迁移到云端有许多不同的路径,我们的经验告诉我们在这一领域形成了相当明确的观点。首先,让我们回答一下为什么你想要从单体迁移到云原生的问题。推动这一迁移的目标通常是

  • 提高可伸缩性。
  • 更快地实现新功能。
  • 更灵活的可扩展方法。

你不必重写你的单体应用就能实现这些目标。为什么要花所有时间重写你已有的功能呢?只需专注于让你的单体应用支持事件驱动架构

Kyma 如何解决你的挑战?

什么是 Kyma?

Kyma 运行在 Kubernetes 上,由多个不同的组件组成,其中三个是

  • 应用连接器 (Application connector),你可以使用它将任何应用连接到 Kubernetes 集群,并通过 Kubernetes Service Catalog 暴露其 API 和事件。
  • 无服务器 (Serverless),它使你能够轻松地为你的应用编写扩展。你的函数代码可以通过 API 调用触发,也可以通过来自外部系统的事件触发。你还可以从函数中安全地回调集成系统。
  • 服务目录 (Service Catalog) 在此暴露集成系统。这种集成还使你能够使用来自 Azure、AWS 或 Google Cloud 等超大规模云服务商的服务。Kyma 支持轻松集成由 Microsoft 和 Google 维护的官方服务代理 (service brokers)。

core components

你可以观看此视频,通过一个真实的演示场景,简要了解 Kyma 的关键特性。

我们为你选择了合适的技术

只有经过适当监控和配置,才能在像 Kyma 这样的项目中提供可靠的可扩展性。我们决定不再重复造轮子。CNCF 生态系统中有很多优秀的项目,大多数都拥有庞大的社区支持。我们决定挑选其中最好的,并将它们全部整合到 Kyma 中。你可以看到与上面相同的架构图,但重点突出了我们整合起来创建 Kyma 的项目:

Kyma architecture

你无需自己集成这些工具:我们确保它们能很好地协同工作,并且始终保持最新(Kyma 已经在使用 Istio 1.1)。借助我们定制的安装程序 (Installer)Helm charts,我们实现了 Kyma 的轻松安装和轻松升级到新版本。

不要重写你的单体应用

重写很困难,耗资巨大,并且在大多数情况下并非必需。说到底,你需要的是能够更快地编写新功能并将其投入生产。你可以通过使用应用连接器 (Application Connector) 将单体应用连接到 Kyma 来实现。简而言之,这个组件确保了

  • 你可以安全地回调已注册的单体应用,无需处理授权问题,因为应用连接器会处理这一切。
  • 从你的单体应用发送的事件会安全地到达 Kyma 事件总线 (Event Bus)。

目前,你的单体应用可以消费三种不同类型的服务:用于同步通信的 REST(带有 OpenAPI 规范)和 OData(带有 Entity Data Model 规范),以及用于异步通信,你可以注册一个基于 AsyncAPI 规范的事件目录。你的事件随后会通过 NATS Streaming 通道并使用 Knative eventing 在内部传递。

一旦你的单体应用服务连接成功,你可以通过前面提到的服务目录 (Service Catalog) 集成,在选定的 Namespaces 中供应这些服务。作为开发者,你可以访问目录并查看所有可供你消费的服务列表。这包括来自你的单体应用的服务,以及通过已注册的服务代理,如 Azure 的 OSBA,获得的来自其他第三方提供商的服务。这是一个包含了你需要的一切的单一位置。如果你想启动一个新应用,你所需的一切在 Kyma 中都已准备就绪。

最后是一些代码

看看我为了将单体应用与 Azure 服务集成而不得不编写的一些代码。我想要了解客户在产品评论区分享的情感。对于每一个包含评论的事件,我希望使用机器学习调用一个情感分析服务,如果评论是负面的,我想将其存储到数据库中供日后查看。这是通过我们的无服务器 (Serverless) 组件创建的函数的代码。请注意我的代码注释。

你可以观看此短视频,观看情感分析函数的完整演示。

/* It is a function powered by NodeJS runtime so I have to import some necessary dependencies. I choosed Azure's CosmoDB that is a Mongo-like database, so I could use a MongoClient */
const axios = require("axios");
const MongoClient = require('mongodb').MongoClient;

module.exports = { main: async function (event, context) {
    /* My function was triggered because it was subscribed to customer review event. I have access to the payload of the event. */
    let negative = await isNegative(event.data.comment)
    
    if (negative) {
      console.log("Customer sentiment is negative:", event.data)
      await mongoInsert(event.data)
    } else {
      console.log("This positive comment was not saved:", event.data) 
    }
}}

/* Like in case of isNegative function, I focus of usage of the MongoClient API. The necessary information about the database location and an authorization needed to call it is injected into my function and I just need to pick a proper environment variable. */
async function mongoInsert(data) {

    try {
          client = await MongoClient.connect(process.env.connectionString, { useNewUrlParser: true });
          db = client.db('mycommerce');
          const collection = db.collection('comments');
          return await collection.insertOne(data);
    } finally {
      client.close();
    }
}
/* This function calls Azure's Text Analytics service to get information about the sentiment. Notice process.env.textAnalyticsEndpoint and process.env.textAnalyticsKey part. When I wrote this function I didn't have to go to Azure's console to get these details. I had these variables automatically injected into my function thanks to our integration with Service Catalog and our Service Binding Usage controller that pairs the binding with a function. */
async function isNegative(comment) {
    let response = await axios.post(`${process.env.textAnalyticsEndpoint}/sentiment`,
      { documents: [{ id: '1', text: comment }] }, {headers:{ 'Ocp-Apim-Subscription-Key': process.env.textAnalyticsKey }})
    return response.data.documents[0].score < 0.5
}

感谢 Kyma,我无需担心围绕我的函数的基础设施。正如我所提到的,我所需的所有工具都在 Kyma 中,并且它们是集成的。我可以通过 Loki 快速获取日志,并且我可以快速访问预配置的 Grafana 面板,查看通过 PrometheusIstio 提供的 Lambda 指标。

Grafana with preconfigured lambda dashboard

这种方法为你添加新功能提供了极大的灵活性。它也为你提供了时间来重新思考是否需要重写旧功能。

贡献和提供反馈

Kyma 是一个开源项目,我们非常希望它能壮大。这需要你的帮助。阅读完这篇文章后,你已经知道我们不想重复造轮子。我们在工作模式中也坚持这一方法,这使得社区贡献者能够参与其中。我们以特别兴趣小组 (Special Interest Groups) 的形式工作,并有公开录制的会议,你可以随时加入,因此我们的设置与你熟悉的 Kubernetes 本身类似。也请随时通过 TwitterSlack 与我们分享你的反馈。