ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

在 Kubeless 中实现新事件源 Trigger:从 CRD 建模到控制器、清单与 CI 的完整开发指南

在 Kubeless 中实现新事件源 Trigger:从 CRD 建模到控制器、清单与 CI 的完整开发指南 后端云原生微服务【免费下载链接】kubelessKubernetes Native Serverless Framework项目地址https://gitcode.com/gh_mirrors/ku/kubeless点击查看免费下载本文是一份面向 Kubeless 贡献者的实操指南围绕如何把一个新的**事件源Event Source**接入 Kubeless 成为一等公民Trigger展开从理解 Trigger 在 Kubeless 架构中的定位到将事件源建模为 Kubernetes CRD、设计 Spec、自动生成客户端代码、编写 CRD Controller、构建镜像与 Manifest再到补齐单元测试与端到端测试的完整流程。读完本文你将掌握新增一个 Trigger 的全部步骤与仓库内的参考实现位置能够独立完成一个 Trigger 控制器仓库的搭建。Trigger 是什么Kubeless 三大核心概念之一在动手开发前需要先建立对 Trigger 的准确认知。根据 Kubeless 架构文档Kubeless 建立在Functions函数、Triggers触发器、Runtime运行时三大核心概念之上Function要执行的代码及其元数据运行时、依赖、构建指令等拥有独立的生命周期Trigger事件源与需要在该事件源发生事件时被调用的函数之间的关联。当事件源发生事件时Kubeless 会确保关联的函数被调用且至多一次at most once一个 Trigger 可以关联单个函数也可以取决于事件源类型关联多个函数Runtime函数执行所依赖的语言与运行时环境。Kubeless 的设计核心是充分复用 Kubernetes 的Custom Resource DefinitionCRD与Custom Controller机制函数被建模为一个 CRDfunctions.kubeless.io每一个事件源都被建模为独立的 Trigger CRD并为每个 CRD 配套一个独立的控制器来处理其增删改查CRUD。这种独立 CRD 独立控制器的设计带来了清晰的责任分离与模块化解耦也决定了新增一个事件源 Trigger 的工作方式每个 Trigger 控制器都在独立的仓库中开发而不是修改 Kubeless 核心仓库。Kubeless CLI 侧的集成也印证了这一结构cmd/kubeless/trigger/trigger.go 中TriggerCmd通过AddCommand依次挂载了cronjob、kafka、http、nats、kinesis五个子命令组每个子命令组内部再挂载create/delete/list/updateKinesis 还额外有publish与createStream见 cmd/kubeless/trigger/kinesis/kinesis_trigger.go。你可以在 docs/triggers.md 看到当前已支持的触发器清单。开发前准备为 Trigger 建立独立仓库每个 Kubeless Trigger 控制器都在自己的仓库中开发。如果你想创建新的 Trigger就需要为其新建一个仓库。当前已存在的 Trigger 是新建仓库的最佳模板HTTP Trigger对应 CLI 集成见 cmd/kubeless/trigger/http/CronJob Trigger对应 CLI 集成见 cmd/kubeless/trigger/cronjob/Kafka Trigger对应 CLI 集成见 cmd/kubeless/trigger/kafka/NATS Trigger对应 CLI 集成见 cmd/kubeless/trigger/nats/从仓库源码结构还可以推断cmd/kubeless/trigger/kinesis/ 对应的 AWS Kinesis Trigger 也遵循同样的独立仓库模式其清单与测试辅助逻辑参见 manifests/kinesis/kinesalite.yaml 与 script/libtest.bash 中的deploy_kinesis_trigger_controller/wait_for_kubeless_kinesis_controller_ready等函数。一个 Trigger 仓库的完整交付物应包括CRD 定义、Go API 类型、自动生成的客户端代码、控制器实现、CLI 子命令、Dockerfile、Makefile 构建目标、jsonnet Manifest 以及单元测试与端到端测试。下面按步骤展开。第一步将事件源建模为 CRD为事件源创建新的 CRD 是第一步新 Trigger 的 CRD 与现有 Trigger 的 CRD 大体相似。以 Kafka Trigger 为例其 CRD 定义如下原文示例apiVersion: apiextensions.k8s.io/v1beta1 kind: CustomResourceDefinition metadata: name: kafkatriggers.kubeless.io spec: group: kubeless.io names: kind: KafkaTrigger plural: kafkatriggers singular: kafkatrigger scope: Namespaced version: v1beta1关键字段说明metadata.name采用复数形式.group的格式如kafkatriggers.kubeless.io这是 Kubernetes CRD 的全局唯一标识spec.groupAPI 组Kubeless 系列 CRD 统一使用kubeless.iospec.names.kindGo 侧类型名与kubectl输出中显示的 Kind建议使用驼峰命名如KafkaTriggerspec.names.plural/spec.names.singular分别对应kubectl get kafkatriggers的复数资源名与单数资源名spec.scopeNamespaced即 Trigger 是命名空间级资源spec.versionv1beta1与 Kubeless 当前 API 版本保持一致。为事件源起一个合适、直观intuitive的名字名字会直接暴露在 API 组、资源名和 Kind 中需要能让人一眼看出其代表的事件源。仓库内 kubeless-non-rbac.jsonnet 中同样以apiextensions.k8s.io/v1beta1的CustomResourceDefinition形式定义了functions.kubeless.io、httptriggers.kubeless.io、cronjobtriggers.kubeless.io三个 CRD其names字段分别设置了plural、singular、kind可作为新 Trigger CRD 的对照参考{ apiVersion: apiextensions.k8s.io/v1beta1, kind: CustomResourceDefinition, metadata: objectMeta.name(httptriggers.kubeless.io), spec: {group: kubeless.io, version: v1beta1, scope: Namespaced, names: {plural: httptriggers, singular: httptrigger, kind: HTTPTrigger}}, }第二步设计 CRD 的 SpecGo 类型定义好 CRD 之后需要把事件源及其属性建模为资源对象的 Spec。Kubernetes API 资源对象的关键属性请遵循 Kubernetes 社区约定的 API conventions对外部资料的引用仅为说明规范来源实际实现以仓库与官方约定为准。除Spec部分外定义一个 Trigger 所需的其余部分与现有 Trigger 高度相似。以 Kafka Trigger 的 Go 类型定义为例原文示例type KafkaTrigger struct { metav1.TypeMeta json:,inline metav1.ObjectMeta json:metadata Spec KafkaTriggerSpec json:spec }metav1.TypeMeta提供apiVersion与kindmetav1.ObjectMeta提供名称、命名空间、标签等标准元数据二者与所有 Kubernetes 资源一致事件源特有属性全部收敛在Spec中。仓库内 pkg/apis/kubeless/v1beta1/function.go 中Function与FunctionSpec的定义展示了同样的三段式结构可作为 Spec 设计的直接参照type Function struct { metav1.TypeMeta json:,inline metav1.ObjectMeta json:metadata Spec FunctionSpec json:spec }建模 Spec 时最需要设计的部分是事件源如何与函数关联。根据事件源的性质你可能需要让一个事件源关联单个函数也可能需要关联多个函数应选用合适的机制来表达这种关联例如 Kafka Trigger 使用Kubernetes 标签选择器Label Selector将任何带匹配标签的函数与事件源关联起来——这是一对多关联的典型实现例如 HTTP Trigger 这类天然对应单个函数的事件源则使用函数名直接指向某个已部署的函数。在 CLI 层可以看到 Kafka Trigger 标签选择器的实际形态cmd/kubeless/trigger/kafka/create.go 中把--function-selector解析出的labelSelector.MatchLabels写入kafkaTrigger.Spec.FunctionSelector.MatchLabels并将topic写入kafkaTrigger.Spec.Topic同时createCmd要求--trigger-topic与--function-selector两个参数为必填MarkFlagRequired并支持--dryrun输出 YAML/JSON 清单而不实际创建kubelessUtils.DryRunFmt。这套必填参数 dry-run 预览的模式可以照搬到新 Trigger 的 CLI 中。第三步代码生成clientset / lister / informer定义好新 Trigger 的类型后需要把类型注册进 API 组并自动生成配套的客户端代码以便在控制器中方便地监听与操作该资源放置与注册将新 Trigger 的类型文件放到pkg/apis/kubeless/v1beta1/路径下并在register.go中登记新类型。仓库内 pkg/apis/kubeless/v1beta1/register.go 的addKnownTypes展示了注册模式——通过runtime.NewSchemeBuilder(addKnownTypes)构造SchemeBuilder在addKnownTypes里调用scheme.AddKnownTypes(SchemeGroupVersion, Function{}, FunctionList{})。新 Trigger 需要把YourTrigger{}、YourTriggerList{}加入同一 GroupVersionkubeless.io/v1beta1并补齐对应的DeepCopyObject方法可由生成器产出。运行代码生成在 Trigger 仓库内执行make update或./hack/update-codegen.sh即可为新的 API 资源对象自动生成 clientset、lister 与 informer。仓库内 hack/update-codegen.sh 的生成命令如下${CODEGEN_PKG}/generate-groups.sh deepcopy,client,informer,lister \ github.com/kubeless/kubeless/pkg/client github.com/kubeless/kubeless/pkg/apis \ kubeless:v1beta1可见生成器覆盖deepcopy、client、informer、lister四类代码输出目录为pkg/client相对pkg/apis生成目标组为kubeless:v1beta1。生成产物在本仓库中的落点可参考 pkg/client/clientset/versioned/、pkg/client/informers/externalversions/kubeless/v1beta1/、pkg/client/listers/kubeless/v1beta1/ 三个目录的既有结构。生成代码的用途自动生成的 clientset 用于以强类型方式读写 CRD 对象informer 用于监听对象变化并维护本地缓存lister 用于从缓存中按索引快速查询对象。这三者在下一步编写控制器时非常有用原文表述为 comes handy是控制器骨架的基础设施。第四步编写 CRD Controller最关键的一步控制器是整个 Trigger 接入中最重要的一步。就控制器的骨架而言它与现有的 Kafka、NATS、HTTP Trigger 控制器高度相似。功能上控制器做两件核心的事情监听 Kubernetes API Server 上对新 Trigger 对象的增删改查CRUD操作并采取相应动作当事件源中发生事件时触发关联的函数。本仓库虽然没有内置各 Trigger 控制器它们在各独立仓库中但 pkg/controller/function_controller.go 作为 Kubeless 核心的 Function 控制器完整展示了 Kubeless 体系内informer workqueue worker这一标准控制器骨架可直接移植为 Trigger 控制器的模板。从该文件可以提炼出如下要点informer 事件回调通过kv1beta1.NewFunctionInformer(...)创建 informer并注册AddFunc/UpdateFunc/DeleteFunc回调function_controller.go。回调中使用cache.MetaNamespaceKeyFunc生成namespace/name形式的 key 并推入 workqueueUpdateFunc中通过functionObjChanged对比新旧对象的 Spec 差异比较 Function、Checksum、Handler、Deps、Timeout 等字段避免无意义的重复入队workqueue 限速重试workqueue.NewRateLimitingQueue(workqueue.DefaultControllerRateLimiter())创建限速队列常量maxRetries 5控制最大重试次数function_controller.goprocessNextItem中处理成功调用queue.Forget失败且重试次数未达上限时调用queue.AddRateLimited达到上限则放弃并上报错误Run 生命周期Run(stopCh)中启动 informer、cache.WaitForCacheSync等待缓存同步随后wait.Until(c.runWorker, time.Second, stopCh)循环消费队列finalizer 清理Function 对象在删除时通过 finalizerkubeless.io/function保证关联资源Deployment、Service、ConfigMap、HPA、构建 Job 等被清理后才真正删除见 function_controller.go 与deleteK8sResources。如果你的事件源控制器需要管理附属资源建议采用同样的 finalizer 模式。原文档建议以现有 Kafka 控制器的代码与逻辑作为参考来编写新 Trigger 控制器本仓库内 tests/integration-tests-kafka.bats 中的Test 1:n association between Kafka trigger and functions也验证了 Kafka Trigger 的核心行为——多个函数可通过标签选择器同时关联到同一个 Kafka Trigger 上。此外触发关联函数这一动作的具体形态取决于事件源协议HTTP 回调、消息队列消费、定时调度等需要在新 Trigger 控制器中针对事件源客户端实现但无论哪种形态watch CRD 对象 消费事件源 调用函数的责任边界是一致的。第五步构建控制器二进制与 Docker 镜像确保你的控制器是一个独立的二进制可以由 Makefile 构建。请参照现有某个 Trigger 控制器仓库中的cmd目录来组织入口同时确保有对应的Dockerfile来构建控制器镜像并以其他 Trigger 控制器的 Dockerfile 为参考。仓库内 Makefile 展示了 Kubeless 核心组件二进制 镜像的构建范式可迁移到 Trigger 仓库binary: CGO_ENABLED0 ./script/binary controller-build: ./script/binary-controller -os$(OS) -arch$(ARCH) docker/function-controller: controller-build cp $(BUNDLES)/kubeless_$(OS)-$(ARCH)/kubeless-function-controller $ function-controller: docker/function-controller $(DOCKER) build -t $(CONTROLLER_IMAGE) $其中 script/binary 通过go install ./cmd/...产出可执行文件。对应地docker/function-controller/Dockerfile 是以已编译好的二进制为基础构建最终控制器镜像的。为你的 Trigger 仓库增加合适的 Makefile 目标让控制器二进制与 Docker 镜像都能一键构建。第六步Manifestjsonnet 生成的 YAML为新的 Trigger 创建一个 jsonnet 文件并确保生成的 YAML 文件中包含三部分CRD 定义新 Trigger 的CustomResourceDefinition见第一步Trigger 控制器的 Deployment将控制器镜像部署到集群中并注入所需环境变量与 ServiceAccount必要的 RBAC 规则允许控制器 watch/读写新 Trigger CRD 及其管理的附属资源。仓库内 kubeless-non-rbac.jsonnet 是核心组件的清单参考它以crd数组集中定义全部 CRD以container.default(http-trigger-controller, kubeless/http-trigger-controller:v1.0.3)的形式为各 Trigger 控制器声明 Deployment 容器含imagePullPolicy与controllerEnv而 kubeless.jsonnet 则在非 RBAC 版本之上追加了ClusterRole/ClusterRoleBinding与控制器所需的 RBAC 规则如对kubeless.io组的functions、httptriggers、cronjobtriggers资源的get/list/watch/update/delete权限以及对batch组cronjobs、jobs的操作权限。新 Trigger 的 jsonnet Manifest 中大部分内容与 Kafka 或 HTTP Trigger 通用因此直接以现有 jsonnet 清单为蓝本替换资源名、镜像与 RBAC 条目即可。补充CLI 子命令集成推荐虽然原文档未单列此步但从仓库结构看Kubeless 所有 Trigger 都在kubeless trigger命令下提供了一等公民的 CLI 支持cmd/kubeless/trigger/trigger.go。要让新 Trigger 可被用户操作建议同样在 Trigger 仓库中实现一个独立的 CLI 入口提供create、list、update、delete子命令如 Kafka 的 create.go 所示并在 Kubeless 主仓库的TriggerCmd.AddCommand(...)中登记该步通常由 Kubeless 核心仓库配合完成。参数设计上可复用 Kafka 的先例必填事件源参数、--namespace、--dryrun与--output。第七步CI 与测试新 Trigger 能正常工作后添加测试以保障并维持 Trigger 的功能至关重要。每个 Trigger 应包含单元测试覆盖基本功能如 CRD Spec 的构造、标签选择器的解析、控制器核心逻辑端到端测试确保与最新版 Kubeless 核心镜像的兼容性。运行测试的 CI 是 TravisCIKafka Trigger 仓库中的 CI 配置文件可作示例文件需在 CI 中至少定义 4 个 job构建二进制与 Manifest 的 job在 Minikube 场景下进行端到端功能测试的 job将测试所用镜像以latest标签推送的 job在构建新 tag 时自动生成 GitHub Release 的 job。以上大部分功能依赖已经开发好的脚本因此只需要修改 YAML 中的少量数据与名称即可复用。测试用例定义在每个 Trigger 仓库的tests/目录中这些测试是加载了公共库的bats测试公共库即 script/libtest.bash。该库提供了大量可直接复用的辅助函数例如k8s_wait_for_pod_ready/k8s_wait_for_pod_gone/k8s_wait_for_pod_logline等待 Pod 就绪、消失或出现指定日志wait_for_kubeless_kafka_server_ready/wait_for_kubeless_nats_controller_ready/wait_for_kubeless_kinesis_controller_ready等待各事件源与控制器就绪这些函数也印证了独立控制器 独立就绪等待的通用模式kubeless_kafka_trigger_delete/kubeless_nats_trigger_delete清理测试遗留的 Triggerverify_clean_object验证删除后关联资源确实被清理。仓库内 tests/integration-tests-kafka.bats 是一个可直接照抄的 bats 测试样例每个test块通过load ../script/libtest加载公共库然后调用deploy_kafka、wait_for_kubeless_kafka_server_ready、deploy_function、deploy_kafka_trigger、verify_function等函数串联出部署事件源 → 部署函数 → 创建 Trigger → 验证函数被事件触发的完整场景。以 Kafka 为参照为新 Trigger 设计类似的实用测试场景即可。收尾检查清单将以上步骤串起来一个新 Trigger 的完整交付应满足独立仓库以现有 Trigger 仓库为模板CRD 定义复数.group命名、kubeless.io组、Namespaced作用域、v1beta1版本Go 类型TypeMeta ObjectMeta Spec三段式Spec 中明确事件源 ↔ 函数的关联机制标签选择器或函数名类型放入pkg/apis/kubeless/v1beta1/并更新register.go运行make update/./hack/update-codegen.sh生成 deepcopy、client、informer、lister控制器informer workqueue 骨架watch CRD CRUD消费事件源并触发函数必要处使用 finalizer 清理独立二进制 Dockerfile Makefile 构建目标jsonnet ManifestCRD 控制器 Deployment RBAC并生成对应 YAML单元测试 bats 端到端测试复用script/libtest.bashCI 配置定义构建、Minikube E2E、latest镜像推送、tag 自动发版 4 个 job。完成上述工作后新的事件源就能以与 HTTP、CronJob、Kafka、NATS 等现有 Trigger 完全一致的方式成为 Kubeless 体系中的一等公民。赞分享后端云原生微服务【免费下载链接】kubelessKubernetes Native Serverless Framework项目地址https://gitcode.com/gh_mirrors/ku/kubeless点击查看免费下载相关推荐Filament Modal 弹窗组件实战:从 trigger 触发、Alpine 事件控制到完整自定义指南Filament Modal 弹窗组件实战:从 trigger 触发、Alpine 事件控制到完整自定义指南 在 Filament 中, x filament后端UI组件前端理解usearch的数据对齐内存访问效率优化技术理解usearch的数据对齐内存访问效率优化技术 在高性能向量搜索领域内存访问效率往往是决定系统性能的关键因素。usearch作为一款快速开源的向量与字符串向量数据库搜索引擎Meshery自定义资源CRD开发与控制器实现指南Meshery自定义资源CRD开发与控制器实现指南 在云原生应用开发中自定义资源Custom ResourceCR和自定义资源定义Custom Re云原生微服务运维DevOps上一篇百度脑图在线思维整理与可视化的终极利器下一篇终极指南使用App Installer轻松安装iOS应用和IPA文件创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表