KubeEdge 边缘节点远程升级:NodeUpgradeJob CRD 与云边协同升级方案详解
2026/9/17 5:05:25 网站建设 项目流程

KubeEdge 边缘节点远程升级:NodeUpgradeJob CRD 与云边协同升级方案详解

【免费下载链接】kubeedgeKubernetes Native Edge Computing Framework (project under CNCF)项目地址: https://gitcode.com/GitHub_Trending/ku/kubeedge

导读

在边缘计算场景中,海量边缘节点分散部署在网络边缘,若逐一登录节点手工升级 EdgeCore,运维成本极高。KubeEdge 通过定义集群级自定义资源NodeUpgradeJoboperations.kubeedge.io/v1alpha1),配合云端控制器与边缘侧 keadm 升级工具,实现了从云端一键批量升级边缘节点、并自动同步升级结果状态的完整闭环。本文以官方提案 edge-node-upgrade.md 为骨架,结合仓库内 CRD 类型定义、控制器实现、Admission Webhook 校验、CloudHub HTTP 接口与边缘侧 action 源码,深入讲解其设计原理、CRD 字段语义、升级工作流与校验规则,帮助读者掌握如何在真实集群中通过kubectl创建NodeUpgradeJob完成边缘节点升级与结果观测。

背景与动机:为什么需要边缘节点远程升级

边缘节点通常位于用户侧网络,无法直接暴露给运维人员远程登录。升级管理(Edge Node Upgrade Management)是边缘计算中"从云端远程升级边缘节点"这一关键能力所必需的。KubeEdge 的该提案主要解决两个核心问题:

  1. 如何从云端发起对边缘节点的升级——提供可被云端 API Server 暴露的 CRD 接口,让用户以声明式方式描述升级诉求;
  2. 如何在云边之间同步升级结果状态——边缘节点完成升级(或升级失败)后,把结果回传给云端并写入 CR 的status字段,供用户随时查询。

设计目标(Goals)

  • 提供从云端升级边缘节点的 API;
  • 在云和边缘节点之间同步边缘节点升级结果。

使用场景(Use Cases)

  • 描述升级属性:用户可以描述升级属性以及与之交互/控制升级的访问机制(目标版本、超时时间、选择节点的方式、使用的升级工具与镜像等);
  • 从云端对升级执行 CRUD 操作:通过 Kubernetes API Server 暴露的 CRD API,用户可以在云端创建、更新、删除升级元数据;
  • 上报升级属性值:边缘节点可以向云端上报升级结果状态。

NodeUpgradeJob 控制器设计:Upstream / Downstream 双通道

NodeUpgradeJob控制器启动两个独立的 goroutine,分别命名为upstream控制器downstream控制器(它们并非独立控制器,仅是为清晰描述而命名):

  • Downstream 控制器:负责把NodeUpgradeJob的更新从云端同步到边缘节点(下发升级指令);
  • Upstream 控制器:职责相反,负责把边缘节点的升级结果回传到云端并更新 CR 状态。

从当前仓库源码看,该控制器经历了从独立控制器(旧版)到 controller-runtime 标准 Reconcile 模式的演进:

  • 控制器入口定义在 cloud/pkg/controllermanager/nodetask/nodeupgradejob.go,通过controllerruntime.NewControllerManagedBy(mgr).For(&operationsv1alpha2.NodeUpgradeJob{}).Complete(c)注册对NodeUpgradeJob的监听;
  • 通用协调逻辑封装在 cloud/pkg/controllermanager/nodetask/reconcile_runner.go 的RunReconcile中,统一处理:添加 Finalizer(kubeedge.io/nodeupgradejob-controller)、删除清理、初始化节点状态、计算任务阶段、超时检测与状态更新(失败重试 3 次、间隔 200ms);
  • 具体业务实现见 cloud/pkg/controllermanager/nodetask/nodeupgradejob_handler.go,包括InitNodesStatus(根据nodeNames/labelSelector校验并初始化各节点任务状态)、CheckTimeout(基于最后 action 更新时间或 CR 创建时间判断是否超时,超时则置为unknown阶段并记录The node task has timed out)以及CalculateStatus(按failureTolerate容错比例汇总任务阶段)。

同步流程:从 kubectl 创建到升级结果回写

下图描述了NodeUpgradeJob属性值在云/边两侧更新时的事件流转全貌(原图见 docs/images/edge-node-upgrade/upgrade.png):

