大家好,欢迎来到IT知识分享网。
云原生框架- KNative入门与原理
Serverless
Serverless通常被直译成“无服务器”,无服务器计算是可以让用户在不考虑服务器的情况下构建并运行应用程序。使用无服务器计算,应用程序仍在服务器上运行,但所有服务器管理工作均由Serverless平台负责。如机器申请、代码发布、机器宕机、实例扩缩容、机房容灾、按量付费等都由平台帮助自动完成,业务开发只需考虑业务逻辑的实现即可。
适用场景
- 无状态、短期运行、对冷启动延迟不敏感的工作负载
- 低频或有零星请求,但具有较大不可预测扩容变化需求的工作负载
- 业务需求变化迅速,要求快速开发实现的场景
KNative简介
Knative 是谷歌牵头的 Serverless 架构方案,旨在提供一套简单易用的 serverless 开源方案,把Serverless 标准化和平台化。
主要功能包括:
- 自动完成代码到容器的的应用构建部署,支持多版本发布(Reversion)
- 基于流量百分比的蓝绿发布(基于Istio)
- 根据请求自动扩缩容,支持缩容到零(AutoScaler)
- 基于 CloudEvents 的事件驱动 ,把应用(或者函数)和特定的事件进行绑定:当事件发生时,自动触发应用(或者函数)
- 丰富的可扩展的事件源
Knative 建立在 kubernetes 和 istio 平台之上,使用 kubernetes 提供的容器管理能力(deployment、replicaset、和 pods等),以及 istio 提供的网络管理功能(Ingress、LB、VirtualService、DestinationRule等)。
Knative 将重点放在两个关键组件上:为其提供流量Serving(服务),以及确保应用程序能够轻松地生产和消费Event(事件)。
Build(构建):
构建系统,把用户定义的函数和应用 build 成容器镜像
Serving(服务)
根据负载情况自动伸缩,包括在没有负载时能够缩减到零。
允许创建多个修订版本(revision)的应用流量策略,从而能够通过 URL 轻松路由到目标应用程序。
Event(事件)
使得生产和消费事件变得更容易。KNative 能够抽象出事件源,并允许操作人员使用自定义的消息传递层(Broker)。
Serving
组件介绍
包括了四个主要资源:Service
、Route
、Configuration
和 Revision
:
Service
: 自动管理工作负载整个生命周期。负责创建route
,configuration
。通过Service
可以指定路由流量使用最新的revision
,或者历史版本的revision
Route
:负责映射网络端点到一个或多个revision。可以通过多种方式管理流量。包括灰度流量和重命名路由Configuration
:负责保持工作负载的期望状态,包含了代码与配置相关的信息,修改一次Configuration
产生一个revision
,在 Configuration 中为部署定义所需的状态,最小化 Configuration 至少包括一个配置名称和一个要部署容器镜像的引用。Revision
:Revision
资源是对工作负载进行的每个修改的代码和配置的快照。Revision
是不可变对象,可以长期保留
其他资源:
Knative Ingress
: 外部请求首先到达Ingress Gateway,根据Kingress的配置做转发,默认采用istio-ingressgateway
作为其基础网络服务, 采用istio的VirtualService
配置来实现服务路由管理,流量百分比。
Knative 的 Pod 是由两个 Container 组成的:Queue-Proxy 和业务容器 User-Container。
Queue-proxy
: Queue-proxy 是每个业务 pod 中都存在的 Sidecar,每个发到业务pod的请求都会先经过 queue-proxy queue-proxy 的其主要作用是 收集和限制 业务应用的并发量,比如当一个 revision 设定了并发量为 5 ,那么 queue-proxy 会保证每次到达业务容器的请求数不会大于 5. 如果多于 5 个请求到达,queue-proxy 会将请求暂存在本地队列中。
暴露几个端口表示如下:
• 8012, queue-proxy 代理的http端口,流量的入口都会到 8012
• 8013, http2 端口,用于grpc流量的转发
• 8022, queue-proxy 管理端口,如健康检查
• 9090, queue-proxy的监控端口,暴露指标供 autoscaler 采集,用于KPA扩缩容
Autoscaler
: Knative 的扩缩容实现,通过request指标来决定是否扩缩容实例,指标来源有两个: 通过获取每个 pod queue-proxy 中的指标,Activator 通过Websocket 主动上报。Activator
: 流量的负载和缓存,是Knative能缩容到 0 的关键,实例为0 时(冷启动),流量会先转发到 Activator,由 Activator 通过 websocket主动触发 Autoscaler 扩缩容。Activator 只在 冷启动阶段是 proxy 模式,当实例足够时,autoscaler会更新 Ingress 指向 revision对应的pod,将请求导向真正的后端
Knative是如何做伸缩容的?
首先要解决的问题是根据什么指标判断伸缩容?cpu、内存、请求数?
knative使用的是并发请求数。
Knative的伸缩是核心是依赖修改deployment的replica数据来实现的。
如何采集请求数?
- 启动revision的pod时,也会启动一个autoscaler(一个knative revision只启动一个autoscaler),autoscaler自己本身也会scale到0,用于接收请求数统计和处理伸缩容。
- 业务pod中,会注入queue-proxy sidecar,用于接收请求,在这里会统计并发数,每秒向Autoscaler 汇报,接收到的请求会转发给业务container。
计算需要pod的个数?
Autoscaler接收到并发统计的时候,会根据算法计算需要的pod个数。
算法中有两种模式,分别是panic和stable模式,一个是短时间,一个是长时间,为了解决短时间内请求突增的场景,需要快速扩容。
如果服务中并发数设置了 10,这时候如果加载了 50 个并发请求的服务,Autoscaler 就会创建了 5 个 POD (50 个并发请求/10=POD)。
再举个例子
一个 Revision 每秒收到 350 个请求并且每次请求大约需要处理 0.5 秒。使用默认设置 (每 Pod 100 个并发请求)。
350 * .5 = 175 //一秒钟的并发就是175 175 / 100 = 1.75 ceil(1.75) = 2 pods
Stable Mode(稳定模式)
在稳定模式下,Autoscaler 根据每个pod期望的并发来调整Deployment的副本个数。根据每个pod在60秒窗口内的平均并发来计算,而不是根据现有副本个数计算,因为pod的数量增加和pod变为可服务和提供指标数据有一定时间间隔。
Panic Mode (恐慌模式)
Panic时间窗口默认是6秒,如果在6秒内达到2倍期望的并发,则转换到恐慌模式下。在恐慌模式下,Autoscaler根据这6秒的时间窗口计算,这样更能及时的响应突发的流量请求。每2秒调整Deployment的副本数达到想要的pod个数(或者最大10倍当前pod的数量),为了避免pod数量频繁变动,在恐慌模式下只能增加,不会减少。60秒后会恢复回稳定模式,进入文稳定模式后就会产生缩容。
KPA&HPA比较k8s
也有 hpa 进行扩缩容,但是 Knative 的 kpa 和 k8s 的 hpa 有很大的不同:
Knative KPA | k8s HPA | |
---|---|---|
指标类型 | 可以根据 请求量扩速容 | 只能根据 cpu memory 等指标扩缩容(或自定义指标) |
01启动 | 可以缩容到0和冷启动 | 只能缩容到1(如果缩容到0,就没有实例了,流量进不来,metrics数据永远为0,此时HPA也无能为力) |
指标获取方式 | Knative 指标获取有两种方式,Activator 和queue-proxy, activator的metrics 是通过websocket 主动push 给Autoscaler的,反应更迅速 | k8s 只能是通过prometheus 轮询获取。 |
反应速度 | Knative 默认会 计算 60 秒窗口内的平均并发数, 也会计算 6 秒的恐慌窗口,6s内达到目标并发的 2 倍,则会进入恐慌模式。在恐慌模式下,Autoscaler 在更短、更敏感的紧急窗口上工作 | 而且 HPA 本身设计比较保守,有一个稳定期(默认5min)默认在5min内没有重新扩缩容的情况下,才会触发扩缩容。当大流量突发过来时,如果正处在5min内的HPA稳定期,这个时候根据HPA的策略,会导致无法扩容。 |
从0启动扩容 整个流程
Eventing
基于事件驱动是 Serveless 的核心功能之一,通过事件驱动服务,满足了用户按需付费(Pay-as-you-go)的需求
组件介绍
kubectl get deployment -n knative-eventing -- 查看组件
Broker & Trigger
从 v0.5 开始,Knative Eventing 定义 Broker 和 Trigger 对象,从而能方便的对事件进行过滤。
- Trigger 描述基于事件属性的过滤器。同时可以根据需要创建多个 Trigger
Event Source | 向Broker发出Kubernetes的事件资源。 |
---|---|
Broker | 事件集代理层中心,接收Source Event 并转发到一个或者多个匹配的Trigger中 |
Trigger | Triggers定义了每个事件消费者能接受到的事件。Brokers使用triggers将事件发送给正确的消费者。每个trigger能够指定一个过滤器,该过滤器能够基于Cloud Event context attribute选择相关的事件。 |
Sink | 实际接收事件的消费者,目的端,例如Knative中的Service |
消息系统 | 每个 Broker 下面对应一个消息的系统,来承载对事件的整个流转。目前社区支持的消息系统包括 Kafka、NATS、Rocket MQ、Rabbit MQ 等。 |
Channel | 在使用Knative的Broker之前,必须安装一个通道提供者,例如InMemoryChannel(开发、测试)、Kafka或者NATS等 |
数据流程图

