在阿里雲上試用 Knative

摘要: 在今年的Google Cloud Next大會上,Google發佈了Knative, 這是由Google、Pivotal、Redhat和IBM等雲廠商共同推出的Serverless開源工具組件,它與Istio,Kubernetes一塊兒,造成了開源Serverless服務的三駕馬車。git

在今年的Google Cloud Next大會上,Google發佈了Knative, 這是由Google、Pivotal、Redhat和IBM等雲廠商共同推出的Serverless開源工具組件,它與Istio,Kubernetes一塊兒,造成了開源Serverless服務的三駕馬車。github

本文來自阿里巴巴中間件事業部美國團隊高級技術專家 Andy在 Knative的實踐,Andy長期關注Service Mesh技術領域,在Cloud Foundry,Kubernetes,Envoy上等有着豐富的實踐和開發經驗。加入Service Mesh開發者羣,微信添加「zjjxg2018」,並備註公司-城市信息。docker

有意思的是:上述幾家公司是相互競爭的,但卻能把各自擅長的技術貢獻給同一個開源項目。另外一個有意思的地方是對Serverless定義的轉變。之前說到Serverless,你們就等同於FaaS,就感受只要把function代碼提交,而後定義event trigger就行了。如今Knative把Serverless這個概念轉變成了免運維:用戶仍是要有server的,只是運維上比管理一個Kubernetes cluster更省心,並且不用的時候並不須要爲server資源支付費用。除此以外,FaaS的應用場景很小,只有很小很快的函數才能比較容易部署。Knative以自助的方式實現部署,應用場景更廣,且通常的應用均可以部署成Serverless。vim

根據Knative提供的文檔介紹,一個完整的Serverless分爲__Build__,__Serve__和__Eventing__三個部分。在本文中,咱們將在阿里雲上按照Knative github的安裝指南,逐步操做,以實現一個Knative應用。api

準備
建立 Kubernetes cluster
在阿里雲上建立一個Kubernetes cluster,用系統默認的設置就行,但要保證你有Admin權限。若是你用已有的 cluster,請確認Kubernetes的版本是1.10以上。服務器

安裝 Knative
這個過程分爲兩步:微信

安裝Istio:
Knative的Istio有一些本身定義的資源,因此不要用Istio網站的缺省安裝。可是Knative現有指南未更新,仍是0.8,有些舊。我所用的是1.0:
curl https://raw.githubusercontent.com/knative/serving/master/third_party/istio-1.0.0/istio.yamlapp

這個安裝須要一點時間,可是是必須的。由於Knative依賴Istio來聯接Serverless,而不是直接經過Kubernetes。等到全部的安裝完成後,咱們要開啓Istio 自動injection:less

kubectl label namespace default istio-injection=enabled
安裝 Knative組件:運維

執行下面的命令:
kubectl apply -f https://github.com/knative/se...
安裝後等待一會並確認:
kubectl get pods -n knative-serving -w
kubectl get pods -n knative-build -w
細心的同窗會發現這裏只安裝了兩部分:Build 和 Serving,那麼Eventing呢?是須要單獨安裝的。

kubectl apply -f https://storage.googleapis.co...
一樣的,運行這個命令來確認:

kubectl get pods -n knative-eventing -w
Build
Build是目前Knative項目中內容最豐富的部分。由於Pivotal拿出了壓箱寶build packs加入Knative。而Google以前多年作app engine,也在這方面累計了不少經驗。

在實現上,Build是一個Kubernetes Custom Resource Definition (CRD)。如同其它的Kubernetes CRD,定義的方式是經過YAML,調用的方式是API。用戶能夠選擇不一樣的build template,好比Google的kaniko,Pivotal的build pack等。在本文中,咱們選擇kaniko build。

先安裝Kaniko Build Template:
kubectl apply -f https://raw.githubusercontent...

Kaniko build template和Docker build template最大的不一樣在於用戶不須要本地安裝Docker engine, Kaniko把代碼搬到雲上生成Image。源代碼能夠在遠程的服務器上,還要指定相應的Dockerfile。

可是,這樣作有個問題:Kaniko怎麼訪問用戶的docker account呢?所以,咱們須要建立一個secret,把用戶的docker username和password存在裏面。而後,還須要一個service account來綁定這個secret。
vim secret.yaml

apiVersion: v1
kind: Secret
metadata:
name: docker-user-pass
annotations:

build.knative.dev/docker-0: https://index.docker.io/v1/

type: kubernetes.io/basic-auth
stringData:
username: <docker username in plain text>
password: <docker password in plain text>
把這裏的username和password換成你本身的賬號信息,而後保存。
kubectl apply -f secret.yaml
vim service-account.yaml

apiVersion: v1
kind: ServiceAccount
metadata:
name: build-bot
secrets:

  • name: docker-user-pass

保存後執行:
kubectl apply -f service-account.yaml

而後咱們建立Kubernetes manifest vim build.yaml:

apiVersion: build.knative.dev/v1alpha1
kind: Build
metadata:
name: docker-build
spec:
serviceAccountName: build-bot #service account created above
source:

git:
  revision: master
  url: "https://github.com/szihai/hello-go.git"

steps:

-
  args:
    - "--dockerfile=/workspace/Dockerfile"
    - "--destination=docker.io/xxx/helloworld-go"
  image: "gcr.io/kaniko-project/executor:v0.1.0"
  name: build-and-push

本文所用的sample app是從Knative repo 上fork的。(例子)

在這裏,咱們指定了template用Kaniko。而後能夠看到咱們引用了前面的ServiceAccount 來訪問secret。用這個以前把裏面的destination換成你本身的docker id,保存後用kubectl apply -f build.yaml 來執行。

