摘要:在今年的GoogleCloudNext大会上,Google发布了Knative,它是由Google、Pivo??tal、Redhat、IBM等云厂商联合推出的Serverless开源工具组件。它与Istio兼容,与Kubernetes一起构成了开源Serverless服务的三驾马车。在今年的GoogleCloudNext大会上,Google发布了Knative,它是Google、Pivo??tal、Redhat、IBM等云厂商联合推出的serverless开源工具组件。它与Istio和Kubernetes一起构成了开源无服务器服务承载的三大驱动力。本文来自阿里巴巴中间件事业部美国团队资深技术专家Andy在Knative的实践。Andy长期关注ServiceMesh技术领域,在CloudFoundry、Kubernetes、Envoy等方面有丰富的实践和开发经验。加入ServiceMesh开发者群,微信添加“zjjxg2018”,备注公司-城市信息。有意思的是,上述几家公司相互竞争,却可以将各自的技术贡献给同一个开源项目。另一个有趣的地方是Serverless定义的转变。之前说到Serverless,大家就相当于FaaS,感觉只需要提交功能代??码,定义事件触发器即可。现在Knative已经将Serverless的概念转变为免费运维:用户还是需要一台服务器,但是运维比管理一个Kubernetes集群更省心,不需要在不用的时候为服务器资源付费。另外,FaaS的应用场景非常小,只有小而快的功能才比较容易部署。Knative以自助的方式实现部署,应用场景更广,一般应用可以部署为Serverless。根据Knative提供的文档,一个完整的Serverless分为三个部分:__Build__、__Serve__和__Eventing__。在本文中,我们将按照阿里云上Knativegithub的安装指南一步步实现一个Knative应用。准备创建Kubernetes集群在阿里云上创建一个Kubernetes集群,使用系统默认设置,但请确保您具有Admin权限。如果您使用现有集群,请确保Kubernetes版本在1.10以上。安装Knative的过程分为两步:安装Istio:Knative的Istio有自己定义的一些资源,所以不要使用Istio官网上的默认安装。不过Knative现有的guide并没有更新,还是0.8,有点老了。我使用的是1.0:curlhttps://raw.githubusercontent.com/knative/serving/master/third_party/istio-1.0.0/istio.yaml这个安装需要一点时间,但这是必要的。因为Knative依赖Istio连接Serverless,而不是直接通过Kubernetes。全部安装完成后,我们需要开启Istio自动注入:kubectllabelnamespacedefaultistio-injection=enabled安装Knative组件:执行如下命令:kubectlapply-fhttps://github.com/knative/se...安装完成后稍等片刻,确认:kubectlgetpods-nknative-serving-wkubectlgetpods-nknative-build-w细心的同学会发现这里只安装了两个部分:Build和Serving,那么Eventing呢?它需要单独安装。kubectlapply-fhttps://storage.googleapis.co...同样,运行这个命令来确认:kubectlgetpods-nknative-eventing-wBuildBuild目前是Knative项目中信息量最大的部分。因为Pivotal拿出压箱宝buildpacks加入Knative。而谷歌在appengine上已经深耕多年,在这方面积累了很多经验。在实现上,Build是一个Kubernetes自定义资源定义(CRD)。和其他KubernetesCRD一样,定义方式是通过YAML,调用方式是API。用户可以选择不同的构建模板,比如Google的kaniko,Pivotal的buildpack等,本文我们选择kaniko构建。首先安装KanikoBuildTemplate:kubectlapply-fhttps://raw.githubusercontent...Kaniko构建模板和Docker构建模板最大的区别在于用户不需要在本地安装Docker引擎,而Kaniko将代码移动到云端以生成图像。源代码可以在远程服务器上,也必须指定相应的Dockerfile。但是,这样做有一个问题:Kaniko是如何访问用户的docker账号的?因此,我们需要创建一个secret,将用户的docker用户名和密码存储在其中。然后,需要一个服务帐户来绑定这个秘密。vimsecret.yamlapiVersion:v1kind:Secretmetadata:名称:docker-user-pass注释:build.knative.dev/docker-0:https://index.docker.io/v1/type:kubernetes.io/basic-authstringData:username:password:将这里的用户名和密码替换成你自己的账号信息,并保存。kubectlapply-fsecret.yamlvimservice-account.yamlapiVersion:v1kind:ServiceAccountmetadata:name:build-botsecrets:name:docker-user-pass保存后执行:kubectlapply-fservice-account.yaml然后我们创建Kubernetesmanifestvimbuild.yaml:apiVersion:build.knative.dev/v1alpha1kind:Buildmetadata:name:docker-buildspec:serviceAccountName:build-bot#serviceaccount上面创建的source:git:revision:masterurl:"https://github.com/szihai/hello-go.git"steps:-args:-"--dockerfile=/workspace/Dockerfile"-"--destination=docker.io/xxx/helloworld-go"图片:"gcr.io/kaniko-project/executor:v0.1.0"name:build-and-push本文中使用的示例应用程序派生自Knative存储库。(示例)这里,我们指定使用Kaniko的模板。然后可以看到我们引用了之前的ServiceAccount来访问secret。在使用这个之前,将里面的destination替换成自己的dockerid,保存后使用kubectlapply-fbuild.yaml执行。那么,您如何知道远程Kaniko是否准备就绪?Kubernetes将为kind创建一个作业:Build。使用kubectlgetpods查找docker-build-xxxxpod。然后运行:kubectl-ndefaultlogsdocker-build-xxxx-cbuild-step-build-and-push观察构建情况。我们也可以直接查看Kubetnetes构建对象:kubectldescribebuilds。你要找的资料是:当然,最直接的方法是在你自己的Dockerhub上找这个Image。Serving部分与正常的Kubetnetes服务发布没有太大区别。首先定义一个服务:vimservice.yamlapiVersion:serving.knative.dev/v1alpha1kind:Servicemetadata:name:helloworld-gonamespace:defaultspec:runLatest:configuration:revisionTemplate:spec:container:image:docker.io/{username}/helloworld-goenv:-name:TARGETvalue:"GoSamplev1"运行kubectlapply-fservice.yaml。需要注意的是,这里我们使用了serving.knative.dev的API。所以它不同于其他部署:不需要deployment.yaml。这可以理解为由knative安排部署。如果你运行kubectlgetdeployments,你可以看到helloworld-go-xxxx-deployment。下一个问题是,如何访问这个服务?这时候,Istio就派上用场了。通常我们必须自己创建Ingress或者LB,现在knative通过Istio为我们做了。首先我们获取IngressGateway的IP地址:kubectlgetsvcknative-ingressgateway-nistio-systemfindEXTERNAL-IPhere。然后我们找到域名:kubectlgetservice.serving.knative.devhelloworld-go-o=custom-columns=NAME:.metadata.name,DOMAIN:.status.domain然后运行:curl-H"Host:{DOMAIN}"http://{EXTERNAL-IP}结果应该是:HelloWorld:GoSamplev1!如果你有一段时间没有访问该服务,当你运行kubectlgetpods时,你会发现这些helloworld-gopod不见了。也就是knative将replica数减少到0。Eventing对于FaaS来说,Eve??nting就是触发这个功能的机制。上面我们使用curl访问服务,其实只是为了测试。在实际部署过程中,该功能应该由事件触发。Eventing是传统FaaS的主要功能,也是除了源码之外唯一真正与开发者相关的部分。正因为如此,其他的FaaS,比如Lambda、Openshift等,都可以通过这一层与Knative对接。Knative设计的Eventing包括3个主要概念:Source:是事件的起源,可以理解为与其他系统的接口。目前支持的包括K8sevents、GitHub和GCPPubSub。Buses:事件传输的方式,目前支持的有Stub、Kafka和GCPPubSub。流程:定义对事件的反应。这可能是一个连锁反应,而不是一个单一的反应。所以,我们要做的就是选择一个Source,选择一个Bus,然后定义一个Flow。在本文中,我们选择K8events和StubClusterBus。先安装它们:kubectlapply-fhttps://storage.googleapis.co...kubectlapply-fhttps://storage.googleapis.co...在生成流之前,有一个小问题:K8event是由Kubernetes内部生成。要接收它,必须通过服务帐户对其进行授权。这是Kubernetes的要求,不是本文的重点。和之前一样,保存后执行:apiVersion:v1kind:ServiceAccountmetadata:name:feed-sanamespace:defaultapiVersion:rbac.authorization.k8s.io/v1kind:Rolemetadata:name:create-deploymentnamespace:defaultrules:apiGroups:["apps"]resources:["deployments"]verbs:["get","list","watch","create","update","delete","patch"]这使feed-sa能够部署接收适配器.apiVersion:rbac.authorization.k8s.io/v1kind:RoleBindingmetadata:名称:feed-sa-deploy命名空间:defaultsubjects:kind:ServiceAccount名称:feed-sa命名空间:defaultroleRef:种类:角色名称:create-deploymentapiGroup:rbac.authorization.k8s.ioThis允许从所有名称空间读取k8s事件。apiVersion:rbac.authorization.k8s.io/v1kind:ClusterRoleBindingmetadata:名称:feed-adminsubjects:kind:ServiceAccount名称:feed-sa名称空间:defaultroleRef:种类:ClusterRole名称:查看apiGroup:rbac.authorization.k8s.io接下来是主要步骤,创建流程:vimflow.yaml:apiVersion:flows.knative.dev/v1alpha1kind:Flowmetadata:名称:k8s-event-flow命名空间:defaultspec:serviceAccountName:feed-sa触发器:eventType:dev.knative.k8s.eventresource:k8sevents/dev.knative.k8s.eventservice:k8seventsparameters:namespace:defaultaction:target:kind:RouteapiVersion:serving.knative.dev/v1alpha1name:helloworld-go然后运行??kubectlapply-fflow.yaml就可以了。让我们看看它是否真的在运行?稍等片刻运行:kubectlgetpods会看到k8s-event-flow-xxx这个job已经运行完毕。然后启动helloworld-go的pod。我们看日志:kubectllogshelloworld-go-xxxxxuser-container,会看到如下结果:Helloworldreceivedarequest.Helloworldreceivedarequest.Helloworldreceivedarequest.Helloworldreceivedarequest....这表明此链接有效。那么,这个流的定义说明了什么?第一种是使用刚刚定义的服务帐户。然后在触发器中定义什么样的事件可以满足条件。这里我们说default命名空间中的所有k8events都是合格的。在动作中,我们定义使用什么样的处理方法。本例直接调用helloworld-go服务。结语Knative是今年最新的云计算演进方向之一。阿里云支持Kubernetes,可以成功运行Knative、Istio等应用。也可以去阿里云亲自体验一下!当然,作为一个备受瞩目的新项目,Knative也会经历成长的阵痛。我们会持续跟进并提供与Knative相关的分享,但不限于实践,敬请期待。