09 — SriovOperatorConfig 控制器深度分析
一、模块定位
SriovOperatorConfigReconciler 是 SR-IOV Network Operator 的全局配置控制器。它负责管理 Operator 的所有基础设施组件:
- Webhook 配置同步(Mutating Webhook + Validating Webhook)
- Config Daemon DaemonSet 同步(SR-IOV Network Config Daemon)
- Device Plugin DaemonSet 同步(通过 helper.go 的
syncPluginDaemonObjs) - Metrics Exporter 同步
- OpenShift systemd 服务同步(通过 MachineConfig)
- Feature Gate 初始化
- 日志级别设置
- Finalizer 管理(确保删除时清理 Webhook)
二、模块整体结构
2.1 类图
2.2 Reconcile 整体流程图
三、核心业务逻辑深度解析
3.1 Reconcile 方法(逐行)
func (r *SriovOperatorConfigReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
logger := log.FromContext(ctx).WithValues("sriovoperatorconfig", req.NamespacedName)
logger.Info("Reconciling SriovOperatorConfig")
// 获取默认的 SriovOperatorConfig 对象
// 注意:在 SetupWithManager 中通过 defaultConfigPredicate() 过滤
// 只处理名为 DefaultConfigName 且在 vars.Namespace 命名空间中的对象
defaultConfig := &sriovnetworkv1.SriovOperatorConfig{}
err := r.Get(ctx, req.NamespacedName, defaultConfig)
if err != nil {
if apierrors.IsNotFound(err) {
// 默认配置不存在,等待创建
// 不重新排队,因为对象创建事件会自动触发 Reconcile
logger.Info("default SriovOperatorConfig object not found. waiting for creation.")
return reconcile.Result{}, nil
}
logger.Error(err, "Failed to get default SriovOperatorConfig object")
return reconcile.Result{}, err
}
// 设置全局日志级别
// 根据 SriovOperatorConfig.Spec.LogLevel 配置
snolog.SetLogLevel(defaultConfig.Spec.LogLevel)
// 检查对象是否正在被删除
if !defaultConfig.ObjectMeta.DeletionTimestamp.IsZero() {
// 对象正在被删除,执行清理逻辑
return r.handleSriovOperatorConfigDeletion(ctx, defaultConfig, logger)
}
// 确保 Finalizer 存在
// Finalizer 确保删除时会先清理 Webhook 等外部资源
if err = r.syncOperatorConfigFinalizers(ctx, defaultConfig, logger); err != nil {
return reconcile.Result{}, err
}
// 初始化 Feature Gates
// 从 SriovOperatorConfig.Spec.FeatureGates 读取配置
r.FeatureGate.Init(defaultConfig.Spec.FeatureGates)
logger.Info("enabled featureGates", "featureGates", r.FeatureGate.String())
Feature Gates 是 Operator 的功能开关机制。通过
SriovOperatorConfig.Spec.FeatureGatesmap 启用/禁用特定功能(如 ParallelNicConfig、ManageSoftwareBridges、MetricsExporter 等)。
// 记录 Injector 和 Webhook 的启用状态
if !defaultConfig.Spec.EnableInjector {
logger.Info("SR-IOV Network Resource Injector is disabled.")
}
if !defaultConfig.Spec.EnableOperatorWebhook {
logger.Info("SR-IOV Network Operator Webhook is disabled.")
}
// 获取 Policy 列表并按优先级排序
// 虽然此控制器不直接应用 Policy,但排序后的列表
// 在某些场景下需要保持一致的顺序
policyList := &sriovnetworkv1.SriovNetworkNodePolicyList{}
err = r.List(ctx, policyList, &client.ListOptions{})
if err != nil {
return reconcile.Result{}, err
}
sort.Sort(sriovnetworkv1.ByPriority(policyList.Items))
// 1. 同步 Webhook 对象(Injector + Operator Webhook)
if err = r.syncWebhookObjs(ctx, defaultConfig); err != nil {
return reconcile.Result{}, err
}
// 2. 同步 Config Daemon DaemonSet
if err = r.syncConfigDaemonSet(ctx, defaultConfig); err != nil {
return reconcile.Result{}, err
}
// 3. 同步 Device Plugin DaemonSet(通过 helper.go)
if err = syncPluginDaemonObjs(ctx, r.Client, r.Scheme, defaultConfig); err != nil {
return reconcile.Result{}, err
}
// 4. 同步 Metrics Exporter
if err = r.syncMetricsExporter(ctx, defaultConfig); err != nil {
return reconcile.Result{}, err
}
// 5. OpenShift 特定:创建 systemd 服务的 MachineConfig
if vars.ClusterType == consts.ClusterTypeOpenshift {
if r.PlatformHelper.IsHypershift() {
// Hypershift 没有 MCO(Machine Config Operator)
return ctrl.Result{}, fmt.Errorf("systemd mode is not supported on hypershift")
}
if err = r.syncOpenShiftSystemdService(ctx, defaultConfig); err != nil {
return reconcile.Result{}, err
}
}
logger.Info("Reconcile SriovOperatorConfig completed successfully")
return reconcile.Result{RequeueAfter: consts.ResyncPeriod}, nil
}
3.2 SetupWithManager — 监听配置
func (r *SriovOperatorConfigReconciler) SetupWithManager(mgr ctrl.Manager) error {
return ctrl.NewControllerManagedBy(mgr).
For(&sriovnetworkv1.SriovOperatorConfig{},
ctrl_builder.WithPredicates(defaultConfigPredicate())). // 只处理默认配置
Owns(&appsv1.DaemonSet{}). // 监听拥有的 DaemonSet 变更
Owns(&corev1.ConfigMap{}). // 监听拥有的 ConfigMap 变更
Complete(r)
}
// defaultConfigPredicate 只允许默认配置对象通过过滤
func defaultConfigPredicate() predicate.Predicate {
return predicate.NewPredicateFuncs(func(object client.Object) bool {
if object.GetName() == consts.DefaultConfigName && object.GetNamespace() == vars.Namespace {
return true
}
return false
})
}
设计要点:只监听默认
SriovOperatorConfig(名为default,在 Operator 命名空间中)。非默认配置对象被忽略。Owns确保 DaemonSet 和 ConfigMap 变更也能触发 Reconcile。
3.3 syncWebhookObjs — 同步 Webhook
func (r *SriovOperatorConfigReconciler) syncWebhookObjs(
ctx context.Context,
dc *sriovnetworkv1.SriovOperatorConfig,
) error {
// webhooks map 包含两个 webhook:
// - InjectorWebHookName → InjectorWebHookPath (网络资源注入器)
// - OperatorWebHookName → OperatorWebHookPath (Operator 验证 webhook)
for name, path := range webhooks {
// 准备渲染数据
data := render.MakeRenderData()
data.Data["Namespace"] = vars.Namespace
data.Data["SRIOVMutatingWebhookName"] = name
data.Data["NetworkResourcesInjectorImage"] = os.Getenv("NETWORK_RESOURCES_INJECTOR_IMAGE")
data.Data["SriovNetworkWebhookImage"] = os.Getenv("SRIOV_NETWORK_WEBHOOK_IMAGE")
data.Data["ReleaseVersion"] = os.Getenv("RELEASEVERSION")
data.Data["ClusterType"] = vars.ClusterType
data.Data["DevMode"] = os.Getenv("DEV_MODE")
data.Data["ImagePullSecrets"] = GetImagePullSecrets()
// 证书管理配置
data.Data["CertManagerEnabled"] = strings.ToLower(
os.Getenv("ADMISSION_CONTROLLERS_CERTIFICATES_CERT_MANAGER_ENABLED")) == trueString
data.Data["OperatorWebhookSecretName"] = os.Getenv("ADMISSION_CONTROLLERS_CERTIFICATES_OPERATOR_SECRET_NAME")
data.Data["OperatorWebhookCA"] = os.Getenv("ADMISSION_CONTROLLERS_CERTIFICATES_OPERATOR_CA_CRT")
data.Data["InjectorWebhookSecretName"] = os.Getenv("ADMISSION_CONTROLLERS_CERTIFICATES_INJECTOR_SECRET_NAME")
data.Data["InjectorWebhookCA"] = os.Getenv("ADMISSION_CONTROLLERS_CERTIFICATES_INJECTOR_CA_CRT")
// Hypershift 外部控制平面标志
data.Data["ExternalControlPlane"] = false
if r.PlatformHelper.IsOpenshiftCluster() {
external := r.PlatformHelper.IsHypershift()
data.Data["ExternalControlPlane"] = external
}
// ResourceInjectorMatchCondition Feature Gate
data.Data[consts.ResourceInjectorMatchConditionFeatureGate] =
r.FeatureGate.IsEnabled(consts.ResourceInjectorMatchConditionFeatureGate)
// 渲染 manifests
objs, err := render.RenderDir(path, &data)
if err != nil {
return err
}
// 如果 Injector 被禁用,删除相关对象
if !dc.Spec.EnableInjector && path == consts.InjectorWebHookPath {
for _, obj := range objs {
err = r.deleteWebhookObject(ctx, obj)
if err != nil {
return err
}
}
continue // 跳过同步,继续下一个 webhook
}
// 如果 Operator Webhook 被禁用,删除相关对象
if !dc.Spec.EnableOperatorWebhook && path == consts.OperatorWebHookPath {
for _, obj := range objs {
err = r.deleteWebhookObject(ctx, obj)
if err != nil {
return err
}
}
continue
}
// 同步 Webhook 对象
for _, obj := range objs {
err = r.syncK8sResource(ctx, dc, obj)
if err != nil {
return err
}
}
}
return nil
}
Webhook 动态启用/禁用:用户可以通过
SriovOperatorConfig.Spec.EnableInjector和Spec.EnableOperatorWebhook来控制 Webhook 的启停。禁用时不仅停止 Webhook 服务,还会删除所有相关的 Kubernetes 对象。
3.4 syncConfigDaemonSet — 同步 Config Daemon
func (r *SriovOperatorConfigReconciler) syncConfigDaemonSet(
ctx context.Context,
dc *sriovnetworkv1.SriovOperatorConfig,
) error {
data := render.MakeRenderData()
// 镜像配置(通过环境变量注入)
data.Data["Image"] = os.Getenv("SRIOV_NETWORK_CONFIG_DAEMON_IMAGE")
data.Data["Namespace"] = vars.Namespace
data.Data["SRIOVCNIImage"] = os.Getenv("SRIOV_CNI_IMAGE")
data.Data["SRIOVInfiniBandCNIImage"] = os.Getenv("SRIOV_INFINIBAND_CNI_IMAGE")
data.Data["OVSCNIImage"] = os.Getenv("OVS_CNI_IMAGE")
data.Data["RDMACNIImage"] = os.Getenv("RDMA_CNI_IMAGE")
data.Data["ReleaseVersion"] = os.Getenv("RELEASEVERSION")
data.Data["ClusterType"] = vars.ClusterType
data.Data["DevMode"] = os.Getenv("DEV_MODE")
data.Data["ImagePullSecrets"] = GetImagePullSecrets()
// 配置模式:Systemd vs DaemonSet
if dc.Spec.ConfigurationMode == sriovnetworkv1.SystemdConfigurationMode {
data.Data["UsedSystemdMode"] = true
} else {
data.Data["UsedSystemdMode"] = false
}
// Feature Gate 状态
data.Data["ParallelNicConfig"] = r.FeatureGate.IsEnabled(consts.ParallelNicConfigFeatureGate)
data.Data["ManageSoftwareBridges"] = r.FeatureGate.IsEnabled(consts.ManageSoftwareBridgesFeatureGate)
// CNI 二进制路径
envCniBinPath := os.Getenv("SRIOV_CNI_BIN_PATH")
if envCniBinPath == "" {
data.Data["CNIBinPath"] = "/var/lib/cni/bin" // 默认路径
} else {
data.Data["CNIBinPath"] = envCniBinPath
}
// 禁用的插件列表
if len(dc.Spec.DisablePlugins) > 0 {
data.Data["DisablePlugins"] = strings.Join(dc.Spec.DisablePlugins.ToStringSlice(), ",")
}
// 渲染 manifests
objs, err := render.RenderDir(consts.ConfigDaemonPath, &data)
if err != nil {
return err
}
// 同步每个对象
for _, obj := range objs {
if obj.GetKind() == "DaemonSet" {
// 为 DaemonSet 设置节点选择器
err = updateDaemonsetNodeSelector(obj, dc.Spec.ConfigDaemonNodeSelector)
if err != nil {
return err
}
}
err = r.syncK8sResource(ctx, dc, obj)
if err != nil {
return err
}
}
return nil
}
配置模式:Operator 支持两种配置模式:
- DaemonSet 模式(默认):Config Daemon 作为 DaemonSet 运行,直接配置节点
- Systemd 模式:通过 systemd 服务运行(OpenShift 上通过 MachineConfig 部署)
3.5 syncMetricsExporter — 同步 Metrics Exporter
func (r *SriovOperatorConfigReconciler) syncMetricsExporter(
ctx context.Context,
dc *sriovnetworkv1.SriovOperatorConfig,
) error {
data := render.MakeRenderData()
data.Data["Image"] = os.Getenv("METRICS_EXPORTER_IMAGE")
data.Data["Namespace"] = vars.Namespace
data.Data["ImagePullSecrets"] = GetImagePullSecrets()
data.Data["MetricsExporterSecretName"] = os.Getenv("METRICS_EXPORTER_SECRET_NAME")
data.Data["MetricsExporterPort"] = os.Getenv("METRICS_EXPORTER_PORT")
data.Data["MetricsExporterKubeRbacProxyImage"] = os.Getenv("METRICS_EXPORTER_KUBE_RBAC_PROXY_IMAGE")
data.Data["IsOpenshift"] = r.PlatformHelper.IsOpenshiftCluster()
// Prometheus Operator 集成
data.Data["IsPrometheusOperatorInstalled"] = strings.ToLower(
os.Getenv("METRICS_EXPORTER_PROMETHEUS_OPERATOR_ENABLED")) == trueString
data.Data["PrometheusOperatorDeployRules"] = strings.ToLower(
os.Getenv("METRICS_EXPORTER_PROMETHEUS_DEPLOY_RULES")) == trueString
data.Data["PrometheusOperatorServiceAccount"] = os.Getenv("METRICS_EXPORTER_PROMETHEUS_OPERATOR_SERVICE_ACCOUNT")
data.Data["PrometheusOperatorNamespace"] = os.Getenv("METRICS_EXPORTER_PROMETHEUS_OPERATOR_NAMESPACE")
// 节点选择器
data.Data["NodeSelectorField"] = GetDefaultNodeSelector()
if dc.Spec.ConfigDaemonNodeSelector != nil {
data.Data["NodeSelectorField"] = dc.Spec.ConfigDaemonNodeSelector
}
objs, err := render.RenderDir(consts.MetricsExporterPath, &data)
if err != nil {
return err
}
// 根据 FeatureGate 决定创建还是删除
if r.FeatureGate.IsEnabled(consts.MetricsExporterFeatureGate) {
// 启用:创建/更新资源
for _, obj := range objs {
err = r.syncK8sResource(ctx, dc, obj)
if err != nil {
return err
}
}
} else {
// 禁用:删除所有资源
err = r.deleteK8sResources(ctx, objs)
if err != nil {
return err
}
}
return nil
}
Metrics Exporter 是通过 FeatureGate 控制的可选组件。禁用时不仅停止部署,还会主动删除之前创建的资源。
3.6 syncOpenShiftSystemdService — OpenShift systemd 服务
func (r *SriovOperatorConfigReconciler) syncOpenShiftSystemdService(
ctx context.Context,
cr *sriovnetworkv1.SriovOperatorConfig,
) error {
if cr.Spec.ConfigurationMode != sriovnetworkv1.SystemdConfigurationMode {
// 非 systemd 模式:如果之前部署了 MachineConfig,需要删除
obj := &machinev1.MachineConfig{}
// 使用 UncachedAPIReader 减少内存占用
err := r.UncachedAPIReader.Get(ctx, types.NamespacedName{Name: consts.SystemdServiceOcpMachineConfigName}, obj)
if err != nil {
if apierrors.IsNotFound(err) {
return nil // 不存在,无需清理
}
return err
}
// 存在 MachineConfig 但已切换到 DaemonSet 模式,删除
logger.Info("Systemd service was deployed but the operator is now operating on daemonset mode, removing the machine config")
err = r.Delete(ctx, obj)
return err
}
// Systemd 模式:创建/更新 MachineConfig
data := render.MakeRenderData()
data.Data["LogLevel"] = cr.Spec.LogLevel
objs, err := render.RenderDir(consts.SystemdServiceOcpPath, &data)
if err != nil {
return err
}
return r.setLabelInsideObject(ctx, cr, objs)
}
UncachedAPIReader:使用非缓存的 API reader 读取 MachineConfig,避免大型 MachineConfig 对象占用 controller-runtime 缓存内存。
3.7 syncOperatorConfigFinalizers — Finalizer 管理
func (r SriovOperatorConfigReconciler) syncOperatorConfigFinalizers(
ctx context.Context,
defaultConfig *sriovnetworkv1.SriovOperatorConfig,
logger logr.Logger,
) error {
// 如果已有 Finalizer,无需添加
if sriovnetworkv1.StringInArray(sriovnetworkv1.OPERATORCONFIGFINALIZERNAME, defaultConfig.ObjectMeta.Finalizers) {
return nil
}
// 添加 Finalizer
newObj := defaultConfig.DeepCopyObject().(client.Object)
newObj.SetFinalizers(
append(newObj.GetFinalizers(), sriovnetworkv1.OPERATORCONFIGFINALIZERNAME),
)
// 使用 Merge Patch 更新(避免覆盖其他字段)
patch := client.MergeFrom(defaultConfig)
err := r.Patch(ctx, newObj, patch)
if err != nil {
return fmt.Errorf("can't patch SriovOperatorConfig to add finalizer [%s]: %w",
sriovnetworkv1.OPERATORCONFIGFINALIZERNAME, err)
}
// 刷新对象以获取最新版本
return r.Get(ctx, types.NamespacedName{
Namespace: defaultConfig.Namespace,
Name: defaultConfig.Name,
}, defaultConfig)
}
3.8 handleSriovOperatorConfigDeletion — 删除处理
func (r *SriovOperatorConfigReconciler) handleSriovOperatorConfigDeletion(
ctx context.Context,
defaultConfig *sriovnetworkv1.SriovOperatorConfig,
logger logr.Logger,
) (ctrl.Result, error) {
var err error
if sriovnetworkv1.StringInArray(sriovnetworkv1.OPERATORCONFIGFINALIZERNAME, defaultConfig.ObjectMeta.Finalizers) {
logger.Info("delete SriovOperatorConfig CR", "Namespace", defaultConfig.Namespace, "Name", defaultConfig.Name)
// 删除所有 Webhook 配置
err = r.deleteAllWebhooks(ctx)
if err != nil {
return reconcile.Result{}, err
}
// 移除 Finalizer,允许对象被最终删除
defaultConfig.ObjectMeta.Finalizers, _ = sriovnetworkv1.RemoveString(
sriovnetworkv1.OPERATORCONFIGFINALIZERNAME, defaultConfig.ObjectMeta.Finalizers)
if err := r.Update(ctx, defaultConfig); err != nil {
return reconcile.Result{}, err
}
}
return reconcile.Result{}, err
}
3.9 deleteAllWebhooks — 删除所有 Webhook
func (r SriovOperatorConfigReconciler) deleteAllWebhooks(ctx context.Context) error {
var err error
obj := &uns.Unstructured{}
// 删除 Operator MutatingWebhookConfiguration
obj.SetGroupVersionKind(schema.GroupVersionKind{
Group: "admissionregistration.k8s.io", Kind: "MutatingWebhookConfiguration", Version: "v1"})
obj.SetName(consts.OperatorWebHookName)
err = errors.Join(err, r.deleteWebhookObject(ctx, obj))
// 删除 Operator ValidatingWebhookConfiguration
obj = &uns.Unstructured{}
obj.SetGroupVersionKind(schema.GroupVersionKind{
Group: "admissionregistration.k8s.io", Kind: "ValidatingWebhookConfiguration", Version: "v1"})
obj.SetName(consts.OperatorWebHookName)
err = errors.Join(err, r.deleteWebhookObject(ctx, obj))
// 删除 Injector MutatingWebhookConfiguration
obj = &uns.Unstructured{}
obj.SetGroupVersionKind(schema.GroupVersionKind{
Group: "admissionregistration.k8s.io", Kind: "MutatingWebhookConfiguration", Version: "v1"})
obj.SetName(consts.InjectorWebHookName)
err = errors.Join(err, r.deleteWebhookObject(ctx, obj))
return err
}
errors.Join:Go 1.20+ 的错误拼接功能,将多个删除操作的错误合并为一个。即使某个删除失败,也会继续尝试删除其他 Webhook。
3.10 syncK8sResource — 通用资源同步
func (r *SriovOperatorConfigReconciler) syncK8sResource(
ctx context.Context,
cr *sriovnetworkv1.SriovOperatorConfig,
in *uns.Unstructured,
) error {
switch in.GetKind() {
case clusterRoleResourceName, // ClusterRole
clusterRoleBindingResourceName, // ClusterRoleBinding
mutatingWebhookConfigurationCRDName, // MutatingWebhookConfiguration
validatingWebhookConfigurationCRDName, // ValidatingWebhookConfiguration
machineConfigCRDName: // MachineConfig
// 集群级别资源不设置 OwnerReference
// 因为 OwnerReference 只能指向同命名空间或集群级别的所有者
default:
// 命名空间级别资源设置 OwnerReference
if err := controllerutil.SetControllerReference(cr, in, r.Scheme); err != nil {
return err
}
}
// 使用 apply.ApplyObject 进行 server-side apply
if err := apply.ApplyObject(ctx, r.Client, in); err != nil {
return fmt.Errorf("failed to apply object %v with err: %v", in, err)
}
return nil
}
OwnerReference 策略:
- 命名空间级别资源(ServiceAccount、Service、Deployment 等):设置 OwnerReference
- 集群级别资源(ClusterRole、ClusterRoleBinding、WebhookConfiguration、MachineConfig):不设置 OwnerReference(K8s 不允许命名空间级别的 Owner 拥有集群级别的资源)
四、组件同步全景图
五、Webhook 启停序列图
六、Finalizer 生命周期
七、Feature Gates 初始化流程
八、环境变量依赖总览
| 环境变量 | 用途 | 使用位置 |
|---|---|---|
SRIOV_NETWORK_CONFIG_DAEMON_IMAGE | Config Daemon 镜像 | syncConfigDaemonSet |
SRIOV_CNI_IMAGE | SR-IOV CNI 镜像 | syncConfigDaemonSet |
SRIOV_INFINIBAND_CNI_IMAGE | IB CNI 镜像 | syncConfigDaemonSet |
OVS_CNI_IMAGE | OVS CNI 镜像 | syncConfigDaemonSet |
RDMA_CNI_IMAGE | RDMA CNI 镜像 | syncConfigDaemonSet |
NETWORK_RESOURCES_INJECTOR_IMAGE | Injector 镜像 | syncWebhookObjs |
SRIOV_NETWORK_WEBHOOK_IMAGE | Webhook 镜像 | syncWebhookObjs |
SRIOV_DEVICE_PLUGIN_IMAGE | Device Plugin 镜像 | syncPluginDaemonObjs |
METRICS_EXPORTER_IMAGE | Metrics Exporter 镜像 | syncMetricsExporter |
METRICS_EXPORTER_KUBE_RBAC_PROXY_IMAGE | kube-rbac-proxy 镜像 | syncMetricsExporter |
RELEASEVERSION | 发布版本 | 多处 |
DEV_MODE | 开发模式 | syncWebhookObjs, syncConfigDaemonSet |
IMAGE_PULL_SECRETS | 镜像拉取密钥 | GetImagePullSecrets |
SRIOV_CNI_BIN_PATH | CNI 二进制路径 | syncConfigDaemonSet |
ADMISSION_CONTROLLERS_CERTIFICATES_* | Webhook 证书配置 | syncWebhookObjs |
METRICS_EXPORTER_PROMETHEUS_* | Prometheus 集成配置 | syncMetricsExporter |
九、关键设计模式总结
9.1 单例配置模式
- 只处理名为
default的 SriovOperatorConfig - 通过
defaultConfigPredicate()过滤 - 确保全局只有一个有效的配置对象
9.2 声明式资源同步
- 使用
apply.ApplyObject进行 Server-Side Apply - 对比期望状态与实际状态,只更新有变化的资源
DeepDerivative避免默认值导致的不必要更新
9.3 Finalizer 保护模式
- 添加 Finalizer 防止过早删除
- 删除时先清理 Webhook 等外部资源
- 清理完成后才移除 Finalizer
9.4 模板渲染 + 同步模式
- 所有组件通过
render.RenderDir渲染 manifests 模板 - 模板中包含镜像、命名空间、配置等变量
- 渲染后通过
syncK8sResource或syncDaemonSet同步到集群
9.5 平台感知模式
- 通过
PlatformHelper检测运行平台 - OpenShift:支持 MachineConfig、systemd 模式
- Hypershift:不支持 systemd 模式
- 标准 Kubernetes:仅 DaemonSet 模式
9.6 动态启停模式
- Webhook 通过
EnableInjector/EnableOperatorWebhook控制 - Metrics Exporter 通过 FeatureGate 控制
- 禁用时主动删除资源,启用时重新创建

1万+

被折叠的 条评论
为什么被折叠?



