Knative是一个开源的企业级解决方案,用于在kubernetes平台中构建Serveless 和管理事件驱动的应用程序。
介绍
Knative is an Open-Source Enterprise-level solution to build Serverless and Event Driven Applications
Serverless Containers in Kubernetes environments.
- knative 是 k8s 原生扩展组件,用于部署、运行和管理 Serverless 类型的云原生应用
- knative(读音
kay-nay-tiv),由 Google 在 2018 年 7 月正式发布,当前由 Redhat、Google 和 IBM,以及各种初创公司组成的开源社区共同维护
为什么需要 Serverless 容器
- 配置简单,通过简化的 YAML 定义自定义的 CRDs
- 弹性伸缩:支持缩资源数量为 0
- 渐进式发布:根据您的需要选择发布策略
- 事件集成:支持处理来自多个源的事件
- 处理事件:支持事件代理(event broker)触发程序
- 可扩展:Kubernetes 原生集成和扩展
核心组件
说明:
Serving 和 Eventing 协同工作,管理任务和应用
Serving
- 支持由请求驱动计算
- 关注应用的网络、弹性伸缩(支持缩容至 0)和版本(revision)记录
- When you build or run a function, an Open Container Initiative (OCI) format container image is generated automatically for you, and is stored in a container registry(参考)
- 部署、管理和伸缩无状态应用规模
- 替代 kubernetes Deployment 控制器,负责编排运行基于 HTTP 协议的无状态应用
- knative 的 Serving 对象,相当于 Kubernetes 的 Service + Deployment 的功能
- 流量切分
- 通过在 Pod 扩展时缓冲请求来削峰填谷
- 基于单个请求进行负载均衡
- 基于请求的速度、自动扩缩容
Eventing
- 以声明的方式创建对事件源的订阅,并将事件路由到目标端点
- 管理事件的
订阅(subscription)、分发(delivery)和处理
- 基于
pub/sub 模型连接 Serving
- 旧版本存在的
Build 组件,已经拆分为 Tekton 项目,主要作用包括
- https://github.com/knative/specs
Knative Serving
参考:knative Serving,代码入口参考,相关文档
- 相关资源定义在
serving.knative.dev 群组中
- 主要包括 4 个 CRDs
Service: service.serving.knative.dev
- 自动控制下面三种类型资源对象的管理
- 是对 Serverless 类型应用功能的抽象,负责整个 Serverless 的声明周期
Route: route.serving.knative.dev
- 将请求路由到目标
Revision
- 支持将流量按比例切分并路由到多个
Revision
Configuration: configuration.serving.knative.dev
- 定义 Service 期望状态(spec)的配置
- Service 的更新,也将导致 Configuration 的更新
Revision: revision.serving.knative.dev,参考,代码定义
- Service 的每次代码或配置变更都生成一个 revision
- revision 是快照数据,不可变
- 相关 metrics,如 kn.queueproxy.depth
- Serving API
Knative Serving 子组件
参考:
子组件:
Activator Revision 中的 Pod 数量收缩至 0 时,activator 负责接收并缓存相关的请求,同时报告指标数据给 Autoscaler,并在 Autoscaler 在 Revision 上扩展出必要的 Pod 后,再将请求路由至相应的 Revision。
Autoscaler Knative 通过注入一个称为 queue-proxy 容器的 sidecar 代理来了解它部署的 Pod 上的请求,而 Autoscaler 会为每个服务使用“每秒请求数”来自动缩放其 Revision 上的 Pod。
Controller 负责监视 Serving CRD(KService、Configuration、Route 和 Revision)相关的 API 对象并管理它们的生命周期,是 Serving 声明式 API 的关键保障。
Webhooks 为 Kubernetes 提供的外置 Admission Controller,兼具 Validation 和 Mutation 的功能,主要作用于 Serving 专有的几个 API 资源类型之上,以及相关的 ConfigMap 资源上。负责验证和改变 Knative 资源。
DomainMapping 将指定的域名映射至 Service、KService,甚至是 Knative Route 之上,从而使用自定义域名访问特定的服务。
Queue-Proxy 是 Knative Service Pod 中的一个 sidecar 容器。它负责收集指标并在将请求转发到用户容器时强制执行所需的并发性。如果需要的话,它也可以充当队列,类似于 activator
Activator
本质上以通过 golang httputil.ReverseProxy 包实现对流量的代理,核心代理如下:
// Create activation handler chain
// Note: innermost handlers are specified first, ie. the last handler in the chain will be executed first
ah := activatorhandler.New(ctx, throttler, transport, networkConfig.EnableMeshPodAddressability, logger, tlsEnabled, tp)
ah = handler.NewTimeoutHandler(ah, "activator request timeout", func(r *http.Request) (time.Duration, time.Duration, time.Duration) { // 设置 timeout
if rev := activatorhandler.RevisionFrom(r.Context()); rev != nil { // 获取对应的 reversion 信息
responseStartTimeout := 0 * time.Second
# ResponseStartTimeoutSeconds 是请求路由层等待容器处理请求并开始发送网络流量的最长秒数。简言之,它衡量的是从请求送达容器到容器开始响应的这段时间。
if rev.Spec.ResponseStartTimeoutSeconds != nil {
responseStartTimeout = time.Duration(*rev.Spec.ResponseStartTimeoutSeconds) * time.Second
}
idleTimeout := 0 * time.Second
if rev.Spec.IdleTimeoutSeconds != nil {
idleTimeout = time.Duration(*rev.Spec.IdleTimeoutSeconds) * time.Second
}
return time.Duration(*rev.Spec.TimeoutSeconds) * time.Second, responseStartTimeout, idleTimeout
}
- mainHandler
- activationHandler 在处理请求前,activationHandler 会等待某个修订版本的活动端点 (active endpoint)可用
- ServeHTTP 实现 golang http.ServeHTTP 接口
- activationHandler 重要成员 Throttler(限流器)是 Knative Serving 自动扩缩容(Autoscaling)机制的一部分,它的主要作用是在服务从零实例(pod)扩容时,管理和限制进入的请求
- infiniteBreaker
- Maybe capacity 可用时执行 thunk
- 多个 activator 和后端 pod 的流量切分,pod 根据 ip 排序,每个 activator 将流量代理到指定的一组后端 pod 上,相关实现参考
- assignSlice 函数的作用是为特定的 Activator 实例挑选一部分 pod 来处理请求。这个机制只在直接通过 pod 的 IP 地址进行路由时才起作用,如果使用 ClusterIP 这种服务抽象,它就没有意义了。此外,为了正确执行,assignSlice 必须接收一份按地址排序的 pod 追踪器列表。
- pickIndices picks the indices for the slicing
- podTracker、NewBreaker podTracker 主要跟踪和管理服务 Pod 的生命周期,并确保请求能够被正确路由到这些 Pod 上
- inferIndex 返回此激活器(activator)切片的索引。如果 inferIndex 返回 -1,则意味着这个激活器暂时还不会接收任何流量,因此不参与切片;这种情况发生在启动后,但在它被接入(threaded into)端点(endpoints)之前(此操作在报告健康状态后最多需要 10 秒)。目前,我们只是对所有激活器的 IP 地址进行排序,并在这个列表中找到自身的索引。
- newRevisionThrottler 中根据 containerConcurrency 使用不同的 lbproxy:
If the number of pods is not divisible by the number of activators, we allocate one pod to each activator exclusively.
examples
1. we have 20 pods and 3 activators -> we'd get 2 remnants so activator with index 0,1 would each pick up a unique tracker
2. we have 24 pods and 5 activators -> we'd get 4 remnants so the activator 0,1,2,3 would each pick up a unique tracker
Autoscaling
Queue-Proxy
Knative Serving 中的 queue-proxy(队列代理)主要负责以下功能:
- 并发请求处理与限流 它会测量自动扩缩器所需的并发请求数量,尤其是在请求路径中移除了激活器(activator)时。此外,如果用户有要求,它还会实施
containerConcurrency(容器并发)的硬性限制。
- 优雅停机
queue-proxy 在 Pod 终止时负责处理优雅停机。它的做法是:拒绝新的请求、使就绪检查(readiness checks)失败,但同时继续处理并完成现有请求。
- 性能监控与启动优化
- 报告指标:它会从用户容器的外部报告 HTTP 指标和跟踪信息,这样就可以测量出基础设施所贡献的延迟。
- 加速启动:在启动阶段(即就绪之前),它会更频繁地探测用户容器,以实现比 Kubelet 探测(每秒最多探测一次)更早地提供服务。
- 就绪检查的重写 为了支持上述功能,Knative Serving 会将用户容器的
readinessProbe 重写为 queue-proxy 的一个参数。最终,queue-proxy 的就绪检查会同时包含它自身的就绪状态和用户容器的就绪状态。
Knative serving 服务创建的每个 Pod 都会创建一个queue-proxy Sidecar,以强制执行请求并发限制。队列代理预留 25 milliCPU,但不预留内存。队列代理的耗用情况取决于队列中的请求数量以及请求的大小;它可以占用的 CPU 和内存资源没有限制。
请求时,不会缓存请求体,而是业务容器接收到请求时,请求体以客户端指定的 chunk 流过queue-proxy,响应时有 buffer cache,本质上是 httputil.BufferPool。
监听的端口(参考):
// BackendHTTPPort is the backend, i.e. `targetPort` that we setup for HTTP/1 services.
BackendHTTPPort = 8012
// BackendHTTP2Port is the backend, i.e. `targetPort` that we setup for HTTP/2 services.
BackendHTTP2Port = 8013
// BackendHTTPSPort is the backend. i.e. `targetPort` that we setup for HTTPS services.
BackendHTTPSPort = 8112
// QueueAdminPort specifies the port number for
// health check and lifecycle hooks for queue-proxy.
QueueAdminPort = 8022
// AutoscalingQueueMetricsPort specifies the port number for metrics emitted
// by queue-proxy for autoscaler.
AutoscalingQueueMetricsPort = 9090
// UserQueueMetricsPort specifies the port number for metrics emitted
// by queue-proxy for end user.
UserQueueMetricsPort = 9091
| Probe Request Source |
Path |
Extra features |
comment |
| Activator probe requests |
:8012 |
With header K-Network-Probe=queue. Expected queue as response body. |
Probe requests from Activator before it proxies external requests |
| VirtualService/Gateway probe requests |
:8012 |
With header K-Network-Probe=probe and non-empty K-Network-Hash header |
This is used to detect which version of a VirtualService an Envoy Pod is currently serving. They are proxied from VirtualService to activator/queue-proxy. |
| Kubelet probe requests |
:8012 |
With non-empty K-Kubelet-Probe header or with header user-agent=kube-probe/* |
I don’t think currently kubectl sends probe requests to this path. We can delete it. Correct me if I was wrong. |
| Queue-proxy Readiness Exec probe requests |
:8022/health |
|
Probe requests triggered by Kubelet Readiness Exec probe. |
参考:
Knative Eventing
参考:CloudEvents 介绍
Knative Eventing 是一个 API 集合,允许应用使用事件驱动架构(Event-driven architecture)模型
核心概念
图参考自互联网
事件源(Event Source) 事件生产者的抽象,参考
事件类型(Event Type) 事件类型,在 Event Registry 中定义
事件处理流(Eventing Flows) 支持两种类型:
Event Sinks 能接收 Event 的可寻址(addressable)或可调用(Callable)的资源,Knative Eventing Sink 支持三种类型:
- Knative Service
- Channels
- Brokers
- Knative Eventing 支持的事件传递模式
- Sources to Sink:
- 单一 Sink 模式,事件接收过程中不存在队列和过滤等操作
- Channels and Subscriptions
- Event Source 将事件发到多个 Channel
- Channel 可以有多个 Subscription(即 Sink)
- Channel 中的事件以 Cloud Event 格式传递
- 不支持事件过滤
图参考
- Brokers and 【
- Brokers and Triggers
- 功能类似于 Channels and Subscriptions 模式,且支持消息过滤
- 事件过滤机制运行 Subscription 使用事件属性的条件表达式(Trigger)筛选事件
- Trigger 负责订阅 Broker,并对 Broker 传递的消息进行过滤,并对消息进行格式化
- 该模式为生产推荐的使用模式
代码架构
Knative 遵循 kubernetes 扩展方式,通过自定义 API 资源类型实现如下:
Serving 自动化完成服务的部署和扩缩容
Eventing 标准化事件驱动
- knative
- Serving
- Serving Controller
- Resources API
- Service
- Route
- Configuration
- Revision
- Eventing
- Eventing Controller
- Resources API
重要配置:
说明
- Knative 并不提供 FaaS 方案,用户可以在 Knative + Kubernetes 基础上,借助其他项目(如 Kyma)构建 FaaS 系统