在阿里云上试用 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相关、但不限于实践的分享,敬请期待。

相关文章
相关标签/搜索