Knative 簡介

本文做者來自螞蟻金服系統部之芥html

什麼是 Knative?

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等)。性能優化



knative 核心概念和原理

爲了實現 serverless 應用的管理,knative 把整個系統分紅了三個部分:bash

  • Build:構建系統,把用戶定義的函數和應用 build 成容器鏡像
  • Serving:服務系統,用來配置應用的路由、升級策略、自動擴縮容等功能
  • Eventing:事件系統,用來自動完成事件的綁定和觸發

Build 構建系統

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:服務系統

serving 的核心功能是讓應用運行起來提供服務。雖然聽起來很簡單,但這裏包括了不少的事情:

  • 自動化啓動和銷燬容器
  • 根據名字生成網絡訪問相關的 service、ingress 等對象
  • 監控應用的請求,並自動擴縮容
  • 支持藍綠髮布、回滾功能,方便應用方法流程

knative serving 功能是基於 kubernetes 和 istio 開發的,它使用 kubernetes 來管理容器(deployment、pod),istio 來管理網絡路由(VirtualService、DestinationRule)。

由於 kubernetes 和 istio 自己的概念很是多,理解和管理起來比較困難,knative 在此之上提供了更高一層的抽象(這些對應是基於 kubernetes 的 CRD 實現的)。這些抽象出來的概念對應的關係以下圖:

  • Configuration:應用的最新配置,也就是應用目前指望的狀態,對應了 kubernetes 的容器管理(deployment)。每次應用升級都會更新 configuration,而 knative 也會保留歷史版本的記錄(圖中的 revision),結合流量管理,knative 可讓多個不一樣的版本共同提供服務,方便藍綠髮布和滾動升級
  • Route:應用的路由規則,也就是進來的流量如何訪問應用,對應了 istio 的流量管理(VirtualService)
  • Service:注意這裏不是 kubernetes 中提供服務發現的那個 service,而是 knative 自定義的 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 各組件之間的關係:




  • 能夠看到,每一個 revision 對應了一組 deployment 管理的 pod
  • pod 會自動彙報 metrics 數據到 autoscaler,autoscaler 會根據請求量和資源使用狀況修改 deployment 的 replicas 數量,從而實現自動擴縮容。serverless 一個重要的特定是它會 scale to 0 的,也就是當應用沒有流量訪問時,它會自動銷燬全部的 pod
  • activator 比較有趣,它是爲了處理 scale to 0 而出現的。當某個 revision 後面的 pod 縮容到 0 時,route 的流量會指向 activator,activator 接收到請求以後會自動拉起 pod,而後把流量轉發過去
  • route 對象對應了 istio 的 DestinationRoute 和 VirtualService,決定了訪問應用的流量如何路由

Eventing:事件系統

serving 系統實現的功能是讓應用/函數可以運行起來,而且自動伸縮,那何時纔會調用應用呢?除了咱們熟悉的正常應用調用以外,serverless 最重要的是基於事件的觸發機制,也就是說當某件事發生時,就觸發某個特定的函數。

事件概念的出現,讓函數和具體的調用方可以解耦。函數部署出來不用關心誰會調用它,而事件源觸發也不用關心誰會處理它。

Note:目前 serverless 的產品和平臺不少,每一個地方支持的事件來源以及對事件的定義都是不一樣的(好比 AWS Lambda 支持不少本身產品的事件源)。Knative 天然也會定義本身的事件類型,除此以外,knative 還聯合 CNCF 在作事件標準化的工做,目前的產出是 CloudEvents 這個項目。

爲了讓整個事件系統更有擴展性和通用性,knative 定義了不少事件相關的概念。咱們先來介紹一下:

  • EventSource:事件源,可以產生事件的外部系統
  • Feed:把某種類型的 EventType 和 EventSource 和對應的 Channel 綁定到一塊兒
  • Channel:對消息實現的一層抽象,後端可使用 kafka、RabbitMQ、Google PubSub 做爲具體的實現。channel name 相似於消息集羣中的 topic,能夠用來解耦事件源和函數。事件發生後 sink 到某個 channel 中,而後 channel 中的數據會被後端的函數消費
  • Subscription:把 channel 和後端的函數綁定的一塊兒,一個 channel 能夠綁定到多個knative service

它們之間的關係流程圖以下:

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 目前的狀態

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 應用場景和思考

knative 基於 kubernetes 和 istio 的 serverless 開源實現,目標是爲了提供更高層次的抽象,讓開發者無需關注基礎設施(虛擬機或者容器,網絡配置,容量規劃),而專一於業務代碼便可。

目前 serverless 以及 knative 的幾個問題:

1. 性能問題

性能問題一直是 serverless 被人詬病的一點,也是目前它不能普遍用於應用服務上的決定性緣由。互聯網的應用大多數有高併發、高性能的要求,serverless 整個網絡鏈路很長,容器啓停須要額外的時間,還沒法知足互聯網應用的要求。