用户使用kubectl创建NodeUpgradeJobCR 以触发升级任务;NodeUpgradeJob控制器通过 List-Watch 监听该资源,向边缘节点发送升级消息;边缘节点的 EdgeCore 使用keadm执行升级操作;keadm将升级结果上报云端;云端把升级结果写入NodeUpgradeJobstatus字段。用户通过查看status字段即可判断升级是否成功。

Downstream 控制器的职责

  1. 监听 CRD 资源:使用 List-Watch 机制监控NodeUpgradeJobCRD 资源,收到 K8s APIServer 事件后存入本地缓存(旧版使用 map 缓存,当前版本基于 informer/controller-runtime cache,见 cloud/pkg/taskmanager/downstream/node_upgrade.go 中GetKubeEdgeInformerFactory().Operations().V1alpha2().NodeUpgradeJobs().Informer()的注册方式)。
  2. 幂等性判断:检查升级任务是否已完成(全部或部分节点升级完成)。若已完成则不再向边缘节点重复发送升级消息;仅当升级未完成时才下发。该操作是为了防止 cloudcore 重启等场景下重复向边缘节点发送升级消息。
  3. 节点过滤:使用 K8s informer 根据 CR 中指定的NodeNamesLabelSelector获取节点列表,并过滤掉不满足升级要求的节点:
    • 边缘节点已经处于期望的目标升级版本;
    • 非边缘节点(缺少标签"node-role.kubernetes.io/edge": "");
    • 边缘节点正处于 Upgrading 或 NotReady 状态;
    • 去除重复节点。
  4. 下发升级消息:对每个合规的边缘节点发送升级 beehive 消息;调用 K8s API 将边缘节点标记为不可调度(unschedulable),避免在升级中的边缘节点上继续部署应用;同时启动一个 Goroutine 处理超时——若未收到边缘节点升级响应,则将NodeUpgradeJob状态更新为超时状态,以应对无响应场景。

CloudHub 与 EdgeHub 的云边通道

  • CloudHub将升级请求发送给每个边缘节点的 EdgeHub。
  • EdgeHub侧的处理逻辑:
    1. 增加一个升级子模块处理升级消息,该子模块会对升级消息做一系列校验:检查 UpgradeID 是否为空、edgecore 是否已处于目标版本等;
    2. 为提高适配性,提供升级 Provider 接口,默认使用KeadmUpgrade执行升级操作;用户可通过设置UpgradeTool字段选择其他安装器完成升级任务(从当前仓库看,该字段已在 v1alpha1/v1alpha2 类型中移除,默认固定使用 keadm,详见 v1alpha1/type.go);
    3. KeadmUpgrade会下载指定版本的 keadm:EdgeCore 拉取kubeedge/installation-package镜像,并把 keadm 二进制从容器复制到主机路径;随后启动一个守护进程运行keadm upgrade相关命令完成升级操作,而不是直接运行keadm命令——因为 keadm 在升级过程中会 kill 掉 edgecore 进程,必须隔离执行。

keadm 升级三阶段:预处理、执行与回滚

  • 预处理(preprocess):keadm 在开始升级边缘节点前会做预处理工作。使用/etc/kubeedge/idempotency_record文件保证同一时间只能执行一次升级;备份edgecore.dbedgecore.yamledgecore到备份路径/etc/kubeedge/backup/{From_Version};拉取kubeedge/installation-package镜像并把新版本 edgecore 二进制从容器复制到主机升级路径/etc/kubeedge/upgrade/{To_Version}
  • 执行(process):停止 edgecore,把新版本 edgecore 复制到/usr/local/bin目录并启动新 edgecore。
  • 回滚(rollback):若升级失败,keadm 执行回滚操作以启动原始 edgecore 进程:停止 edgecore、回滚文件、把备份目录/etc/kubeedge/backup/{From_Version}中的文件复制回原路径,然后启动原始 edgecore。

无论升级成功还是失败,keadm 都会把**升级结果及失败原因(若失败)**上报给 CloudHub 的 HTTP 服务。

Upstream 控制器与结果落盘

  • CloudHub:其 HTTP 服务新增/nodeupgrade接口,将升级响应消息转发给NodeUpgradeJob控制器 Upstream。该接口实现见 cloud/pkg/cloudhub/servers/httpserver/nodetask/upgrade.go:UpgradeEdge解析请求体(限制最大 1MB),根据上报的Statusupgrade_success/upgrade_failed_rollback_success/upgrade_failed_rollback_failed)构造对应Event/Action,通过 beehive 消息发送给 TaskManager 模块处理。
  • Upstream 控制器:将节点标记为**可调度(schedulable)**并 patch 升级状态;若升级成功,调用 K8s API 在 Node 的 annotation 中记录升级历史,例如"nodeupgradejob.operations.kubeedge.io/history": "v1.10.0->v1.11.0",方便用户查看节点升级历史。

