后端声明式升级指导
后端声明式升级介绍
应用场景
声明式升级是openFuyao提供的一种基于声明式API的集群版本升级方式。用户仅需声明期望的目标版本,系统将自动完成升级路径校验、升级资源准备、组件有序升级和状态追踪等全流程操作。通过后端执行升级,用户可以查看升级过程中的阶段信息,了解升级执行步骤。
适用于以下场景:
- 将集群的openFuyao版本从v26.06-rc.2及后续版本升级到更高版本。
- 在线环境和离线环境下的集群版本升级。
能力范围
- 声明式触发升级:修改ClusterVersion CR(Custom Resource,自定义资源)的desiredVersion字段即可触发升级,系统自动下发升级指令。
- 升级路径自动校验:基于UpgradePath规则自动校验当前版本到目标版本的升级路径是否合法。
- 多跳升级自动执行:当不存在直接升级路径时,系统自动按中间版本逐跳执行。
- DAG(Directed Acyclic Graph,有向无环图)驱动的并行升级:升级组件按依赖关系构建DAG拓扑图,支持同批次组件并行升级。
- 在线/离线场景均支持。
- 管理集群和业务集群均可升级。业务集群的升级要在管理其生命周期的集群(管理集群或引导节点)上进行操作。
亮点特征
- 声明式触发:仅需声明目标版本(修改ClusterVersion CR的desiredVersion字段),无需关心升级执行细节。
- DAG并行升级:相较于旧版串行PhaseFlow升级,声明式升级支持组件按依赖拓扑并行执行,缩短整体升级耗时。
- 多跳自动执行:跨版本升级时,系统自动计算中间跳版本并逐跳执行,用户无需手动干预。
基本概念
| 概念 | 说明 |
|---|---|
| ClusterVersion | 声明式升级的触发CR,通过设置spec.desiredVersion字段声明期望的目标版本 |
| UpgradePath | 升级路径规则CR,定义了版本之间的合法升级路径,包括from、to、blocked等信息 |
| ReleaseImage | 版本发布镜像CR,包含升级所需的组件列表、依赖关系和执行方式(inline或manifest) |
| ComponentVersion | 组件版本定义CR,定义单个升级组件的类型、版本、依赖、升级策略和前置资源 |
| 升级DAG | 基于ReleaseImage和ComponentVersion的依赖关系构建的有向无环图,决定升级组件的执行顺序 |
| 多跳升级 | 当从当前版本到目标版本不存在直接升级路径而存在多跳路径时,系统自动按中间版本逐跳执行升级 |
声明式升级的触发和执行流程如下:
流程步骤说明:
- 修改desiredVersion:修改ClusterVersion CR的spec.desiredVersion字段为目标版本。
- 检测版本变更:ClusterVersionReconciler检测到desiredVersion与currentVersion不一致,触发升级流程。
- 查询升级路径:ClusterVersionReconciler查询UpgradePath CR,校验从当前版本到目标版本的升级路径是否合法。
- 确保资源存在:确保ReleaseImage CR存在且状态为Valid,系统自动从OCI镜像仓库拉取并解析。
- 写入升级注解:在BKECluster上写入upgrade-ready注解,触发BKEClusterReconciler进入升级流程。
- 检测升级注解:BKEClusterReconciler检测BKECluster上的upgrade-ready注解,进入声明式升级流程。
- 解析升级组件:解析ReleaseImage获取升级组件列表和依赖关系。
- 构建DAG拓扑图:基于ReleaseImage的升级组件列表和ComponentVersion的依赖关系,构建DAG拓扑图。
- 并行执行升级:按DAG拓扑批次并行执行各组件升级,inline组件(etcd、kubernetes等)通过PhaseRunner执行,manifest组件(provider、coredns等)通过ClusterApplier执行。
- 判断升级是否成功:检查所有组件是否升级成功。
- 更新状态:升级成功后更新BKECluster和ClusterVersion状态,每个组件完成后更新DeclarativeUpgradeStatus。
- 记录失败组件:升级失败时记录失败组件信息。
- 判断是否达到目标版本:检查当前版本是否等于目标版本,若不等于则继续执行下一跳升级。
- 升级完成:当前版本等于目标版本,升级全部完成,清除升级注解。
使用限制
| 限制项 | 说明 |
|---|---|
| 不支持降级 | 只提供了版本升级功能,未提供版本降级功能 |
| 最低版本要求 | 目前支持可升级的最低版本是v26.06-rc.2 |
| 升级影响 | 非高可用集群升级K8s相关组件时,会出现短暂的apiserver服务不可用 |
| etcd备份建议 | 升级前建议备份etcd数据,升级失败时需手动回滚 |
| 离线上传限制 | 离线场景补丁上传不支持在在线模式下操作 |
| 集群健康要求 | 升级前集群状态必须为Healthy,否则升级可能失败 |
注意:
v26.03版本到v26.06版本的升级参考升级指导。下面的指导为v26.06-rc.2及后续版本的升级指导。
在线场景升级操作
前提条件
- 管理集群正常运行。
- 管理集群可以访问远程版本仓库。
- 需升级的集群的状态为Healthy(健康)。
步骤一:检查集群状态
# 查看业务集群状态
kubectl get bkecluster <集群名称> -n <命名空间>
# 期望输出: Healthy
# 若输出不是Healthy,需先排查和修复集群问题步骤二:查询可升级路径
# 查看UpgradePath CR中的升级路径规则
kubectl get upgradepath openfuyao-upgrade-paths -o yaml步骤三:触发升级
通过kubectl操作ClusterVersion CR
如果期望升级到v26.06版本,可以执行以下操作触发升级。
# patch更新desiredVersion
kubectl patch clusterversion <集群名称> -n <命名空间> --type merge -p '{"spec":{"desiredVersion":"v26.06"}}'
# 或者 edit clusterversion 资源,将desiredVersion修改为v26.06
kubectl edit clusterversion <集群名称> -n <命名空间>说明:
修改ClusterVersion CR的desiredVersion字段是声明式升级的唯一触发方式。系统检测到desiredVersion与currentVersion不一致后,自动进入升级流程。
步骤四:监控升级进度
通过kubectl查看升级过程中的各项状态:
# 查看ClusterVersion状态
kubectl get clusterversion <集群名称> -n <命名空间> -wClusterVersion的phase字段含义:
| Phase | 说明 |
|---|---|
| Pending | 升级请求已提交,等待处理 |
| PreChecking | 升级前置校验中 |
| Upgrading | 升级执行中 |
| Upgraded | 单跳升级完成(多跳场景下仍有后续跳) |
| Ready | 升级全部完成,currentVersion等于desiredVersion |
| Blocked | 升级路径被阻断 |
| PreCheckFailed | 前置校验失败 |
| Failed | 升级失败 |
# 查看集群整体健康状态
kubectl get bkecluster <集群名称> -n <命名空间> -w声明式升级的阶段顺序(按DAG拓扑执行):
| 升级批次 | 阶段名称 | CR Phase名 | 说明 |
|---|---|---|---|
| 批次1 | provider自升级 | EnsureProviderSelfUpgrade | cluster-api-provider-bke自身镜像滚动升级 |
| 批次2 | Agent升级 | EnsureAgentUpgrade | 升级各节点上的bke-agent |
| 批次3 | Containerd升级 | EnsureContainerdUpgrade | 升级各节点上的containerd |
| 批次4 | etcd升级 | EnsureEtcdUpgrade | 滚动升级etcd集群 |
| 批次5 | Master升级 | EnsureMasterUpgrade | 滚动升级Master节点kubernetes组件 |
| 批次5 | Worker升级 | EnsureWorkerUpgrade | 滚动升级Worker节点kubernetes组件 |
| 批次6 | kube-proxy升级 | manifest方式 | 通过ClusterApplier应用YAML清单 |
| 批次6 | coredns升级 | manifest方式 | 通过ClusterApplier应用YAML清单 |
| 批次6 | calico升级 | manifest方式 | 通过ClusterApplier应用YAML清单 |
说明:
1.同批次内的组件并行执行,不同批次之间按依赖顺序串行执行。批次1~批次6由DAG拓扑排序自动决定,依赖关系来源于ReleaseImage中各ComponentVersion的spec.dependencies字段。
2.批次5中Master升级和Worker升级并行执行;批次6中kube-proxy、coredns和calico并行执行。
3.多跳升级场景下,每跳执行上述全部阶段后自动进入下一跳。
4.provider自升级完成后会触发新Pod接管后续升级流程,旧Pod自动退出。
步骤五:确认升级完成
# 确认ClusterVersion的currentVersion等于desiredVersion
kubectl get clusterversion <集群名称> -n <命名空间> -o jsonpath='{.status.currentVersion}'
# 确认ClusterVersion的phase为Ready
kubectl get clusterversion <集群名称> -n <命名空间> -o jsonpath='{.status.phase}'
# 确认集群状态恢复为Healthy
kubectl get bkecluster <集群名称> -n <命名空间> -o jsonpath='{.status.clusterHealthState}'离线场景升级操作
前提条件
- 管理集群正常运行且是离线环境。
- 集群处于离线模式。
- 需升级的集群的状态为Healthy(健康)。
- 已准备好版本配置文件(用于制备全量离线包),制备离线包需要在在线环境,之后将制作好的离线包上传到引导节点。
制备离线包步骤一:准备版本配置文件
下载openFuyao版本的索引文件,获取版本和文件名称的对应关系。
bashwget https://openfuyao.obs.cn-north-4.myhuaweicloud.com/openFuyao/version-config/index.yaml索引文件样例内容:
yaml- openFuyaoVersion: v26.06 filePath: ./VersionConfig-v26.06.yaml - openFuyaoVersion: v26.06-rc.2 filePath: ./VersionConfig-v26.06-rc.2.yaml根据索引文件下载目标版本的配置文件。
bashwget https://openfuyao.obs.cn-north-4.myhuaweicloud.com/openFuyao/version-config/VersionConfig-v26.06-rc.2.yaml
制备离线包步骤二:上传版本配置文件
通过kubectl直接操作ConfigMap
# 创建版本配置ConfigMap(在openfuyao-patch命名空间下)
kubectl create configmap cm.v26.06-rc.2 -n openfuyao-patch \
--from-literal=v26.06-rc.2="$(cat VersionConfig-v26.06-rc.2.yaml)"
# 更新bke-config ConfigMap,添加patch索引
kubectl patch configmap bke-config -n cluster-system --type merge \
-p '{"data":{"patch.v26.06-rc.2":"cm.v26.06-rc.2"}}'制备离线包步骤三:制备全量离线包
根据制备离线包步骤一:准备版本配置文件中下载的版本配置文件,制备包含升级所需全部镜像、二进制文件和版本补丁的全量离线包。
安装docker(使用20.10.13或18.09.0版本)并配置docker,编辑/etc/docker/daemon.json文件,在文件中添加以下配置项:
说明:
若daemon.json文件不存在,需手动创建。若文件中已有其他配置项,将"insecure-registries"添加到已有配置中即可,无需替换整个文件内容。json{ "insecure-registries": ["0.0.0.0/0"] }重启docker:
bashsystemctl restart docker根据版本配置文件制备全量离线包。此处以v26.06-rc.2版本为例,请根据实际目标版本替换文件名和离线包名称:
bashbke build -f VersionConfig-v26.06-rc.2.yaml -t offline-v26.06-rc.2.tar.gz说明:
请将命令中的版本号替换为您实际要升级的目标版本号。
说明:
此处以v26.06-rc.2版本为例,请将命令中的版本号替换为您实际要升级的目标版本号。
全量离线包包含以下内容:
| 内容 | 说明 |
|---|---|
| 容器镜像 | 版本配置文件中repos定义的所有容器镜像 |
| registry镜像 | 用于引导节点本地镜像源的registry:2镜像 |
| 二进制文件 | 版本配置文件中files定义的containerd、kubelet、kubectl等二进制文件 |
| RPM/deb包 | 版本配置文件中rpms/debs定义的操作系统依赖包 |
| Helm charts | 版本配置文件中charts定义的Helm chart包 |
| 版本补丁 | 版本配置文件中patches定义的VersionConfig补丁文件 |
| bke安装工具 | bkeadm安装命令工具 |
说明:
1.版本配置文件定义了全量离线包所需的所有镜像、二进制文件和依赖包,是制备离线包的输入配置。
2.全量离线包确保升级所需的所有资源均可在离线环境下使用,避免因缺少依赖导致升级失败。
离线升级步骤一:上传离线包到引导节点
将全量离线包文件放置在引导节点的/etc/openFuyao目录下。
将离线包同步到引导节点镜像源服务:
bash# 登录引导节点 # 解压全量离线包 tar -xzvf /etc/openFuyao/offline-v26.06-rc.2.tar.gz # 同步镜像到本地镜像源 bke registry patch --source ./offline-v26.06-rc.2 --target <引导节点IP>:40443 # 拷贝二进制文件到指定目录 cp containerd-*.tar.gz /bke/mount/source_registry/files/说明:
此处以v26.06-rc.2版本为例,请将命令中的版本号替换为您实际要升级的目标版本号。
离线升级步骤二:检查集群状态
与在线场景一致:
kubectl get bkecluster <集群名称> -n <命名空间>离线升级步骤三:触发升级
与在线场景一致:
如果期望升级到v26.06版本,可以执行以下操作触发升级。
# patch更新desiredVersion
kubectl patch clusterversion <集群名称> -n <命名空间> --type merge -p '{"spec":{"desiredVersion":"v26.06"}}'
# 或者 edit clusterversion 资源,将desiredVersion修改为v26.06
kubectl edit clusterversion <集群名称> -n <命名空间>离线升级步骤四:监控升级进度
与在线场景一致,参见在线场景-监控升级进度章节。
离线升级步骤五:确认升级完成
与在线场景一致,参见在线场景-确认升级完成章节。
升级失败处理
查看失败详情
# 查看ClusterVersion状态
kubectl get clusterversion <集群名称> -n <命名空间> -o yaml
# 查看DeclarativeUpgradeStatus中的失败记录
kubectl get bkecluster <集群名称> -n <命名空间> -o jsonpath='{.status.declarativeUpgrade.lastFailure}'
# 查看集群状态
kubectl get bkecluster <集群名称> -n <命名空间> -o jsonpath='{.status.clusterHealthState}'常见失败原因
| 失败原因 | 说明 | 排查命令 |
|---|---|---|
| 集群不健康 | 升级前集群状态非Healthy | kubectl get bkecluster <名称> -n <名称> -o jsonpath='{.status.clusterHealthState}' |
| 升级路径被阻断 | UpgradePath规则中路径被标记为blocked | kubectl get upgradepath -o yaml |
| 镜像拉取失败 | 离线场景下镜像包未正确同步 | 登录引导节点检查镜像源服务 |
| 资源不足 | 节点CPU/内存/磁盘资源不足 | kubectl top nodes |
| 网络问题 | 节点间网络通信异常 | kubectl get nodes 查看节点Ready状态 |
FAQ
声明式升级和旧版PhaseFlow升级有什么区别?
对比项 旧版PhaseFlow 声明式升级 触发方式 修改BKECluster.spec.openFuyaoVersion 修改ClusterVersion.spec.desiredVersion 执行方式 串行执行所有升级阶段 DAG拓扑驱动并行执行 组件顺序 固定顺序 按依赖关系动态决定 多跳升级 不支持 支持自动逐跳执行 升级版本列表为空是什么原因?
bash# 检查UpgradePath CR是否存在 kubectl get upgradepath # 检查路径规则 kubectl get upgradepath openfuyao-upgrade-paths -o jsonpath='{.spec.paths}'可能原因:1)当前版本已是最新版本;2)UpgradePath规则中当前版本不存在可达的升级路径;3)在线模式下远程版本仓库不可达。
多跳升级是什么?
当从当前版本到目标版本不存在直接升级路径时(如v26.06-rc.2到v26.06),系统自动计算中间跳版本路径(如v26.06-rc.2 -> v26.06-rc.3 -> v26.06),并逐跳执行升级。每跳完成后自动进入下一跳,直到到达最终目标版本。
升级过程中provider自升级后为什么会有短暂中断?
provider自升级采用Kubernetes Deployment滚动更新机制:旧Pod patch镜像后,K8s创建新Pod,待新Pod Ready后终止旧Pod。新Pod启动后会自动接管后续升级流程。此过程通常在1-2分钟内完成。