針對這一點,不少 serverless 框架也在不斷地作改進,好比不斷精簡容器的啓動時間、容器啓動以後會作緩存等,好比 nuclio 就宣稱本身的平臺比 AWS Lambda 要快 10 倍以上。

相信隨着 serverless 的不斷演進,性能問題會不斷優化,至於能不能達到互聯網應用的要求,還要時間給咱們答案。

2. 是否須要 istio 這一層?

基於 kubernetes 的 serverless 組件很是多,好比 kubeless。可是基於同時又基於 istio,目前 knative 仍是第一個這麼作的。

有些人的疑問在於,knative 真的有必要基於 istio 來作嗎?對於這個問題,我我的的見解是必要的。

雖然 istio 纔剛剛release 1.0 版本,可是它做爲集羣基礎設施通用網絡層的地位已經開始顯露,相信在將來的發展中接受度會愈來愈大,並逐漸鞏固本身的地位。雖然現階段來講,不少人並不很是熟悉 istio 的狀況,可是從長遠角度來看,這一點將是 knative 的一個優點所在。

另外,基於 istio 構建本身的 serverless 服務,也符合目前軟件行業不要重複造輪子的工做。istio 在集羣的網絡管理方面很是優秀(智能路由、負載均衡、藍綠髮布等),基於 istio 來作可讓 knative 不用重複工做就能直接使用 istio 提供的網絡通用功能。

3. 系統複雜度

這一點和上面相似,knative 下面已經有兩個很是複雜的平臺:kubernetes 和 istio。這兩個平臺的理解、構建、運維自己就很複雜,現在又加上 knative 整個平臺,須要瞭解的概念都要幾十個,更不要提落地過程當中會遇到的各類問題。

對於公有云來講,kubernetes 和 istio 這些底層平臺能夠交給雲供應商來維護(好比 google Function),可是對於內部構建來講,這無疑提升了整個技術門檻,對系統管理人來的要求更高。

如何安裝部署整個集羣?如何對集羣作升級?出現問題怎麼調試和追蹤?怎麼更好地和內部的系統對接?這些系統的最佳實踐是什麼?怎麼作性能優化?全部這些問題都須要集羣管理人員思考並落實。

4. 函數的可運維性?

相對於編寫微服務來講,單個函數的複雜度已經很是低,可是當很是多的函數須要共同工做的時候,如何管理這些函數就成了一個必須解決的問題。

  • 如何快速找到某個函數?
  • 如何知道一個函數的功能是什麼?接受的參數是什麼?
  • 怎麼保證函數的升級不會破壞原有的功能?升級以後如何回滾?怎麼記錄函數的歷史版本一方面追溯?
  • 當有多個函數須要同時工做的時候,怎麼定義它們之間的關係?
  • 函數出現問題的時候如何調試?

對於函數的運維,通常的 serverless 平臺(包括 knative)都提供了 logging、metrics、tracing 三個方面的功能。默認狀況下,knative 使用 EFK(Elasticsearch、Fluent、Kibana)來收集、查找和分析日誌;使用 prometheus + grafana 來收集和索引、展現 metrics 數據;使用 jaeger 來進行調用關係的 tracing。

針對 serverless 衍生出來的運維工具和平臺還不夠多,如何調試線上問題尚未看到很是好的解決方案。

5. knative 成熟度

最後一點是關於 knative 成熟度的,前面已經提到,knative 目前剛出現不久。雖然整個框架和設計都已經搭好了,可是不少實現都比較初級。這裏提幾點來講:

  • 爲了實現 autoscaling,knative 在每一個 pod 中添加一個叫作 queue proxy 的代理,它會自動把請求的 metrics 發送給 autoscaler 組件做爲參考。這樣一來,整個網絡鏈路上又多了一層,對整個性能勢必會有影響,將來的打算是直接使用 envoy sidecar 來替換掉 queue proxy
  • 支持的事件源和消息系統還還優先,外部事件只支持 github、kubernetes 和 Google PubSub。 這個問題能夠慢慢擴展,knative 自己會實現很經常使用的事件類型,自定義的事件源用戶能夠本身實現
  • 目前尚未函數的 pipeline 管理(相似 AWS Lambda Step Functions),多個函數如何協做並無本身處理。雖然沒有在官方文檔中看到這方面的 roadmap,可是之後必定會有這方面的功能(不論是 knative 自己來作,仍是社區做爲工具補充來實現)

這方面的問題都不是大事情,隨着 knative 版本的迭代,在很快的時間都可以解決。

參考資料


歡迎關注【金融級分佈式架構】微信公衆號,瞭解更多

相關文章
相關標籤/搜索