Broker & Trigger
模型的中 Event
传递的基本方式,其中事件传递的格式是标准的 CLoudEvent
的格式。简要介绍下图中的流程:
- 事件由事件源
Source
产生, Knative 支持多种事件源,如GitHub
、Heartbeats
、k8s
、ContainerSource
等 - 图中 事件源产生
type
为foo
的事件,发送到Broker
,其中 有三个Trigger
绑定了Broker
,两个Trigger
的filter
是type:foo
,也就是会关注type=foo
的事件,然后发送给对应的消费者。 Service1
和Service3
只是单纯的消费,并不回复事件Service2
收到事件后回复type=bar
的事件,事件重新传递到 Broker上,此时只有一个 Trigger 过滤了type:bar
事件被传送到Service3
消费。- 其中消费者是否回复事件是可选的。
底层实现原理
备注:控制平面为实线,数据平面为虚线,实线的方框为 Knative 组件,虚线的方框为 k8s CR 资源
Knative Eventing 事件传递过程中依赖消息通道 Channel,为了便于持久化,生产环境使用可持久化的消息通过(NatsStreaming ) 来做事件的消息通道,如果是开发调试,则直接用 InMemoryChannel 即可(只会保存在内存中,不会持久化)
系统数据平面流程
EventSource------> Broker------>Trigger------->SubScriber
- EventSource——> Broker
Broker
可以手动生成,或者通过给namespace
打 labeleventing.knative.dev/injection:true
,让sugar-controller
会自动生成对应的Broker
实例。EventSource
一般通过SinkURI
环境变量将Broker
的 地址传入 比如,Broker
的地址为http://broker-ingress.knative-eventing.svc.cluster.local/default/default
,该地址为broker-ingress
的地址# kubectl get broker NAME URL AGE READY REASON default http://broker-ingress.knative-eventing.svc.cluster.local/default/default 46h True
- Broker——>Trigger
broker-ingress
得到Broker
的信息(name namespace)之后, 可以通过Broker-Controller
得到对应的Channel
的status
信息, 如下得到channelAddress
的地址(http://default-kne-trigger-kn-channel.default.svc.cluster.local)
channelAddress
的地址是个svc 的地址,通过externalName
指向natss-ch-dispatcher
apiVersion: eventing.knative.dev/v1 kind: Broker metadata: name: default namespace: default status: address: --broker 地址 url: http://broker-ingress.knative-eventing.svc.cluster.local/default/default annotations: knative.dev/channelAPIVersion: messaging.knative.dev/v1beta1 -- channelAddress 地址,会被Broker-Controller更新 knative.dev/channelAddress: http://default-kne-trigger-kn-channel.default.svc.cluster.local knative.dev/channelKind: NatssChannel knative.dev/channelName: default-kne-trigger
natss-ch-dispatcher
负责将 消息(主题为channel.Name + "." + channel.Namespace
) 发布到Natss-Streaming
组件- Trigger——->SubScriber
natss-ch-dispatcher
不仅负责发布,还负责订阅消息,natss-ch-dispatcher
订阅natssChannel
, 获取natssChannel
的subscriber
的地址subscriberUri
,通过subscriberUri
发送消息给broker-filter
,跟broker-ingress
一样,subscriberUri
的地址是broker-filter
的 地址,通过请求path
区分哪个trigger
,请求 path :/triggers/<trigger namespace>/<trigger name>/<trigger UID>
apiVersion:
apiVersion: messaging.knative.dev/v1beta1 kind: NatssChannel metadata: name: default-kne-trigger namespace: default spec: --subscribers集合 subscribers: - generation: 1 replyUri: http://broker-ingress.knative-eventing.svc.cluster.local/default/default --subscriberUri2 subscriberUri: http://broker-filter.knative-eventing.svc.cluster.local/triggers/default/trigger2/c0f3f1bb-9a25-4fb2-b803-fc5cd74e57da uid: 9b4c991a-8912-4333-aa5a-caf053e5ee9c - generation: 1 replyUri: http://broker-ingress.knative-eventing.svc.cluster.local/default/default --subscriberUri3 subscriberUri: http://broker-filter.knative-eventing.svc.cluster.local/triggers/default/trigger3/28e7ba73-d514-4aea-a0de-7946fc21e7cc uid: 56d00260-e69f-4d7a-bd05-ca95 - generation: 1 replyUri: http://broker-ingress.knative-eventing.svc.cluster.local/default/default --subscriberUri1 subscriberUri: http://broker-filter.knative-eventing.svc.cluster.local/triggers/default/trigger1/3f6e7a8e-f7d1-4c8f-a25a-1970b6ab73e3 uid: 963fd671-097f-489a-a857-c1803ad3fb19 status: address: url: http://default-kne-trigger-kn-channel.default.svc.cluster.local
broker-filter
获取到Trigger
的信息后, 通过 根据 Trigger 的filter 将消息过滤,再决定是否将消息发给 对应的subscriber
,subscriber
可以从Triggerstatus
的subcriberUri
获取到,对于subscriber
Reply 的消息,broker-filter
发送到replyUri
地址上,http://broker-ingress.knative-eventing.svc.cluster.local/default/default
,也就是发送给 Broker (实际是broker-ingress
)apiVersion: eventing.knative.dev/v1 kind: Trigger metadata: name: trigger1 namespace: default spec: broker: default filter: attributes: type: dev.knative.sources.ping subscriber: ref: apiVersion: serving.knative.dev/v1 kind: Service name: service1 namespace: default status: subscriberUri: http://service1.default.svc.cluster.local
系统控制平面流程
- 详细流程
- 1.1
mt-broker-controller
watchBroker
的创建 - 1.2
mt-broker-controller
根据Broker
的配置,创建对应的Channel
,此处为NatssChannel
- 1.3
Natss-ch-controller
watchNatssChannel
的创建,更新Natss-Streaming
的服务端状态到NatssChannel
的 status - 1.4
Natss-ch-controller
创建 svc,externalname指向natss-ch-dispatcher
- 1.5
mt-broker-controller
watchNatssChannel
的status - 1.6
mt-broker-controller
更新Broker的status,
其中包含:Broker
的address
(broker-ingress
的地址),channel
的address
,供broker-ingress
使用 - 2.1
mt-broker-controller
watchTrigger
- 2.2
mt-broker-controller
根据Trigger(含 subscriber 的信息)
创建subscription,
其中包含subsciber(broker-filter)
的地址和 Broker
的信息
apiVersion: messaging.knative.dev/v1 kind: Subscription metadata: name: default-trigger1-3f6e7a8e-f7d1-4c8f-a25a-1970b6ab73e3 namespace: default spec: --生成系统目前对应的Channel channel: apiVersion: messaging.knative.dev/v1beta1 kind: NatssChannel name: default-kne-trigger reply: ref: apiVersion: eventing.knative.dev/v1 kind: Broker name: default namespace: default -- 生成Trigger对应的subscriber subscriber: uri: http://broker-filter.knative-eventing.svc.cluster.local/triggers/default/trigger1/3f6e7a8e-f7d1-4c8f-a25a-1970b6ab73e3
- 2.3
eventing-controller
watchsubscription
,解析subcriber
和replyUri
的地址(broker-ingress
的地址) - 2.4
eventing-controller
根据 已更新的subcription
列表,然后再去更新NatssChannel
里的subsriberUrl
和replyUrl
- 2.5
mt-broker-controller
根据subscription
和broker
的状态 更新Trigger
的状态
控制面和数据面的逻辑结合的地方在于:
broker-ingress
和broker-filter
:broker-ingress
watchBroker
,从Broker
的status
中获取channel
的地址(natss-ch-dispatch
的svc
的地址)broker-filter
watchTrigger
,根据 trigger 中subscriber 地址,将event filter 后决定是否发送到 对应的 target
用户配置Yaml示例
ping Event Source
apiVersion: sources.knative.dev/v1beta2 kind: PingSource metadata: name: ping-source spec: schedule: "*/2 * * * *" contentType: "application/json" data: '{"message": "Hello world!"}' sink: ref: apiVersion: eventing.knative.dev/v1 kind: Broker name: default --- SinkURI
Broker
default-broker.yaml
apiVersion: eventing.knative.dev/v1 kind: Broker metadata: name: default namespace: default
Trigger
apiVersion: eventing.knative.dev/v1 kind: Trigger metadata: name: trigger1 spec: filter: -- 过滤属性 attributes: type: foo subscriber: ref: apiVersion: serving.knative.dev/v1 kind: Service name: service1 --trigger2.yaml apiVersion: eventing.knative.dev/v1 kind: Trigger metadata: name: trigger2 spec: filter: -- 过滤属性 attributes: type: foo subscriber: ref: apiVersion: serving.knative.dev/v1 kind: Service name: service2 --trigger3.yaml apiVersion: eventing.knative.dev/v1 kind: Trigger metadata: name: trigger3 spec: filter: -- 过滤属性 attributes: type: bar subscriber: ref: apiVersion: serving.knative.dev/v1 kind: Service name: service3
Service
apiVersion: serving.knative.dev/v1 kind: Service metadata: name: service1 spec: template: spec: containers: - image: docker.io/zqb/event-display:v1 --service2 apiVersion: serving.knative.dev/v1 kind: Service metadata: name: service2 spec: template: spec: containers: - image: docker.io/zqb/event-display:v1 -- service3 apiVersion: serving.knative.dev/v1 kind: Service metadata: name: service3 spec: template: spec: containers: - image: docker.io/zqb/event-display-with-reply:v1
- 1.1
- Trigger——->SubScriber
Install
Install the Knative Serving component
To install the Knative Serving component:
Install the required custom resources by running the command:
kubectl apply -f https://github.com/knative/serving/releases/download/v0.24.0/serving-crds.yaml
Install the core components of Knative Serving by running the command:
kubectl apply -f https://github.com/knative/serving/releases/download/v0.24.0/serving-core.ya
Install a networking layer
The following commands install Istio and enable its Knative integration.
Install a properly configured Istio by following the Advanced Istio installation instructions or by running the command:
kubectl apply -l knative.dev/crd-install=true -f https://github.com/knative/net-istio/releases/download/v0.24.0/istio.yaml kubectl apply -f https://github.com/knative/net-istio/releases/download/v0.24.0/istio.yaml
Install the Knative Istio controller by running the command:
kubectl apply -f https://github.com/knative/net-istio/releases/download/v0.24.0/net-istio.yaml
Fetch the External IP address or CNAME by running the command:
kubectl --namespace istio-system get service istio-ingressgateway
\
Install the Eventing component
To install the Eventing component:
Install the required custom resource definitions (CRDs):
kubectl apply -f https://github.com/knative/eventing/releases/download/v0.24.0/eventing-crds.yaml
Install the core components of Eventing:
kubectl apply -f https://github.com/knative/eventing/releases/download/v0.24.0/eventing-core.yaml
- For information about the YAML files in Knative Eventing, see Description Tables for YAML Files.
kubectl apply --filename https://github.com/knative/eventing/releases/download/v0.24.0/eventing.yaml
- Verify the installation
Monitor the Knative components until all of the components show aSTATUS
ofRunning
orCompleted
:
kubectl get pods --namespace knative-eventing
Optional: Install a default channel (messaging) layer
kubectl apply --filename https://github.com/knative/eventing/releases/download/v0.24.0/in-memory-channel.yaml
文档地址
官方文档:https://knative.dev/
Github:https://github.com/knative
Knative Service Docshttps://github.com/knative/serving/tree/main/docs
Knative Eventing Docshttps://github.com/knative/eventing/tree/main/docs
免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://haidsoft.com/147767.html