Knative Eventing 中 Channel 如何注入默认 Provisioner

本文涉及的产品
容器镜像服务 ACR,镜像仓库100个 不限时长
简介: 在 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。

相关实践学习
Docker镜像管理快速入门
本教程将介绍如何使用Docker构建镜像,并通过阿里云镜像服务分发到ECS服务器,运行该镜像。
容器应用与集群管理
欢迎来到《容器应用与集群管理》课程,本课程是“云原生容器Clouder认证“系列中的第二阶段。课程将向您介绍与容器集群相关的概念和技术,这些概念和技术可以帮助您了解阿里云容器服务ACK/ACK Serverless的使用。同时,本课程也会向您介绍可以采取的工具、方法和可操作步骤,以帮助您了解如何基于容器服务ACK Serverless构建和管理企业级应用。 学习完本课程后,您将能够: 掌握容器集群、容器编排的基本概念 掌握Kubernetes的基础概念及核心思想 掌握阿里云容器服务ACK/ACK Serverless概念及使用方法 基于容器服务ACK Serverless搭建和管理企业级网站应用
目录
相关文章
|
6月前
|
消息中间件 Kubernetes Cloud Native
【Kubernetes的Knative Servina、Knative Eventing 核心概念及Broker、Channel and Trigger使用】
【Kubernetes的Knative Servina、Knative Eventing 核心概念及Broker、Channel and Trigger使用】
Knative Eventing 中如何实现 Registry 事件注册机制
在最新的 Knative Eventing 0.6 版本中新增了 Registry 特性, 为什么要增加这个特性, 该特性是如何实现的。针对这些问题,希望通过本篇文章给出答案。
3763 0
Knative 基本功能深入剖析:Knative Eventing 之 Sequence 介绍
作者 | 元毅,阿里云容器平台高级开发工程师,负责阿里云容器平台 Knative 相关工作。 导读:在实际的开发中我们经常会遇到将一条数据需要经过多次处理的场景,称为 Pipeline。那么在 Knative 中是否也提供这样的能力呢?其实从 Knative Eventing 0.7 版本开始,就提供了 Sequence CRD 资源,用于事件处理 Pipeline。
|
Go
透过 In-memory Channel 看 Knative Eventing 中 Broker/Trigger 工作机制
In-memory Channel是当前Knative Eventing中默认的Channel, 也是一般刚接触Knative Eventing首先了解到的Channel。本文通过分析 In-memory Channel 来进一步了解 Knative Eventing 中Broker/Trigger事件处理机制。
4579 0
|
JSON Kubernetes 监控
阿里云容器Kubernetes监控(十) - kube-eventer发布Webhook信道支持
kube-eventer是Kubernetes社区中针对事件监控、报警、chatOps场景的开源组件,新版本的kube-eventer支持了泛化Webhook的支持,更多信息请点击详情。
3830 0
阿里云容器Kubernetes监控(十) - kube-eventer发布Webhook信道支持
|
消息中间件 Kafka API
解读 Knative Eventing v0.14.0 版本特性
Knative Eventing v0.14.0 版本已于近期发布,新版本带来了哪些特性呢?本文会进行相关的解读
1437 0
Knative Eventing 之 Sequence 介绍
在处理数据时,往往会涉及到一个数据需要进行多次加工,这时候我们一般是通过Pipeline的方式进行处理。那么在Knative Eventing中是否也能支持对一个事件进行分步骤多次处理? 这个还真有。从 0.7 版本开始,Knative Eventing中提供了一个 Sequence 资源模型,可用于事件Pipeline处理。
1933 0
|
域名解析
Knative 基本功能深入剖析:Knative Serving 之服务路由管理
导读:本文主要围绕 Knative Service 域名展开,介绍了 Knative Service 的路由管理。文章首先介绍了如何修改默认主域名,紧接着深入一层介绍了如何添加自定义域名以及如何根据 path 关联到不同的 Knative Service 。
|
Kubernetes Serverless 容器
Knative 核心概念介绍:Build、Serving 和 Eventing 三大核心组件
Knative 主要由 Build、Serving 和 Eventing 三大核心组件构成。Knative 正是依靠这三个核心组件,驱动着 Knative 这艘 Serverless 巨轮前行。本文主要介绍这三个核心组件。
5204 0
|
1月前
|
存储 JSON 监控
Higress Controller**不是将配置信息推送到Istio的内存存储里面的**。
【2月更文挑战第30天】Higress Controller**不是将配置信息推送到Istio的内存存储里面的**。
14 1