本文發表於一年多前。舊文章可能包含過時內容。請檢查頁面中的資訊自發布以來是否已變得不正確。
Kyma - 輕鬆擴充套件和構建 Kubernetes
根據最近完成的CNCF 調查,雲原生技術在生產環境中的採用率正在迅速增長。Kubernetes 是這場技術革命的核心。自然,雲原生技術的增長也伴隨著其生態系統的增長。當然,雲原生技術的複雜性也隨之增加。只需在谷歌搜尋“Kubernetes is hard”這個短語,你就會得到大量文章來解釋這個複雜性問題。CNCF 社群最棒的一點是,這樣的問題可以透過聰明的開發者構建新工具來賦能 Kubernetes 使用者而得到解決:例如,像 Knative 及其Build 資源擴充套件等專案,旨在降低各種場景的複雜性。儘管增加複雜性似乎是需要解決的最重要問題,但它並不是您在向雲原生過渡時面臨的唯一挑戰。
待解決的問題
選擇正確的技術很困難
現在您已經瞭解了 Kubernetes,您的團隊已經接受了培訓,並且您已經開始在其上構建應用程式,是時候面對新一層的挑戰了。雲原生不僅僅意味著部署一個供開發者在其上構建的平臺。開發者還需要儲存、備份、監控、日誌記錄和服務網格來對傳輸中的資料強制執行策略。這些獨立的系統中的每一個都必須正確配置和部署,並且需要獨立地進行日誌記錄、監控和備份。CNCF 旨在提供幫助。我們提供了所有云原生技術的概覽圖,但列表非常龐大,可能會讓人不知所措。
這就是 Kyma 讓您生活更輕鬆的地方。它的使命宣言是提供一種靈活簡單的方式來擴充套件應用程式。

該專案旨在為您提供構建端到端、生產級雲原生應用程式所需的工具。Kyma 由 SAP 捐贈給開源社群;SAP 在編寫生產級雲原生應用程式方面擁有豐富的經驗。這就是我們如此興奮地宣佈 Kyma 的第一個主要版本,Kyma 1.0 釋出的原因!
決定從單體應用轉向雲原生的路徑很困難
嘗試在谷歌搜尋 `monolith to cloud native` 或 `monolith to microservices`,你會得到大量關於如何應對這一挑戰的演講和論文。將單體應用遷移到雲有許多不同的途徑,我們的經驗告訴我們在這個領域應該相當有主見。首先,讓我們回答為什麼要從單體應用轉向雲原生的問題。推動這一轉變的目標通常是:
- 提高可伸縮性。
- 更快地實現新功能。
- 更靈活的可擴充套件性方法。
您無需重寫您的單體應用程式即可實現這些目標。為什麼要花費所有時間重寫已有的功能呢?只需專注於讓您的單體應用程式支援事件驅動架構。
Kyma 如何解決您的挑戰?
什麼是 Kyma?
Kyma 執行在 Kubernetes 上,由多個不同的元件組成,其中三個是:
- 應用程式聯結器,您可以使用它將任何應用程式與 Kubernetes 叢集連線,並透過 Kubernetes 服務目錄暴露其 API 和事件。
- Serverless 讓您能夠輕鬆為應用程式編寫擴充套件。您的函式程式碼可以由 API 呼叫觸發,也可以由來自外部系統的事件觸發。您還可以從函式中安全地回撥整合系統。
- 服務目錄旨在暴露整合系統。這種整合還使您能夠使用 Azure、AWS 或 Google Cloud 等超大規模雲服務提供商的服務。Kyma 允許輕鬆整合由 Microsoft 和 Google 維護的官方服務代理。
您可以觀看此影片,透過真實的演示場景簡要了解 Kyma 的主要功能。
我們為您選擇了正確的技術
只有在妥善監控和配置的情況下,您才能在 Kyma 這樣的專案中提供可靠的可擴充套件性。我們決定不重複造輪子。CNCF 生態系統中有許多優秀的專案,大部分都有龐大的社群支援。我們決定挑選最好的專案,並將它們整合到 Kyma 中。您可以看到與上方相同的架構圖,但重點是我們將哪些專案組合在一起建立了 Kyma:

- 監控和警報基於 Prometheus 和 Grafana
- 日誌記錄基於 Loki
- 事件處理使用 Knative 和 NATS
- 資產管理使用 Minio 作為儲存
- 服務網格基於 Istio
- 跟蹤使用 Jaeger
- 身份驗證由 dex 提供支援
您無需整合這些工具:我們確保它們能很好地協同工作,並且始終保持最新(Kyma 已經在使用 Istio 1.1)。透過我們定製的安裝程式和Helm圖表,我們實現了 Kyma 的輕鬆安裝和升級到新版本。
不要重寫您的單體應用
重寫既困難又耗資巨大,並且在大多數情況下是沒有必要的。最終,您需要的是能夠更快地編寫新功能並將其投入生產。您可以透過使用應用程式聯結器將您的單體應用連線到 Kyma 來實現這一目標。簡而言之,這個元件確保了:
- 您可以安全地回撥已註冊的單體應用,而無需處理授權問題,因為應用程式聯結器會處理這些問題。
- 從您的單體應用傳送的事件安全地到達 Kyma 事件匯流排。
目前,您的單體應用可以消費三種不同型別的服務:用於同步通訊的 REST(帶有OpenAPI規範)和 OData(帶有實體資料模型規範),以及用於非同步通訊的基於AsyncAPI規範的事件目錄。您的事件隨後使用帶有Knative eventing的NATS Streaming通道在內部交付。
一旦您的單體服務連線成功,您就可以透過前面提到的服務目錄整合,在選定的名稱空間中配置這些服務。作為開發者,您可以訪問目錄,檢視所有可消費的服務列表。這包括來自您的單體應用程式的服務,以及透過已註冊的服務代理(如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儀表盤,透過Prometheus和Istio檢視我的Lambda指標。

這種方法在新增新功能時為您提供了很大的靈活性。它還讓您有時間重新思考重寫舊功能的必要性。
貢獻和提供反饋
Kyma 是一個開源專案,我們非常樂意幫助它成長。它的發展離不開您的幫助。閱讀本文後,您已經知道我們不想重複造輪子。我們在工作模式中堅持這一原則,這使社群貢獻者能夠參與進來。我們在特殊興趣小組中工作,並有公開錄製的會議,您可以隨時加入,因此我們的設定類似於您從 Kubernetes 本身瞭解到的那種。歡迎透過Twitter或Slack與我們分享您的反饋。