前言
Serverless
最重要三个特征
- 隐藏了服务器的复杂性
- 按需付费
- 弹性伸缩
第1章 Knative入门
Knative有两个关键模块
Knative服务模块(Serving)
Knative
服务模块提供了简化的部署语法来使服务在Kubernetes
集群中运行,并且这些服务具备根据HTTP
负载自动扩容或者缩容到零的能力
Knative事件模块(Eventing)
可以将Knative Service
和其他的事件流系统(如Apache Kafka
主题等)通过非HTTP
方式连接起来
如何切换命名空间
$ kubectl config set-context --current --namespace=chapter-1
或者使用kubens
将当前命名空间设置为chapter-1
$ kubens chapter-1
第2章 理解Knative服务模块
Knative
服务模块通过提供更加简化的语法来部署应用,它会基于HTTP
负载的变化选择自动扩容或者缩容到零,Knative
平台将会管理服务的部署、版本、网络和扩缩容
Knative
服务模块通过HTTP URL
暴露服务,并且具有这么多安全的默认配置
Knative Service部署模型
在部署Knative Service
过程中,Knative Service
控制器会生成Knative
配置、Knative
修订版本(Revision
)、Knative
路由(Route
)
Knative配置
表示服务部署期望状态,并使用微服务开发的12要素应用将代码和配置完全分离。基于期望状态,Knative
配置控制器会为你的服务生成一个Kubernetes
部署(Deployment
)资源,每次对Knative
配置的更改都会产生一个新的Kubernetes
配置
Knative修订版本
每次对配置的更改都会产生一个新的修订版本。Knative
修订版本类似于版本控制标签,它是不可变的。每个Knative
修订版本都有一个与之关联的Kubernetes
部署,因此可以将应用回滚到任何一个正确的配置版本
Knative路由
用于访问或调用Knative
服务的URL
ksvc
是Knative Service
自定义资源(Knative Service Custom Resource
)的简称,在Kubernetes
集群中可通过以下命令查询
$ kubectl api-resources --api-group=serving.kative.dev
12要素应用
是一种构建
SaaS
应用的方法,为构建SaaS
应用提供了方法论
- 使用标准化流程自动配置,从而使新的开发者花费最少的学习成本加入这个项目
- 和操作系统间尽可能划清界限,在各个系统中提供最大的可移植性
- 选择适合部署在现代的云计算平台,从而在服务器和系统管理方面节省资源
- 将开发环境和生产环境的差异降到最低,并使用持续交付实施敏捷开发
- 可以在工具、架构和开发流程不发生明显变化的前提下实现扩展
这套理论适用于任意语言和后端服务(数据库、消息队列、缓存等)开发的应用程序
部署Knative Service
apiVersion: serving.knative.dev/v1
kind: Service
metadata:
name: greeter ❶
spec:
template:
metadata
name: greeter-v1 ❷
spec:
containers:
- image: quay.io/rhdevelopers/knative-tutorial-greeter:quarkus
livenessProbe:
httpGet:
path: /healthz
readinessProbe:
httpGet:
path: /healthz
❶ 服务名称。此Knative Service
创建的所有Kubernetes
资源都将在greeter
为前缀
❷ Knative
修订版本名字。如果不写,则Knative
会自动生成
运行命令创建Knative Service greeter
$ kubectl -n chapter-2 apply -f service.yaml
使用命令kubectl get ksvc
查询可用的ksvc
服务
$ kubectl -n chapter-2 get ksvc greeter
Knative
配置表示的是Knative Service
的当前状态,即ksvc
的哪个修订版本需要接收请求。当前应该只有一个修订版本;greeter-v
1,因此执行kubectl -n chapter-2 get configurations greeter
命令的结果应该是
$ kubectl get configrations greeter
更新Knative配置
12要素应用规定:对应用程序配置的任何更改均视为新修订,修订版本是不可变的,表示某个版本下的应用程序和配置状态。利用修订版本可以回滚到任何一个已知的历史状态
下图所示的Knative Service
部署模型,一个ksvc
生成一个配置,一个配置生成一个修订版本,一个修订版本生成一个部署,一个部署生成一个副本集(ReplicaSet
),最终由副本集生成Pod
来运行Knative Service
每次对Knative
应用的更改,比如修改镜像、修改存活探针、修改环境变量等,都会导致Knative
生成一个新的修订版本。每个修订版本都会生成一个相应的Kubernetes
部署
apiVersion: serving.knative.dev/v1
kind: Service
metadata:
name: greeter
spec:
template:
spec:
containers:
- image: quay.io/rhdevelopers/knative-tutorial-greeter:quarkus
env:
- name: MESSAGE_PREFIX
value: Namaste
livenessProbe:
httpGet:
path: /healthz
readinessProbe:
httpGet:
path: /healthz
traffic:
- tag: v1
revisionName: greeter-v1
percent: 100
- tag: v2
revisionName: greeter-v2
percent: 0
- tag: latest
latestRevision: true
percent: 0
如果greeter-v
1在60s
(Knative
默认的冷却窗口)内没有收到请求,那么实例数会自动缩容到0.当然这也是Knative
通过Serverless
服务帮你节省云计算资源的关键
对Knative Service
的任何修改都会产生一个新的修订版本。现在对于Knative Service greeter
应该有两个修订版本。使用以下命令查看这两个修订版本
$ kubectl -n chapter-2 get revisions
可以看到两个版本,分别为greeter-v1
和greeter-v2
可以看到有个新的修订版本扩容出来了,不过并不会生成新的路由、ksvc
和配置,可通过下面的指令来查看对应的Knative
资源
❶ kubectl get routes
❷ kubectl get ksvc
❸ kubectl get configurations
设置Knative Service版本间分流
可通过
Knative Service
中的traffic
设置来控制不同版本之间的流量分布。Knative Serving YAML
的流量设置traffic
描述了具体的流量分配方法,例如
apiVersion: serving.knative.dev/v1
kind: Service
metadata:
name: greeter
spec:
template:
spec:
traffic: ❶
- tag: v1 ❷
revisionName: greeter-v1 ❸
percent: 50 ❹
- tag: v2
revisionName: greeter-v2
percent: 50
❶ traffic
描述的流量分配
❷ tag
表示当前服务的版本,在traffic
中是唯一的
❸ revisionName
表示当前流量分配指定的版本
❹ 当前版本接收的流量的百分比,注意这里所有的版本接收的流量的百分比总和需要确保是100%
Knative
服务模块为每个标识符创建了一个唯一的服务URL
。可以使用以下命令查询
$ kubectl -n chapter-2 get ksvc greeter -oyaml | yq -r 'status.traffic[*.url]'
第3章 Knative自动扩缩容
Knative
通过缩容到零(scale-to-zero
)和自动扩缩容(autoscaling
)特性能够有效地满足这些需求
HPA
依赖于3个重要指标
❶ 并发数
❷ 每秒请求数
❸ CPU
KPA
可以看作HPA
的扩展版本,对默认HPA
算法进行了一些调整,使其能更适应且更快速地响应并处理流量驱动的Knative
扩缩容需求
配置Knative Service自动扩缩容
Kubernetes
的knative-serving
命名空间下的ConfigMap config-autoscaler
定义了所有关于缩容到零和自动扩缩容的参数 。可以用kubectl
命令查看该ConfigMap
$ kubectl -n knative-serving get cm config-autoscaler -o yaml
以下代码段展示了ConfigMap config-autoscaler
的简要内容。重点看本章示例的一些参数 ,如下所示
apiVersion: serving.knative.dev/v1
kind: KnativeServing
metadata:
name: knative-serving
namespace: knative-serving
spec:
config:
autoscaler:
container-concurrency-target-default: '100' ❶
enable-scale-to-zero: 'true' ❷
stable-window: 60s ❸
scale-to-zero-grace-period: 30s ❹
❶ 每个服务Pod
能随的最大请求并发数,默认值是100
❷ 是否允许缩容到零,默认值是true
❸ 监听请求调用次数和相关指标的时间窗口,默认值是60s
❹ 非活跃Pod
被终止的时间窗口,默认值是30s
缩容到零(即Knative
终止非活跃Pod
的能力)可以由参数enable-scale-to-zero
配置。enable-scale-to-zero
默认值为true
,表示如果Knative
在stable-window
时间窗口内未再收到请求,则会尝试启动Knative
的缩容到零功能。将此参数设置为false
,可以禁用此功能
stable-window
表示监听请求数指标的时间窗口。在默认情况下,如果Pod
过去60s
内未收到新的请求,则自动扩缩容会通过将Pod
标记为inactive
来启动缩容到零功能
Stable-to-zero-grace-period
是自动扩缩容监听被标记为inactive
的Pod
的时间窗口,并且在这个时间段内,自动扩缩容会尝试终止被标记为inactive
的Pod
配置Knative Service以处理突发请求
配置
Knative Service
的默认并发数来处理突增的请求。在
Knative Service
的YAML
配置中,可以加上注解来覆盖默认值和自动扩容参数
apiVersion: serving.knative.dev/v1
kind: Service
metadata:
name: preference
labels:
serving.knative.dev/visibility: "cluster-local"
spec:
template:
metadata:
annotations:
autoscaling.knative.dev/target: "10" ❶
spec:
containers:
- image: quay.io/rhdevelopers/istio-tutorial-preference:v1
env:
- name: COM_REDHAT_DEVELOPER_DEMOS_CUSTOMER_REST_RECOMMENDATIONSERVICE_MP_REST_URL
value: "http://recommendation.knativetutorial.svc.cluster.local"
❶ 配置Pod
的并发数是10
使用hey
工具进行压测
$ hey -c 50 -z 10s \ ❶
-host "$HOST_HEADER" \ ❷
"http://$IP_ADDRESS/?sleep=3&upto=10000&memload=100" ❸
❶ 表示使用hey
负载测试工具时间是10s
,并且请求并发数是50
❷ 和之前一样,设置请求头HOST
。在这个例子中,我们将其设置成prime-generator.chapter-3.example
❸ 对应的是请求URL
,具体如下
-
sleep
,模拟慢请求行为,通过将sleep
设置为3s
来模拟 -
upto
,不断计算生成质数,直到最大值 -
memload
,模拟内存负载为100MB
观察Pod
扩容过程
$ watch kubectl get pods
第4章 Knative事件模块
Knative事件模块有3种主要使用方法
事件源到接收器(Source to Sink)模式
是最简单的方法。提供了单个接收器,即事件接收服务,该服务不需要队列、背压和过滤。事件源到接收器模式不支持事件回复,意味着接收消息而不需要返回值。事件源只负责传递消息,而不会等待接收器的回复。可以把事件源到接收器模式比作发后不理(fire and forget
)消息模式
图4-1 事件源到接收器模式
source-sink
管道与订阅(channel and subscription)模式
在管道与订阅模式下,Knative
事件模式定义了一个管道,可以连接多个后端,例如内存、Kafka
和GCP PubSub
作为事件源。如图所示,在接收器服务框中,每个管道都至少有一个订阅者,每个订阅者都可以接收事件消息并按需处理。管道中的消息都会被格式化成标准CloudEvents
,并且继续往后发送给其他订阅者以进行下一步的处理。管道与订阅模式不具备过滤消息的能力
图4-2 管道与订阅模式
channels-subs
代理与触发器(Broker and Trigger)模式
代理与触发器模式类似于管道与订阅模式,但是它支持过滤消息。消息过滤机制允许订阅者订阅它感兴趣的来自代理的消息。Knative
事件模块会给每个代理默认创建一个Knative
事件模块管道。如图4-3所示,每个触发器都可以从代理处订阅消息,并且在其对应的代理上设置消息过滤。过滤器会在消息分发到消息接收器服务(订阅者)之前生效

使用事件源产生事件
Knative
事件源是指那些可以产生事件的组件。事件源的职责是连接、限流、捕获和缓存外部系统的事件,并且将这些事件传递给接收器
Knative
事件源安装了4个开箱即用的事件源
$ kubectl api-resources --api-group=sources.eventing.knative.dev
查看eventinghello Pod
日志
$ stern eventinghello -c user-container
网友评论