CRD 设计详解

API 分组与版本

NodeUpgradeJobCRD 为**集群级(cluster-scoped)**资源,分组、种类与 API 版本信息如下:

FieldDescription
Groupoperations.kubeedge.io
APIVersionv1alpha1
KindNodeUpgradeJob

当前仓库同时保留了v1alpha1v1alpha2两个版本:v1alpha2标记为存储版本(+kubebuilder:storageversion),并引入PhaseNodeStatusActionFlowConcurrencyCheckItemsFailureTolerateRequireConfirmationImageDigestGetter等增强字段,v1alpha1State/Event/Action等字段被标记为 Deprecated(计划在 v1.23 移除)。完整的 CRD YAML 见 manifests/charts/cloudcore/crds/operations_v1alpha2_nodeupgradejob.yaml。

NodeUpgradeJob就像"可复用的模板":使用它可以把边缘节点升级到指定版本,并方便地从云端进行操作。

NodeUpgradeJob 类型定义

提案给出了完整的 Go 类型定义(在仓库中实际落地于 staging/src/github.com/kubeedge/api/apis/operations/v1alpha1/type.go 与 v1alpha2/types_nodeupgrade.go):

// NodeUpgradeJob is used to upgrade edge node from cloud side. // +k8s:openapi-gen=true // +kubebuilder:subresource:status // +kubebuilder:resource:scope=Cluster type NodeUpgradeJob struct { metav1.TypeMeta `json:",inline"` metav1.ObjectMeta `json:"metadata,omitempty"` // Specification of the desired behavior of NodeUpgradeJob. // +optional Spec NodeUpgradeJobSpec `json:"spec,omitempty"` // Most recently observed status of the NodeUpgradeJob. // +optional Status NodeUpgradeJobStatus `json:"status,omitempty"` } // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object // NodeUpgradeJobList is a list of NodeUpgradeJob. type NodeUpgradeJobList struct { metav1.TypeMeta `json:",inline"` metav1.ListMeta `json:"metadata,omitempty"` Items []NodeUpgradeJob `json:"items"` }
NodeUpgradeJobSpec:规格字段语义
// NodeUpgradeJobSpec is the specification of the desired behavior of the NodeUpgradeJob. type NodeUpgradeJobSpec struct { // +Required: Version is the EdgeCore version to upgrade. Version string `json:"version,omitempty"` // UpgradeTool is a request to decide use which upgrade tool. If it is empty, // the upgrade job simply use default upgrade tool keadm to do upgrade operation. // +optional UpgradeTool string `json:"upgradeTool,omitempty"` // TimeoutSeconds limits the duration of the node upgrade job. // Default to 300. // If set to 0, we'll use the default value 300. // +optional TimeoutSeconds *uint32 `json:"timeoutSeconds,omitempty"` // NodeNames is a request to select some specific nodes. If it is non-empty, // the upgrade job simply select these edge nodes to do upgrade operation. // Please note that sets of NodeNames and LabelSelector are ORed. // Users must set one and can only set one. // +optional NodeNames []string `json:"nodeNames,omitempty"` // LabelSelector is a filter to select member clusters by labels. // It must match a node's labels for the NodeUpgradeJob to be operated on that node. // Please note that sets of NodeNames and LabelSelector are ORed. // Users must set one and can only set one. // +optional LabelSelector *metav1.LabelSelector `json:"labelSelector,omitempty"` // Image specifies a container image name, the image contains: keadm and edgecore. // keadm is used as upgradetool, to install the new version of edgecore. // The image name consists of registry hostname and repository name, but cannot includes the tag, // Version above will be used as the tag. // If the registry hostname is empty, docker.io will be used as default. // The default image name is: kubeedge/installation-package. // +optional Image string `json:"image,omitempty"` }

各字段核心语义:

