Knative Eventing 中 Channel 如何注入默认 Provisioner

简介: 在 Knative Eventing 中创建 Broker 时,如果不指定 provisioner, 系统会自动创建默认的 provisioner, 那么这个机制是如何实现的呢? 本文基于 Knative Eventing 0.5 版本,介绍了这个实现机制。

场景

通常的在创建Broker时,我们需要通过 spec.ChannelTemplate 指定使用某个具体的 Channel Provisioner。例如这样的Broker:

apiVersion: eventing.knative.dev/v1alpha1
kind: Broker
metadata:
  name: pubsub-channel
spec:
  channelTemplate:
    provisioner:
      apiVersion: eventing.knative.dev/v1alpha1
      kind: ClusterChannelProvisioner
      name: gcp-pubsub

这里通过spec.ChannelTemplate 指定了名称为gcp-pubsub的provisioner。那么我们也遇到过这样的Broker:

apiVersion: eventing.knative.dev/v1alpha1
kind: Broker
metadata:
  name: default

并没有指定使用某个具体的 channel, 但创建完Broker之后会发现已经创建出来了Channel:

apiVersion: eventing.knative.dev/v1alpha1
kind: Channel
metadata:
  ...
  name: default-broker-8ml79
  namespace: default
  ownerReferences:
  - apiVersion: eventing.knative.dev/v1alpha1
    blockOwnerDeletion: true
    controller: true
    kind: Broker
    name: default
    uid: 2e4c3332-6755-11e9-a81f-00163f005e02
spec:
  provisioner:
    apiVersion: eventing.knative.dev/v1alpha1
    kind: ClusterChannelProvisioner
    name: in-memory
...

分析

我们知道 Broker创建之后,会通过 reconcile controller 会创建相应的Channel, 也就是下面这段代码:

// newChannel creates a new Channel for Broker 'b'.
func newChannel(b *v1alpha1.Broker, l map[string]string) *v1alpha1.Channel {
    var spec v1alpha1.ChannelSpec
    if b.Spec.ChannelTemplate != nil {
        spec = *b.Spec.ChannelTemplate
    }

    return &v1alpha1.Channel{
        ObjectMeta: metav1.ObjectMeta{
            Namespace:    b.Namespace,
            GenerateName: fmt.Sprintf("%s-broker-", b.Name),
            Labels:       l,
            OwnerReferences: []metav1.OwnerReference{
                *metav1.NewControllerRef(b, schema.GroupVersionKind{
                    Group:   v1alpha1.SchemeGroupVersion.Group,
                    Version: v1alpha1.SchemeGroupVersion.Version,
                    Kind:    "Broker",
                }),
            },
        },
        Spec: spec,
    }
}

分析上面这段代码,我们可以很清楚得出这样的结论:如果Broker中设置了Spec.ChannelTemplate, 那么Channel中会直接使用ChannelTemplate所对应的provisioner。
但如果没有设置的话, 那么Channel中的spec应该设置为nil。但事实上设置了in-memory provisioner, 那么这个是在哪里注入的呢?

注入机制

经过定位源代码,我们发现在channel_defaults.go中,发现下面这段代码:

func (c *Channel) SetDefaults(ctx context.Context) {
    if c != nil && c.Spec.Provisioner == nil {
        // The singleton may not have been set, if so ignore it and validation will reject the
        // Channel.
        if cd := ChannelDefaulterSingleton; cd != nil {
            prov, args := cd.GetDefault(c.DeepCopy())
            c.Spec.Provisioner = prov
            c.Spec.Arguments = args
        }
    }
    c.Spec.SetDefaults(ctx)
}

分析一下,我们可以看到当c.Spec.Provisioner==nil时, 会设置默认的Provisioner。
进一步分析ChannelDefaulterSingleton, 我们可以在webhook中赋予了实现设置:

...
// Watch the default-channel-webhook ConfigMap and dynamically update the default
// ClusterChannelProvisioner.
channelDefaulter := channeldefaulter.New(logger.Desugar())
eventingv1alpha1.ChannelDefaulterSingleton = channelDefaulter
configMapWatcher.Watch(channeldefaulter.ConfigMapName, channelDefaulter.UpdateConfigMap)
...

接着分析发现 ChannelDefaulter 实现了 GetDefault 方法:

// GetDefault determines the default provisioner and arguments for the provided channel.
func (cd *ChannelDefaulter) GetDefault(c *eventingv1alpha1.Channel) (*corev1.ObjectReference, *runtime.RawExtension) {
    // Because we are treating this as a singleton, be tolerant to it having not been setup at all.
    if cd == nil {
        return nil, nil
    }
    if c == nil {
        return nil, nil
    }
    config := cd.getConfig()
    if config == nil {
        return nil, nil
    }

    // TODO Don't use a single default, instead use the Channel's arguments to determine the type of
    // Channel to use (e.g. it can say whether it needs to be persistent, strictly ordered, etc.).
    dp := getDefaultProvisioner(config, c.Namespace)
    cd.logger.Info("Defaulting the ClusterChannelProvisioner", zap.Any("defaultClusterChannelProvisioner", dp))
    return dp, nil
}

并且这里是通过一个ConfigMap设置使用的默认provisioner, 这个ConfigMap名称为default-channel-webhook, 没错可以在 Knative Eventing 安装文件中发现这个资源:

