本文做者來自螞蟻金服系統部之芥html
knative 是谷歌開源的 serverless 架構方案,旨在提供一套簡單易用的 serverless 方案,把 serverless 標準化。目前參與的公司主要是 Google、Pivotal、IBM、Red Hat,2018年7月24日纔剛剛對外發布,當前還處於快速發展的階段。git
這是 Google Cloud Platform 宣佈 knative 時給出的介紹:github
Developed in close partnership with Pivotal, IBM, Red Hat, and SAP, Knative pushes Kubernetes-based computing forward by providing the building blocks you need to build and deploy modern, container-based serverless applications.
能夠看出,knative 是爲了解決容器爲核心的 serverless 應用的構建、部署和運行的問題。docker
serverless 的概念已經出現蠻久了,爲了理解 serverless 能夠從應用開發者的角度來看,使用 serverless 框架以後,應用開發者的整個操做流程就變成了:ubuntu
~ # 編寫 code 和 configuration 文件
~ # faascli build
~ # faascli deploy
~ # curl http://myapp.com/hello
hello, world from Awesome FaaS App!複製代碼
能夠看到用戶只須要編寫代碼(或者函數),以及配置文件(如何 build、運行以及訪問等聲明式信息),而後運行 build 和 deploy 就能把應用自動部署到集羣(能夠是公有云,也能夠是私有的集羣)。後端
其餘事情都是 serverless 平臺(好比這裏的 knative)自動處理的,這些事情包括:api
和標準化的 FaaS 不一樣,knative 指望可以運行全部的 workload : traditional application、function、container。緩存
knative 是創建在 kubernetes 和 istio 平臺之上的,使用 kubernetes 提供的容器管理能力(deployment、replicaset、和 pods等),以及 istio 提供的網絡管理功能(ingress、LB、dynamic route等)。性能優化
爲了實現 serverless 應用的管理,knative 把整個系統分紅了三個部分:bash
build 的功能是把用戶的代碼自動化構建成容器鏡像,初次聽起來很奇怪,有了 docker 以後有一個 Dockerfile 不就能構建容器了嗎?爲何還須要一個新的 Build 系統?
Knative 的特別之處在於兩點:一是它的構建完成是在 kubernetes 中進行的,和整個 kubernetes 生態結合更緊密;另外,它旨在提供一個通用的標準化的構建組件,能夠做爲其餘更大系統中的一部分。
正如官方文檔中的說的那樣,更可能是爲了定義標準化、可移植、可重用、性能高效的構建方法:
The goal of a Knative build is to provide a standard, portable, reusable, and performance optimized method for defining and running on-cluster container image builds.
Knative 提供了 Build
CRD 對象,讓用戶能夠經過 yaml 文件定義構建過程。一個典型的 Build
配置文件以下:
apiVersion: build.knative.dev/v1alpha1
kind: Build
metadata:
name: example-build
spec:
serviceAccountName: build-auth-example
source:
git:
url: https://github.com/example/build-example.git
revision: master
steps:
- name: ubuntu-example
image: ubuntu
args: ["ubuntu-build-example", "SECRETS-example.md"]
steps:
- image: gcr.io/example-builders/build-example
args: ['echo', 'hello-example', 'build']
複製代碼
其中,serviceAccountName
是構建過程當中須要用到的密碼和認證信息(好比鏈接到 git repo 的 SSH keys、push 鏡像到 registry 的用戶名和密碼等);source
是代碼信息,好比這裏的 git 地址和分支;steps
是真正運行過程當中的各個步驟,這個示例中的步驟只是做爲 demo,真正的構建過程通常是 pull 代碼、 build 鏡像和 push鏡像到 registry 等邏輯。
由於大部分的構建過程都是一致的,所以 knative 還提供了 Build template
的概念,Build template 封裝了預先定義好的構建過程(就是封裝了上面的 steps
過程),並提供了很是簡單的配置參數來使用。
使用 build template 構建容器鏡像就更簡單了,只須要提供代碼的地址和鏡像名字便可,好比下面是使用 Google kaniko 模板構建 github 源碼的 yaml 文件(須要在代碼根目錄存在 Dockerfile 文件):
apiVersion: build.knative.dev/v1alpha1
kind: Build
metadata:
name: kaniko-build
spec:
serviceAccountName: build-bot
source:
git:
url: https://github.com/my-user/my-repo
revision: master
template:
name: kaniko
arguments:
- name: IMAGE
value: us.gcr.io/my-project/my-app複製代碼
serving 的核心功能是讓應用運行起來提供服務。雖然聽起來很簡單,但這裏包括了不少的事情:
knative serving 功能是基於 kubernetes 和 istio 開發的,它使用 kubernetes 來管理容器(deployment、pod),istio 來管理網絡路由(VirtualService、DestinationRule)。
由於 kubernetes 和 istio 自己的概念很是多,理解和管理起來比較困難,knative 在此之上提供了更高一層的抽象(這些對應是基於 kubernetes 的 CRD 實現的)。這些抽象出來的概念對應的關係以下圖:
services.serving.knative.dev
。單獨控制 route 和 configuration 就能實現 serving 的全部功能,但knative 更推薦使用 Service 來管理,由於它會自動幫你管理 route 和 configuration一個 hello world 的 serving 配置以下所示:
apiVersion: serving.knative.dev/v1alpha1
kind: Service
metadata:
name: helloworld-go
namespace: default
spec:
runLatest:
configuration:
revisionTemplate:
spec:
container:
image: docker.io/{username}/helloworld-go
env:
- name: TARGET
value: "Go Sample v1"
複製代碼
看起來和 kubernetes 的 pod 定義很是相似,可是它會幫你管理 deployment、ingress、service discovery、auto scaling……從這個角度來看,能夠認爲 knative 提供了更高的抽象,自動幫你封裝掉了 kubernetes 和 istio 的實現細節。
下面這張圖介紹了 knative serving 各組件之間的關係:
serving 系統實現的功能是讓應用/函數可以運行起來,而且自動伸縮,那何時纔會調用應用呢?除了咱們熟悉的正常應用調用以外,serverless 最重要的是基於事件的觸發機制,也就是說當某件事發生時,就觸發某個特定的函數。
事件概念的出現,讓函數和具體的調用方可以解耦。函數部署出來不用關心誰會調用它,而事件源觸發也不用關心誰會處理它。
Note:目前 serverless 的產品和平臺不少,每一個地方支持的事件來源以及對事件的定義都是不一樣的(好比 AWS Lambda 支持不少本身產品的事件源)。Knative 天然也會定義本身的事件類型,除此以外,knative 還聯合 CNCF 在作事件標準化的工做,目前的產出是 CloudEvents 這個項目。
爲了讓整個事件系統更有擴展性和通用性,knative 定義了不少事件相關的概念。咱們先來介紹一下:
它們之間的關係流程圖以下:
Bus 是 knative 內部的事件存儲層,用戶能夠選擇本身感興趣的實現,目前支持的方式有:Stub(在內存中實現的簡單消息系統)、Kafka、Google PubSub。若是想要事件可以正常運行,必須在 knative 集羣中安裝其中一個 bus 實現方式。
有了 bus 以後,咱們就能夠監聽外部的事件了。目前支持的事件源有三個:github(好比 merge 事件,push 事件等),kubernetes(events),Google PubSub(消息系統),後面還會不斷接入更多的事件源。
若是要想監聽對應的事件源,須要在 knative 中部署一個 source adaptor 的 pod,它負責從外部的系統中讀取事件。
讀取後的事件,會根據用戶配置的 Feed 對象(裏面包括了事件源和 channel 的對應關係),找到對應的 channel,而後把消息發送到這個 channel 中(channel 的消息最終是存儲在後端的 bus 系統裏的)。
而後,knative 會根據 subscription 的配置,不斷從 channel 中讀取事件,而後把事件做爲參數調用對應的函數,從而完成了整個事件的流程。
knative 是 2018 年 7月纔剛剛對外開放,雖然內部已經開發一段時間,可是目前還處於很是早前的階段(從支持的事件源和 bus就能看出來)。目前代碼還不穩定,不少實現都是 hard-coded。
knative 也是脫產於 google 和 CNCF,所以整個社區運行方式和目標與以前的 kubernetes 以及 istio 很是類似。社區根據組件分紅多個 Working Group,每一個 Group 獨立負責本身的功能,全部的開源活動(文檔、視頻、代碼)都是開放的。另外,CloudEvents 做爲 knative 依賴的標準,目標也是成爲 CRI、CNI、CSI 這種相似的標準。
knative 社區目前很是活躍,已 github.com/knative/serving
項目爲例,一個月已經有 600+ star,目前有 60+ contributor,900+ commits,並且入門的文檔和教程都已經很是全面。
knative 基於 kubernetes 和 istio 的 serverless 開源實現,目標是爲了提供更高層次的抽象,讓開發者無需關注基礎設施(虛擬機或者容器,網絡配置,容量規劃),而專一於業務代碼便可。
目前 serverless 以及 knative 的幾個問題:
性能問題一直是 serverless 被人詬病的一點,也是目前它不能普遍用於應用服務上的決定性緣由。互聯網的應用大多數有高併發、高性能的要求,serverless 整個網絡鏈路很長,容器啓停須要額外的時間,還沒法知足互聯網應用的要求。
針對這一點,不少 serverless 框架也在不斷地作改進,好比不斷精簡容器的啓動時間、容器啓動以後會作緩存等,好比 nuclio 就宣稱本身的平臺比 AWS Lambda 要快 10 倍以上。
相信隨着 serverless 的不斷演進,性能問題會不斷優化,至於能不能達到互聯網應用的要求,還要時間給咱們答案。
基於 kubernetes 的 serverless 組件很是多,好比 kubeless。可是基於同時又基於 istio,目前 knative 仍是第一個這麼作的。
有些人的疑問在於,knative 真的有必要基於 istio 來作嗎?對於這個問題,我我的的見解是必要的。
雖然 istio 纔剛剛release 1.0 版本,可是它做爲集羣基礎設施通用網絡層的地位已經開始顯露,相信在將來的發展中接受度會愈來愈大,並逐漸鞏固本身的地位。雖然現階段來講,不少人並不很是熟悉 istio 的狀況,可是從長遠角度來看,這一點將是 knative 的一個優點所在。
另外,基於 istio 構建本身的 serverless 服務,也符合目前軟件行業不要重複造輪子的工做。istio 在集羣的網絡管理方面很是優秀(智能路由、負載均衡、藍綠髮布等),基於 istio 來作可讓 knative 不用重複工做就能直接使用 istio 提供的網絡通用功能。
這一點和上面相似,knative 下面已經有兩個很是複雜的平臺:kubernetes 和 istio。這兩個平臺的理解、構建、運維自己就很複雜,現在又加上 knative 整個平臺,須要瞭解的概念都要幾十個,更不要提落地過程當中會遇到的各類問題。
對於公有云來講,kubernetes 和 istio 這些底層平臺能夠交給雲供應商來維護(好比 google Function),可是對於內部構建來講,這無疑提升了整個技術門檻,對系統管理人來的要求更高。
如何安裝部署整個集羣?如何對集羣作升級?出現問題怎麼調試和追蹤?怎麼更好地和內部的系統對接?這些系統的最佳實踐是什麼?怎麼作性能優化?全部這些問題都須要集羣管理人員思考並落實。
相對於編寫微服務來講,單個函數的複雜度已經很是低,可是當很是多的函數須要共同工做的時候,如何管理這些函數就成了一個必須解決的問題。
對於函數的運維,通常的 serverless 平臺(包括 knative)都提供了 logging、metrics、tracing 三個方面的功能。默認狀況下,knative 使用 EFK(Elasticsearch、Fluent、Kibana)來收集、查找和分析日誌;使用 prometheus + grafana 來收集和索引、展現 metrics 數據;使用 jaeger 來進行調用關係的 tracing。
針對 serverless 衍生出來的運維工具和平臺還不夠多,如何調試線上問題尚未看到很是好的解決方案。
最後一點是關於 knative 成熟度的,前面已經提到,knative 目前剛出現不久。雖然整個框架和設計都已經搭好了,可是不少實現都比較初級。這裏提幾點來講:
這方面的問題都不是大事情,隨着 knative 版本的迭代,在很快的時間都可以解決。
歡迎關注【金融級分佈式架構】微信公衆號,瞭解更多