那麼,如何知道遠程的Kaniko到底作好了沒有呢?Kubernetes 會爲kind: Build 建立一個job。用kubectl get pods 找到一個 docker-build-xxxx 的pod。而後運行:kubectl -n default logs docker-build-xxxx -c build-step-build-and-push 來觀察build的狀況。

咱們也能夠直接查看Kubetnetes build objects: kubectl describe builds。要找的信息是:

圖片描述

固然,最直接的方法是去本身的Docker hub上找到這個Image。

Serving
這個部分與普通的Kubetnetes服務發佈差異不大。先定義一個服務:vim service.yaml

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"

運行kubectl apply -f service.yaml。須要注意的是這裏咱們用了serving.knative.dev 的API。因此與其它部署有所不一樣:不須要deployment.yaml。這可理解爲deployment被knative給包辦了。若是運行kubectl get deployments,就能夠看到helloworld-go-xxxx-deployment。

下一個問題就是,如何訪問這個服務呢?這時候,Istio就出場了。平時咱們要本身建立Ingress 或LB,如今knative經過 Istio幫咱們作了。首先咱們獲得Ingress Gateway的IP地址:
kubectl get svc knative-ingressgateway -n istio-system

這裏找到EXTERNAL-IP。而後咱們找到Domain name:

kubectl get service.serving.knative.dev helloworld-go -o=custom-columns=NAME:.metadata.name,DOMAIN:.status.domain
接着運行:

curl -H "Host: {DOMAIN}" http://{EXTERNAL-IP}
結果應該是:Hello World: Go Sample v1!
若是有一段時間沒訪問該服務,就會發現運行kubectl get pods 的時候,這幾個helloworld-go pod不見了。那是knative把replica數降爲0。

Eventing
對於FaaS的來講,Eventing就是觸發這個function的機制。上面咱們用curl去訪問服務,實際上是爲了測試而已。在真實的部署過程當中,這個function應該是有事件觸發的。

Eventing是傳統的FaaS的主要功能,也是除源代碼外惟一與開發者真正相關的部分。正由於如此,其它FaaS,如Lambda, Openshift等,均可以經過這一層與Knative接口。

Knative設計的Eventing包括3個主要的概念:

Source: 就是事件發生的起源,能夠理解爲與其它系統的接口,目前支持的包括K8sevents,GitHub和GCP PubSub 。
Buses: 事件傳輸的途徑,目前支持的有Stub,Kafka和GCP PubSub。
Flows: 定義對事件的反應。這能夠是連鎖的反應而不是單一的。
因此,咱們要作的事就是,選一個Source,選一個Bus, 而後定義一個Flow,就能夠啦。
本文中,咱們選用K8events和Stub ClusterBus。先把它們裝上:

kubectl apply -f https://storage.googleapis.co...
kubectl apply -f https://storage.googleapis.co...
在生成flow以前,有一個小問題:K8 event是Kubernetes內部產生的,要接收的話,必需要經過一個Service Account 來受權。這是Kubernetes的要求,不是本文重點,如前面同樣,保存後執行:

apiVersion: v1
kind: ServiceAccount
metadata:
name: feed-sa

namespace: default

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: create-deployment
namespace: default
rules:

  • apiGroups: ["apps"]
    resources: ["deployments"]
    verbs: ["get", "list", "watch", "create", "update", "delete", "patch"]

This enables the feed-sa to deploy the receive adapter.

apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: feed-sa-deploy
namespace: default
subjects:

  • kind: ServiceAccount
    name: feed-sa
    namespace: default

roleRef:
kind: Role
name: create-deployment

apiGroup: rbac.authorization.k8s.io

This enables reading k8s events from all namespaces.

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: feed-admin
subjects:

  • kind: ServiceAccount
    name: feed-sa
    namespace: default

roleRef:
kind: ClusterRole
name: view
apiGroup: rbac.authorization.k8s.io
接下來是主要的一步,建立flow:vim flow.yaml :

apiVersion: flows.knative.dev/v1alpha1
kind: Flow
metadata:
name: k8s-event-flow
namespace: default
spec:
serviceAccountName: feed-sa
trigger:

eventType: dev.knative.k8s.event
resource: k8sevents/dev.knative.k8s.event
service: k8sevents
parameters:
  namespace: default

action:

target:
  kind: Route
  apiVersion: serving.knative.dev/v1alpha1
  name: helloworld-go

接着運行kubectl apply -f flow.yaml就能夠了。

咱們來看一下是否是真的運行了呢?過一下子運行:
kubectl get pods 會看到k8s-event-flow-xxx的job運行完了。而後helloworld-go的pod都啓動了。咱們看一下日誌: kubectl logs helloworld-go-xxxxx user-container,就會看到以下的結果:

Hello world received a request.
Hello world received a request.
Hello world received a request.
Hello world received a request.
...
這說明這條鏈路是起做用的。那麼,這個flow的定義說了什麼呢?首先是用了剛剛定義的service account。而後在trigger中定義什麼樣的event能夠符合條件,這裏咱們說全部在 default namespace 的k8events 都符合。在action中咱們定義有什麼樣的處理方式,本例中就直接調用了helloworld-go service。

結論
Knative是今年最新的雲計算演進方向之一。阿里雲支持Kubernetes,能夠成功運行Knative和Istio等應用,你們也能夠到阿里雲上本身體驗一番!

固然,做爲一個新的備受矚目的項目,Knative也會經歷其成長的煩惱。咱們會持續跟進,並提供和Knative相關、但不限於實踐的分享,敬請期待。

相關文章
相關標籤/搜索