字段类型必填说明
versionstring要升级到的 EdgeCore 版本,如v1.10.0
upgradeToolstring使用的升级工具;为空时默认使用keadm
timeoutSeconds*uint32升级任务时长上限,默认 300 秒;设为 0 时也按 300 秒处理
nodeNames[]string二者选一指定具体节点名执行升级
labelSelector*metav1.LabelSelector二者选一按标签过滤节点执行升级;与nodeNames为 OR 关系,且必须且只能设置其中一个
imagestring包含 keadm 与 edgecore 的容器镜像名;镜像名由 registry 主机名和仓库名组成,不能包含 tag(version会被用作 tag);registry 主机名为空时默认docker.io,默认镜像名为kubeedge/installation-package

此外,v1alpha2版本在 types_nodeupgrade.go 中扩展了以下字段:

  • concurrency(int32,默认 1):每个 CloudCore 实例可同时升级的最大边缘节点数;
  • checkItems([]string,默认 nil):任务执行前需要检查的项目;
  • failureTolerate(string,默认 0.1):任务容忍的失败比例;
  • requireConfirmation(bool,默认 false):是否需要在升级前进行确认;
  • imageDigestGatter:镜像摘要校验配置,可显式指定arm64/amd64平台的sha256摘要,或通过registryAPIhost+token)自动从远端 registry 获取多平台摘要进行校验。
升级结果与状态枚举
// UpgradeResult describe the result status of upgrade operation on edge nodes. // +kubebuilder:validation:Enum=upgrade_success;upgrade_failed_rollback_success;upgrade_failed_rollback_failed type UpgradeResult string // upgrade operation status const ( UpgradeSuccess UpgradeResult = "upgrade_success" UpgradeFailedRollbackSuccess UpgradeResult = "upgrade_failed_rollback_success" UpgradeFailedRollbackFailed UpgradeResult = "upgrade_failed_rollback_failed" ) // UpgradeState describe the UpgradeState of upgrade operation on edge nodes. // +kubebuilder:validation:Enum=upgrading;completed type UpgradeState string // Valid values of UpgradeState const ( InitialValue UpgradeState = "" Upgrading UpgradeState = "upgrading" Completed UpgradeState = "completed" )
  • UpgradeResult三种取值:upgrade_success(升级成功)、upgrade_failed_rollback_success(升级失败但回滚成功)、upgrade_failed_rollback_failed(升级失败且回滚也失败);
  • UpgradeState取值:空字符串(初始值)、upgrading(升级中)、completed(已完成)。
NodeUpgradeJobStatus 与节点级 UpgradeStatus
// NodeUpgradeJobStatus stores the status of NodeUpgradeJob. // contains multiple edge nodes upgrade status. // +kubebuilder:validation:Type=object type NodeUpgradeJobStatus struct { // State represents for the state phase of the NodeUpgradeJob. // There are three possible state values: "", upgrading and completed. State UpgradeState `json:"state,omitempty"` // Status contains upgrade Status for each edge node. Status []UpgradeStatus `json:"status,omitempty"` } // UpgradeStatus stores the status of Upgrade for each edge node. // +kubebuilder:validation:Type=object type UpgradeStatus struct { // NodeName is the name of edge node. NodeName string `json:"nodeName,omitempty"` // State represents for the upgrade state phase of the edge node. // There are three possible state values: "", upgrading and completed. State UpgradeState `json:"state,omitempty"` // History is the last upgrade result of the edge node. History History `json:"history,omitempty"` } // History stores the information about upgrade history record. // +kubebuilder:validation:Type=object type History struct { // HistoryID is to uniquely identify an Upgrade Operation. HistoryID string `json:"historyID,omitempty"` // FromVersion is the version which the edge node is upgraded from. FromVersion string `json:"fromVersion,omitempty"` // ToVersion is the version which the edge node is upgraded to. ToVersion string `json:"toVersion,omitempty"` // Result represents the result of upgrade. Result UpgradeResult `json:"result,omitempty"` // Reason is the error reason of Upgrade failure. // If the upgrade is successful, this reason is an empty string. Reason string `json:"reason,omitempty"` // UpgradeTime is the time of this Upgrade. UpgradeTime string `json:"upgradeTime,omitempty"` }

NodeUpgradeJobStatus保存整个任务级状态;UpgradeStatus记录每个边缘节点的升级状态,其中History记录了HistoryID(升级操作唯一标识)、FromVersion/ToVersion(从哪个版本升到哪个版本)、Result(升级结果)、Reason(失败原因,成功时为空字符串)、UpgradeTime(升级时间)。注意:每个节点的 status 中只保留最后一次升级历史记录

NodeUpgradeJob 示例