apiVersion: v1
data:
  default-channel-config: |
    clusterdefault:
      apiversion: eventing.knative.dev/v1alpha1
      kind: ClusterChannelProvisioner
      name: in-memory
    namespacedefaults:
      some-namespace:
        apiversion: eventing.knative.dev/v1alpha1
        kind: ClusterChannelProvisioner
        name: some-other-provisioner
kind: ConfigMap
metadata:
  name: default-channel-webhook
  namespace: knative-eventing

那么分析到此,我们梳理一下整个注入的流程:
image

结论

通过上面的分析, 我们现在了解了默认provisioner的注入机制, 同时我们也可以通过 webhook 修改默认的provisioner。

相关实践学习
使用ACS算力快速搭建生成式会话应用
阿里云容器计算服务 ACS(Container Compute Service)以Kubernetes为使用界面,采用Serverless形态提供弹性的算力资源,使您轻松高效运行容器应用。本文将指导您如何通过ACS控制台及ACS集群证书在ACS集群中快速部署并公开一个容器化生成式AI会话应用,并监控应用的运行情况。
深入解析Docker容器化技术
Docker是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的Linux机器上,也可以实现虚拟化,容器是完全使用沙箱机制,相互之间不会有任何接口。Docker是世界领先的软件容器平台。开发人员利用Docker可以消除协作编码时“在我的机器上可正常工作”的问题。运维人员利用Docker可以在隔离容器中并行运行和管理应用,获得更好的计算密度。企业利用Docker可以构建敏捷的软件交付管道,以更快的速度、更高的安全性和可靠的信誉为Linux和Windows Server应用发布新功能。 在本套课程中,我们将全面的讲解Docker技术栈,从环境安装到容器、镜像操作以及生产环境如何部署开发的微服务应用。本课程由黑马程序员提供。     相关的阿里云产品:容器服务 ACK 容器服务 Kubernetes 版(简称 ACK)提供高性能可伸缩的容器应用管理能力,支持企业级容器化应用的全生命周期管理。整合阿里云虚拟化、存储、网络和安全能力,打造云端最佳容器化应用运行环境。 了解产品详情: https://www.aliyun.com/product/kubernetes
目录
相关文章
|
云安全 安全 网络安全
|
5天前
|
JavaScript 安全 前端开发
Nodejs Brotli decoder 代码执行漏洞 (CVE-2026-111497)10629
Node.js发布安全更新修复Brotli解码器高危RCE漏洞(CVE-2026-111497),建议受影响版本用户立即升级。
1932 1
|
11天前
|
人工智能 API 开发工具
DeepSeek Harness 神插件:白嫖 13 家大厂模型
`dsh-our-free-model` 是 DeepSeek Harness 神级插件:零配置、零API Key、零账号,聚合13家大厂免费模型(含DeepSeek V4.1 Flash、Kimi K3等),支持本地网关、用量看板与自动降级,真正实现“白嫖即用”。
1888 38
|
8天前
|
Web App开发 人工智能 前端开发
2026 年 AI 浏览器怎么选?Ego Lite、Tabbit、Chrome DevTools MCP 深度对比,开发者到底该用哪个?
2026年AI浏览器选型指南:Ego Lite专注多Agent协同(Mac优先),Tabbit国产首选,原生支持Windows与Codex控制;Chrome DevTools MCP非浏览器而是开发者利器,深度集成Console/Network/Performance调试能力,让AI真正“看懂并验证”前端代码。
1225 3
|
5天前
|
安全 应用服务中间件 Go
PHP2Shell 漏洞拆解:WordPress 与 nginx 为何中招
PHP2Shell 双 RCE 已遭在野利用:WordPress、Drupal 全在射程内,nginx 其实另有洞。拆成因与修复顺序
PHP2Shell 漏洞拆解:WordPress 与 nginx 为何中招
|
12天前
|
JSON 程序员 数据格式
最新版Notepad++下载、安装、配置保姆级教程(附官网安装包)
Notepad++ 是一款免费开源、轻量快速的 Windows 文本编辑器,支持多标签、语法高亮、代码折叠与宏录制,体积小、启动快、资源占用低,兼容 x64/x32/ARM 架构,是程序员和文字工作者的高效利器。
1884 0
|
13天前
|
安全 Linux 芯片
【万字长文】Ollama下载、安装、配置、使用保姆级教程(2026最新图解)
Ollama 是一款免费开源的本地大模型运行工具,支持 DeepSeek、Qwen 等主流模型,一条命令即可下载运行。2026 最新版 v0.35.1 官方安装包(1.47GB)已提供国内直连下载,纯本地、离线可用、无广告、无隐私泄露风险。
1162 4
|
16天前
|
存储 人工智能 安全
千问办公官网入口网页版登录:qwenwork.cn 注册送2000积分、登录送100积分
阿里云千问办公(QwenWork)是AI智能工作平台,支持一句话生成PPT、表格、网页、视频及数据分析。个人免费版送2000积分+每日登录赠100分,含1GB存储、5个发布页;企业版198元/席/月起。阿里千问办公QwenWork官网:https://t.aliyun.com/U/0VCTGt 阿里AI工作平台,一句话完成数据分析、PPT 生成、视频剪辑、网页搭建等复杂任务
|
4天前
|
安全 程序员 应用服务中间件
PHP 被曝两大致命漏洞,请所有程序员抓紧做这件事!
PHP 官方发布了紧急安全更新,一口气修复了两个严重漏洞。如果网站和服务器用了 PHP 应该怎么处理?漏洞的原理是什么?本文给你讲清楚
524 0