Knative Serving 概述
Knative Serving 将一组对象定义为 Kubernetes 自定义资源定义 (CRD)。这些资源用于定义和控制Serverless工作负载在集群上的行为方式。
Knative Serving CRD资源
Knative Serving 将一组对象定义为 Kubernetes 自定义资源定义 (CRD)。这些资源用于定义和控制serverless工作负载在集群上的行为方式。
Service
1. Service资源API在service.serving.knative.dev群组。
2. 对自动编排Serverless类型应用的功能的抽象,负责自动管理工作负载的整个生命周期。
3. 控制其他对象的创建,以确保您的应用程序具有Route、Configuration和每次服务更新的新Revision。可以将服务定义为始终将流量路由到最新版本或固定版本。
Route
1. Route资源API在route.serving.knative.dev群组。
2. 将请求流量路由到目标Revision。
3. 支持将流量按比例切分并路由到多个Revision。
Configuration
1. Configuration资源API在configuration.serving.knative.dev群组。
2. 反映了Service当前期望状态(Spec)的配置。
3. 它提供了代码和配置之间的清晰分离,并遵循十二要素应用程序方法。
4. Service对象的更新,也将导致Configuration的更新。
Revision
1. Revision资源API在revision.serving.knative.dev群组。
2. Service的每次代码或配置变更都会生成一个Revision。
3. Revision是不可变的对象,只要有用就可以保留。
4. Knative Serving Revisions 可以根据传入流量自动扩大和缩小。
Knative Serving 架构
Networking Layer and Ingress
在这种情况下,Ingress 并不指 Kubernetes Ingress 资源。它指的是公开对集群上资源的外部访问的概念。
Knative Serving 依赖于满足Knative Networking 规范的Networking Layer。为此,Knative Serving定义了一个内部KIngress资源,它充当不同的多个可插拔网络层的抽象。目前,社区提供并支持三个网络层:net-kourier、net-contour、net-istio。
流量和 DNS
每个网络层都有一个控制器,负责监视KIngress资源并进行相应的配置Ingress Gateway。它还将status通过该资源报告回信息。
Ingress Gateway 用于将请求路由到activator或直接路由到 Knative Service Pod,具体取决于采用的模式(proxy/serve)。Ingress Gateway 用来处理来自集群内部和集群外部的请求。
为了使 Ingress Gateway 能够在集群外部访问,必须使用类型为 LoadBalancer 或类型为 NodePort 的 Kubernetes 服务来公开它。然后将 DNS 配置为指向 Ingress 网关的 IP 或名称。
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
Queue-Proxy 是 Knative Service Pod 中的一个 sidecar 容器。它负责收集指标并在将请求转发到用户容器时强制执行所需的并发性。如果需要的话,它也可以充当队列,类似于activator 。
Knative Serving 工作模式
Knative Serving HTTP 请求流程
HTTP 请求流程
下图显示了 Knative Serving 的不同请求流和控制平面。请注意,某些组件(例如autoscaler和 apiserver)不会根据每个请求进行更新,而是定期测量系统(这称为控制平面)。
HTTP router、activator和autoscaler 都是共享的集群级资源;这将新 Knative 服务的开销减少到仅在服务未使用时使用元数据,并允许更有效地管理和升级这些共享组件。
路由决策在 HTTP 路由器(ingress层)的每个请求级别上做出一次,并记录在请求的内部标头中。一旦请求被分配给Revision,后续路由取决于测量的流量;在低流量或零流量时,传入请求将路由到activator,而在高流量级别(备用容量大于target-burst-capacity)时,流量将直接路由到应用程序 Pod。
低流量请求流程
当特定Revision的流量较低或为零时,HTTP 路由器会将流量发送到activator,其中包括指示所选Revision的标头。activator充当传入请求的缓冲区或队列 - 如果请求路由到当前没有可用pod数量的Revision,则activator会延迟该请求并向autoscaler发出需要额外pod数量的信号。
当autoscaler检测到Revision的可用Pod数量低于请求的数量时,它会从 Kubernetes 请求增加 Pod 的数量。
当这些新的 Pod 准备就绪或现有的 Pod 有容量时,activator会将延迟的请求转发到就绪的 Pod。如果需要启动一个新的 Pod 来处理请求,这称为冷启动。
高流量请求流程
当Revision具有大量流量(备用容量大于target-burst-capacity)时,直接使用Revision的 pod 地址对ingress路由器进行编程,并将activator从流量中删除。当不需要activator的额外缓冲时,这可以减少延迟并提高效率。在所有情况下,队列代理都会保留在请求路径中。
如果流量低于突发容量阈值(计算方式为:current_demand + target-burst-capacity > (pods * concurrency-target)),则ingress路由器将被重新编程以将流量发送到activator Pods。
通过将activator 端点的子集写入Revision服务的端点来完成ingress 和activator 之间的路由流量。与 Revision 对应的 Kubernetes Service 是 selectorless服务,并且可能包含 Revision 的 pod 端点或activator端点。使用selectorless服务的原因如下:
1. 某些ingress实现不允许跨namespace服务引用。activator在knative-serving 命称空间中运行。
2. 某些ingress实现无法无缝处理路由端点的支持 Kubernetes 服务的更改。
3. 通过在每个Revision的基础上使用子集化,传入的请求被集中到少量的activator,这些activator可以更有效地做出就绪/未就绪的容量决策。每个Revision的有效activator数量较少并不是一个扩展问题,因为当Revision扩大以接收更多流量时,activator将从请求路径中删除。
Queue-Proxy
Knative Serving会为每个Pod注入一个称为Queue Proxy的容器
1. 为业务代码提供代理功能
1. Ingress GW接收到请求后,将其发往目标Pod实例上由Queue Proxy监听的8012端口
2. 而后,Queue Proxy再将请求转发给业务代码容器监听的端口
3. 报告实例上的多个有关客户端请求的关键指标为给Autoscaler
4. Pod健康状态检测(Kubernetes探针,每秒最多探测一次)
5. 为超出实例最大并发量的请求提供缓冲队列
Queue Proxy预留使用了如下几个端口
1. 8012:HTTP协议的代理端口
2. 8013:HTTP/2端口,用于代理gRPC
3. 8022:管理端口,如健康状态检测等
4. 9090:暴露给Autoscaler进行指标采集的端口
5. 9091:暴露给Prometheus进行监控指标采集的端口
Knative Serving Revision
Revision 介绍
Revision是 Knative Serving 资源,其中包含对 Knative 服务所做的每个更改的应用程序代码和配置的时间点快照。
您不能直接创建Revision或更新Revision规范。Knative Service上的spec.template的每次变动,都会自动生成一个新的Revision。但是,您可以强制删除Revision,以处理泄漏的资源以及删除已知的错误Revision,以避免将来在管理 Knative 服务时出现错误。
Revision通常是不可变的,除非它们可能引用可变的 Kubernetes 核心资源,例如 ConfigMap 和 Secret。Revision也可以通过Revision默认值的更改而发生变化。对默认值的更改通常是语法上的,而不是语义上的。
Revision 管理员配置
如果您拥有 Knative 安装的集群管理员权限,则可以修改 ConfigMap 以更改集群上 Knative 服务Revision的全局默认配置选项。
Revision 垃圾收集配置
当 Knative 服务的Revision处于非活动状态时,它们会在设定的时间段后自动清理并回收集群资源。这称为垃圾收集。
| 自创建Revision以来在考虑对Revision进行垃圾回收之前必须经过的时间。 |
| 自Revision最后一次处于活动状态以来在Revision被考虑进行垃圾回收之前必须经过的时间。 |
| 要保留的非活动Revision的最小数量。 |
| 要保留的非活动Revision的最大数量。 |
如果修订属于以下任一类别,则始终保留:
> 该Revision处于活动状态并且正在被Route引用。
> Revision是在设置指定retain-since-create-time的时间内创建的。
> 在最后设置指定retain-since-last-active-time的时间内Route引用了Revision 。
> 现有Revision的数量少于设置指定min-non-active-revisions的数量。
Revision 示例
立即清理任何不活动的Revision
apiVersion: v1
kind: ConfigMap
metadata:
name: config-gc
namespace: knative-serving
data:
min-non-active-revisions: "0"
max-non-active-revisions: "0"
retain-since-create-time: "disabled"
retain-since-last-active-time: "disabled"
...
保留最后十个非活动Revision
apiVersion: v1
kind: ConfigMap
metadata:
name: config-gc
namespace: knative-serving
data:
retain-since-create-time: "disabled"
retain-since-last-active-time: "disabled"
max-non-active-revisions: "10"
...
禁用集群上的gc
apiVersion: v1
kind: ConfigMap
metadata:
name: config-gc
namespace: knative-serving
data:
retain-since-create-time: "disabled"
retain-since-last-active-time: "disabled"
max-non-active-revisions: "disabled"
...
Revision 开发者配置
虽然在不修改 Knative 服务配置的情况下无法手动创建修订版,但您可以修改现有修订版的规范来更改其行为。
禁用Revision的gc
apiVersion: serving.knative.dev/v1
kind: Revision
metadata:
annotations:
serving.knative.dev/no-gc: "true"
...
Knative Serving 配置Private KService
全局配置
默认情况下,通过 Knative 部署的服务使用.svc.cluster.local域,这意味着它们是私有的,因此没有公共 IP 地址或公共 URL。
单KService配置
可以对服务或路由进行标记,使用“networking.knative.dev/visibility”标签,并设定其值为cluster-local。
示例
为 Knative 服务添加标签
# kubectl label kservice ${KSVC_NAME} networking.knative.dev/visibility=cluster-local
为 Knative 路由添加标签
# kubectl label route ${ROUTE_NAME} networking.knative.dev/visibility=cluster-local
为 Kubernetes 服务添加标签
# kubectl label service ${SERVICE_NAME} networking.knative.dev/visibility=cluster-local
Knative Serving 流量管理
集群外部流量
通过KService的外部名称(ksvc-name.namespace.DOMAIN)将流量发给入口网关(例如istio-ingressgateway的Service使用的ExternalIP)的外部地址
通过KService使用的Domainmapping中定义的名称,将流量发往入口网关的外部地址
集群内部流量
未启用mesh时:通过KService的内部名称(ksvc-name.namespace.DOMAIN)将流量发往Knative使用的istio-system名称空间下的knative专用本地流量网关knative-local-gateway
启用mesh时,流量将由mesh根据流量策略进行转发
Knative Serving API
API 群组
# kubectl api-versions |grep knative
autoscaling.internal.knative.dev/v1alpha1
caching.internal.knative.dev/v1alpha1
networking.internal.knative.dev/v1alpha1
serving.knative.dev/v1
serving.knative.dev/v1alpha1
serving.knative.dev/v1beta1
serving.knative.dev 群组
# kubectl api-resources --api-group=serving.knative.dev
NAME SHORTNAMES APIVERSION NAMESPACED KIND
configurations config,cfg serving.knative.dev/v1 true Configuration
domainmappings dm serving.knative.dev/v1beta1 true DomainMapping
revisions rev serving.knative.dev/v1 true Revision
routes rt serving.knative.dev/v1 true Route
services kservice,ksvc serving.knative.dev/v1 true Service
autoscaling.internal.knative.dev 群组
# kubectl api-resources --api-group=autoscaling.internal.knative.dev
NAME SHORTNAMES APIVERSION NAMESPACED KIND
metrics autoscaling.internal.knative.dev/v1alpha1 true Metric
podautoscalers kpa,pa autoscaling.internal.knative.dev/v1alpha1 true PodAutoscaler
networking.internal.knative.dev 群组
# kubectl api-resources --api-group=networking.internal.knative.dev
NAME SHORTNAMES APIVERSION NAMESPACED KIND
certificates kcert networking.internal.knative.dev/v1alpha1 true Certificate
clusterdomainclaims cdc networking.internal.knative.dev/v1alpha1 false ClusterDomainClaim
ingresses kingress,king networking.internal.knative.dev/v1alpha1 true Ingress
serverlessservices sks networking.internal.knative.dev/v1alpha1 true ServerlessService
caching.internal.knative.dev 群组
# kubectl api-resources --api-group=caching.internal.knative.dev
NAME SHORTNAMES APIVERSION NAMESPACED KIND
images caching.internal.knative.dev/v1alpha1 true Image
Knative Serving 运行应用说明
在Serving上,可通过创建Knative Service对象来运行应用;该Service资源会自动创建一个Configuration对象和一个Route对象。
一个Configuration对象,它会创建一个Revision,并由该Revision自动创建一个Deployment对象和一个PodAutoscaler对象
一个Route对象,它会创建一个Kubernetes Service对象和一组Istio VirtualService对象 {kservice-name}-ingress {kservice-name}-mesh
Knative Service 资源规范
Knative Service资源(简称kservice或ksvc)的资源规范主要有两个字段
template:用于创建或更新Configuration,任何更新,都将创建新的Revision对象
traffic:用于创建或更新Route对象
查看 ksvc 资源规范
# kubectl explain ksvc
KIND: Service
VERSION: serving.knative.dev/v1
DESCRIPTION:
Service acts as a top-level container that manages a Route and
Configuration which implement a network service. Service exists to provide
a singular abstraction which can be access controlled, reasoned about, and
which encapsulates software lifecycle decisions such as rollout policy and
team resource ownership. Service acts only as an orchestrator of the
underlying Routes and Configurations (much as a kubernetes Deployment
orchestrates ReplicaSets), and its usage is optional but recommended. The
Service's controller will track the statuses of its owned Configuration and
Route, reflecting their statuses and conditions as its own. See also:
https://github.com/knative/serving/blob/main/docs/spec/overview.md#service
FIELDS:
apiVersion <string>
APIVersion defines the versioned schema of this representation of an
object. Servers should convert recognized schemas to the latest internal
value, and may reject unrecognized values. More info:
https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources
kind <string>
Kind is a string value representing the REST resource this object
represents. Servers may infer this from the endpoint the client submits
requests to. Cannot be updated. In CamelCase. More info:
https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
metadata <Object>
Standard object's metadata. More info:
https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata
spec <Object>
ServiceSpec represents the configuration for the Service object. A
Service's specification is the union of the specifications for a Route and
Configuration. The Service restricts what can be expressed in these fields,
e.g. the Route must reference the provided Configuration; however, these
limitations also enable friendlier defaulting, e.g. Route never needs a
Configuration name, and may be defaulted to the appropriate "run latest"
spec.
status <Object>
ServiceStatus represents the Status stanza of the Service resource.
示例
apiVersion: serving.knative.dev/v1
kind: Service
metadata: <Object>
name: <string> # ksvc名称
namespace: <string> # ksvc所在的名称空间
labels: <map[string]string> # 标签
annotations: <map[string]string> # 注解
serving.knative.dev/rollout-duration: "380s" # 指定流量迁移过程的时长
spec:
template:
spec:
containers:
- image: ghcr.dockerproxy.com/knative/helloworld-go:latest
env:
- name: TARGET
value: "Go Sample v3"
traffic: <[]Object> # 流量管理
configurationName: <string> # 流量的目标configuration,实际接收流量的为其最新版的revision
latestRevision: <boolean> # 显式指定最新版的revision,与revisionName字段互斥
percent: <integer> # 该路由项切分到的流量比例
revisionName: <string> # 流量目标的revision
tag: <string>
url: <string>
参考文档
https://knative.dev/docs/serving/