以下示例展示了如何定义一个NodeUpgradeJob来升级边缘节点:

apiVersion: operations.kubeedge.io/v1alpha1 kind: NodeUpgradeJob metadata: name: upgrade-example labels: description: upgrade-label spec: version: "v1.10.0" timeoutSeconds: 60 labelSelector: matchLabels: "node-role.kubernetes.io/edge": "" node-role.kubernetes.io/agent: ""

示例中各属性的含义:

  • version:描述要升级到的目标版本;
  • nodeNames:请求选择某些特定节点;非空时只对这些边缘节点执行升级。注意NodeNamesLabelSelectorOR关系,必须且只能设置其中一个;
  • labelSelector:按标签过滤节点;节点标签必须匹配才能被该任务操作。与nodeNames同为二选一字段;
  • upgradeTool:选择升级工具;为空时默认使用keadm
  • timeoutSeconds:限制升级任务时长,默认 300;不设置或设为 0 时使用默认值 300;
  • image:指定包含 keadm 与 edgecore 的容器镜像名;若包含 tag 或 digest,会被version字段覆盖;registry 主机名为空时默认docker.io,默认镜像名为kubeedge/installation-package

校验规则(Validation)

提案建议使用两类校验机制保障 CR 的合法性:

  • OpenAPI v3 Schema 校验:基于 CRD 的 OpenAPI v3 Schema 拦截非法请求,例如字段类型错误(布尔字段传入字符串等)。完整 schema 见 operations_v1alpha2_nodeupgradejob.yaml。
  • 校验 Admission Webhook:用于实现 Schema 无法表达的自定义校验规则,例如"创建的 Upgrade 实例未指定任何节点"这类跨字段约束。

NodeUpgradeJob 校验规则清单

  1. 若任何Required字段(如version等)缺失,禁止创建NodeUpgradeJob
  2. nodeNameslabelSelector不能同时为空(必须至少指定一个有效节点),也不能同时设置(二者只能选其一);
  3. CR 一旦创建,不允许更新 spec 字段
  4. 升级失败后,用户需要自行通过 K8sNodeUpgradeJobCR 的 status 字段排查失败原因,并可能需要手动升级;
  5. NodeUpgradeJob的 status 中每节点只保留最后一次升级历史记录;
  6. 同时使用 webhook 做格式校验,例如检查version格式是否正确。

这些规则在仓库中有完整落地实现,见 cloud/pkg/admissioncontroller/admit_nodeupgradejob.go:

  • 校验 WebhookvalidateNodeUpgradeJob调用validation.ValidateVersion校验版本格式、validation.ValidateImageRepo校验镜像仓库名,并强制"NodeNamesLabelSelector必须二选一"的约束(两者都为空或都不为空都会被拒绝);admitNodeUpgradeJobUpdate操作时通过reflect.DeepEqual(oldUpgrade.Spec, newUpgrade.Spec)拒绝一切 spec 修改,与提案规则 3 完全对应;
  • 变更 WebhookmutatingNodeUpgradeJob在创建时自动为.spec.concurrency补默认值 1、为.spec.timeoutSeconds补默认值 300,让 CR 在不显式配置时也能按提案的默认语义运行。

对应的单元测试见 cloud/pkg/admissioncontroller/admit_nodeupgradejob_test.go。

实战要点总结

  1. 升级前置条件:目标节点必须是带node-role.kubernetes.io/edge标签的边缘节点且处于 Ready 状态;集群中需已部署 CloudCore 与相应的NodeUpgradeJobCRD(Helm 安装 CloudCore 时 CRD 位于 manifests/charts/cloudcore/crds 目录下)。
  2. 创建任务:编写 YAML 并通过kubectl apply创建NodeUpgradeJob,控制器会自动完成节点过滤、节点置为不可调度、下发升级消息的完整流程。
  3. 观察结果:通过kubectl get nodeupgradejob <name> -o yaml查看status字段(任务级State+ 节点级Status/History),确认每个节点是upgrade_success还是回滚成功/失败;成功升级后还可通过节点 annotationnodeupgradejob.operations.kubeedge.io/history快速查看升级历史。
  4. 失败处理:升级失败时结合History.ReasonReason字段与节点侧 keadm 日志定位原因,必要时手工升级或重新发起任务。

【免费下载链接】kubeedgeKubernetes Native Edge Computing Framework (project under CNCF)项目地址: https://gitcode.com/GitHub_Trending/ku/kubeedge

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询