在本系列博客的第1部分中(【云原生架构】节俭 Kubernetes operator 第1部分:简介),我们介绍了这样一种想法,即Kubernetes Operator(在大规模部署时)可以消耗大量资源,无论是实际资源消耗还是可调度容量的消耗。我们还介绍了一种想法,即无服务器技术可以通过在活动控制器部署空闲时减少其规模来减少对Kubernetes集群的影响(【云原生架构】节俭K8s Operator 第2部分:将控制器缩放到零)。
在第2部分中,我们仅基于在闲置时将Pod实例的数量缩放为零的想法,介绍了一种无需更改源即可减少现有控制器的资源开销的技术。
在这个由三部分组成的系列文章的最后一篇文章中,我们将展示如何适应现有Operator,以利用Knative服务提供的内置的从零到零的功能。
Operator架构
在较低的级别上,典型Operator的主要任务是监视Kubernetes后备存储(etcd)中发生的更改并对它们做出反应(例如,通过安装和管理Kafka集群)。Informer对象监视事件并将接收到的事件放入工作队列中,以确保在给定时间对于给定对象只有一个协调器(下图中的Handle Object)处于活动状态。Informer对象不断监视事件,而协调器仅在将项目插入工作队列中时才运行,这是在Knative服务中应用从零缩放的主要候选对象。
从0.6开始,Knative Eventing为Kubernetes API服务器事件提供了Cloud Event导入器(或源)。通过将此导入程序与Knative服务提供的“从零缩放”功能结合使用,我们可以实现调节器的“从零缩放”的目标。在这种新的体系结构中,通知程序不会缩放到零,但是现在可以在多个Operator之间共享,从而大大降低了整体资源消耗。
无服务器样本控制器
让我们展示如何使现有控制器适应在Knative中运行。考虑Kubernetes示例控制器项目,该项目演示了如何直接在Go客户端库的顶部实现Operator。该项目定义了一个称为Foo的新CRD,并提供了一个控制器来为Foo对象创建部署。
apiVersion: samplecontroller.k8s.io/v1alpha1
kind: Foo
metadata:
name: example-foo
spec:
deploymentName: example-foo
replicas: 1
generates:
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: example-foo
ownerReferences:
- apiVersion: samplecontroller.k8s.io/v1alpha1
blockOwnerDeletion: true
controller: true
kind: Foo
name: example-foo
spec:
...
修改示例代码以使Foo运算符无服务器
我们修改了原始示例代码,以使Foo运算符变得无服务器(新代码可在GitHub上找到)。这是我们所做的:
我们删除了所有通知程序的创建和配置:通知程序监视Kubernetes后备存储中发生的更改。现在,这是由API服务器事件源完成的(请参见下文)。
我们添加了一个通用通知程序,以侦听传入的云事件并将它们排队在工作队列中:该通知程序将云事件的消耗与处理分离,以进行垂直扩展,(最重要的是)确保在给定的时间仅协调一个给定的对象。
相反,对索引器(内部Informer组件)的所有调用都是针对API服务器进行的:不言自明。
我们添加了一个配置文件来监视Foo和Deployment类型的事件:
apiVersion: sources.eventing.knative.dev/v1alpha1
kind: ApiServerSource
metadata:
name: example-foo
spec:
serviceAccountName: example-foo
resources:
- apiVersion: samplecontroller.knative.io/v1alpha1
kind: Foo
- apiVersion: apps/v1
kind: Deployment
controller: true
sink:
apiVersion: serving.knative.dev/v1alpha1
kind: Service
name: example-foo-reconcile
资源部分指定要监视的对象类型(Foo和Deployment)。controller:true告诉API服务器源控制器监视部署对象,并发送一个包含对控制它的对象的引用的云事件。
我们添加了一个配置文件以将协调程序部署为Knative服务:
apiVersion: serving.knative.dev/v1alpha1
kind: Service
metadata:
name: example-foo-reconcile
spec:
runLatest:
configuration:
revisionTemplate:
metadata:
annotations:
autoscaling.knative.dev/maxScale: "1"
autoscaling.knative.dev/window: "30s"
spec:
container:
image: $DOCKER_USER/knative-sample-controller
serviceAccountName: example-foo-reconcile
我们添加了两个注释来控制Knative pod自动缩放器的行为。第一个将并发Pod的最大值设置为一个,这样它们就不会互相干扰。第二个调整稳定窗口,以便给协调器足够的时间来完成。
您可以按照以下说明尝试自己运行它,以观察调节器缩小到零的情况。
与原始样本控制器示例相比,Knative变量确实有一些限制:
- 由于Knative事件0.6中的事件筛选有限,因此它不监视部署。
- 如果协调器容器崩溃,事件导入器将不重播事件,从而可能使系统处于不一致状态
- 没有定期的事件同步
所有这些限制将在以后的Knative事件发行版中解决。
无服务器的未来
这篇文章结束了我们有关无服务器Operator的系列文章。我们已经展示了两种方法来将Operator缩减到零,第一种适合现有的Operator部署,第二种利用Knative内置的无服务器功能。你选!