ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

K3s Kubernetes 补丁版本发布全流程指南:从上游变基打标到 Channel 更新的完整工程实践

K3s Kubernetes 补丁版本发布全流程指南:从上游变基打标到 Channel 更新的完整工程实践 K3s Kubernetes 补丁版本发布全流程指南从上游变基打标到 Channel 更新的完整工程实践【免费下载链接】k3sLightweight Kubernetes项目地址: https://gitcode.com/GitHub_Trending/k3/k3sK3sLightweight Kubernetes在跟随上游 Kubernetes 发布补丁patch版本时需要一套完整的工程流程先把 k3s 在上游 Kubernetes 仓库中的定制改动 rebase 到新版本 tag 上为每个 staging 模块生成-k3s1后缀的标签并推送再更新 K3s 主仓库的go.mod依赖、验证构建、创建 PR随后依次完成 RC 发布、镜像检查、Rancher KDM 同步以及 Channel Server 的 stable 版本切换。本文以 docs/release/kubernetes-upgrade.md 为主体结合 K3s 仓库内的 go.mod、channel.yaml、scripts/version.sh 与 Makefile 等源码佐证完整还原这一流程。读完本文你将掌握 K3s 发布负责人Release Captain执行一次 Kubernetes 补丁版本升级所需的全部命令、版本变量推导逻辑与发布检查项。发布流程全景概览一次标准的 K3s Kubernetes patch 升级大致分为以下阶段本文将按此顺序逐步展开准备环境Git、GoGOPATH、GPG 签名与 Docker 配置变基与打标在kubernetes/kubernetes仓库中把 k3s 的定制提交 rebase 到新版本 tag通过tag.sh为每个 Kubernetes staging 模块生成v版本-k3s1标签并推送至 k3s-io 远端更新主仓库修改 K3s 仓库的go.mod指向新标签执行go mod tidy必要时升级 Go 版本验证与合入本地构建验证SKIP_VALIDATE1 make、提交 PR、等待 CI 与评审合入发布与同步依次创建 RC、检查 system-agent-installer-k3s 与 k3s-upgrade 镜像、更新 Rancher KDM、创建 GA 发布、最后更新 Channel Server。其中版本号规则贯穿始终上游 Kubernetes 补丁版本形如v1.36.3K3s 标签形如v1.36.3-k3s1发布版本形如v1.36.3k3s1分隔 k3s 自身的迭代号K3s 单独更新时从k3s1递增到k3s2。开始之前环境与版本前提发布流程主要依赖Git与Go两个工具链Git可通过系统自带的包管理器安装Go需要正确安装并配置gopath通常通过环境变量GOPATH指定例如export GOPATH${HOME}/go此外还有两项提交/构建环境的配置GPG 签名在本地 Git 配置中关闭 commit 的 GPG 签名tag 的 GPG 签名按需另行配置git config --local commit.gpgSign falseDocker 中的用户身份兼容发布流程会在 Docker 容器内执行git操作为预防用户身份UID不匹配引发的问题设置如下全局配置git config --global core.safelyUseIncompatibleGitCredentialHelper true克隆上游并配置远端发布工作需要同时操作上游 Kubernetes 仓库与k3s-io 的 Kubernetes fork。首先以upstream为 origin 克隆官方仓库再加入 k3s-io 远端# initial clone git clone --origin upstream \ https://github.com/kubernetes/kubernetes.git \ ${GOPATH}/src/github.com/kubernetes/kubernetes cd ${GOPATH}/src/github.com/kubernetes/kubernetes # add the k3s-io remote git remote add k3s-io https://github.com/k3s-io/kubernetes.git # fetch all remote branches and tags. If you receive a message saying that # previous tags will be clobbered, add --force to the command below. git fetch --all --tags若git fetch --all --tags提示先前已有 tags 会被 clobbered需在命令后追加--force可执行第二遍git fetch --all --tags以确认没有遗漏的 tag便于尽早发现拉取错误参见 docs/release/expanded/cut_release.md 中的完整命令清单。变基与生成标签设置版本变量建立本地变基分支前需要先导出全部版本相关变量。这些变量贯穿后续所有步骤务必与实际要升级的版本一一对应export GLOBAL_GIT_CONFIG_PATH$(git config --list --show-origin --show-scope --global | awk NR1{ split($2,path,:); print path[2] }) export SSH_MOUNT_PATH$(echo ${SSH_AUTH_SOCK} || echo ${HOME}/.ssh/id_rsa) # Set up your new/old versions of Kubernetes export OLD_K8Sold-k8s-version export NEW_K8Snew-k8s-version export OLD_K8S_CLIENTold-k8s-client-version export NEW_K8S_CLIENTnew-k8s-client-version export OLD_K3S_VER${OLD_K8S}-k3s1 export NEW_K3S_VER${NEW_K8S}-k3s1 export RELEASE_BRANCHk8s-release-branch export GOPATH$(go env GOPATH)各变量的含义与示例值如下表变量含义示例v1.28.1 → v1.28.2OLD_K8S/NEW_K8S旧/新 Kubernetes 版本v1.28.1/v1.28.2OLD_K8S_CLIENT/NEW_K8S_CLIENT旧/新client-go关联版本v0.28.1/v0.28.2OLD_K3S_VER/NEW_K3S_VERK3s 侧使用的模块标签版本v1.28.1-k3s1/v1.28.2-k3s1RELEASE_BRANCH目标 Kubernetes 发布分支release-1.28GOPATHGo 工作区路径~/go注意K8S_CLIENT通常形如v0.minor.patch与K8S的v1.minor.patch主版本号不同这是 Kubernetes 仓库中client-go版本号体系的惯例sed替换时按此区分。清理旧构建产物rm -rf _output执行变基将上一次发布的 k3s 定制提交剔除 merge commit即~1rebase 到新的上游 tag 之上。完成后会停留在 detached HEAD 上该提交将在下一步被打上标签git rebase --onto ${NEW_K8S} ${OLD_K8S} ${OLD_K3S_VER}~1该命令的语义是以${OLD_K8S}为边界、把${OLD_K3S_VER}~1这一分支上的 k3s 定制改动整体重放到${NEW_K8S}tag 之上。Kubernetes 每个版本对 Go 版本有严格要求因此需要读取仓库内的 Go 版本定义并用指定版本的 Go 构建。构造构建容器Kubernetes 对每个 release 使用的 Go 版本有严格要求发布流程采用 Alpine Docker 的方式指定构建所用 Go 版本export GOVERSION$(grep -Po ^\s*\K\S .go-version) export GOIMAGEgolang:${GOVERSION}-alpine export BUILD_CONTAINERFROM ${GOIMAGE}\n \ RUN apk add --no-cache \ bash \ git \ make \ tar \ gzip \ curl \ git \ coreutils \ rsync \ alpine-sdk echo -e ${BUILD_CONTAINER} | docker build -t ${GOIMAGE}-dev -即在golang:版本-alpine基础镜像上追加bash、git、make、tar、gzip、curl、coreutils、rsync、alpine-sdk等构建依赖构建出-dev后缀的开发镜像。运行 tag.sh 生成标签rebase 操作会把tag.sh脚本带入工作树。接下来在容器内以当前用户身份执行tag.sh为所有 Kubernetes 模块生成-k3s1标签docker run --rm -u $(id -u):$(id -g) \ -v ${GOPATH}/src:/go/src:rw \ -v ${GOPATH}/pkg:/go/pkg:rw \ -v ${GOPATH}/.cache:/go/.cache:rw \ -v ${GLOBAL_GIT_CONFIG_PATH}:/go/.gitconfig:rw \ -e GIT_TRACE1 \ -e HOME/go \ -e GOCACHE/go/.cache \ -w /go/src/github.com/kubernetes/kubernetes \ ${GOIMAGE}-dev chown -R $(id -u) .git | ./tag.sh ${NEW_K3S_VER} 21 | tee ~/tags-${NEW_K3S_VER}.log关键点说明-u $(id -u):$(id -g)以当前用户身份运行避免容器内 root 产生文件属主问题docs/release/expanded/cut_release.md 的示例中也特意注释了“note user id is 502, I am not root user”通过卷挂载把GOPATH的src、pkg、.cache以及全局.gitconfig传入容器保证容器内的 Go 与 Git 行为与宿主机一致输出同时通过tee落盘为~/tags-${NEW_K3S_VER}.log便于回溯。tag.sh运行结束后输出末尾会列出若干条git push命令将这些命令保存为可执行脚本push.shchmod x push.shtag.sh 输出示例以 1.28 patch release 为例git push ${REMOTE} staging/src/k8s.io/api/v1.28.2-k3s1 git push ${REMOTE} staging/src/k8s.io/apiextensions-apiserver/v1.28.2-k3s1 git push ${REMOTE} staging/src/k8s.io/apimachinery/v1.28.2-k3s1 git push ${REMOTE} staging/src/k8s.io/apiserver/v1.28.2-k3s1 git push ${REMOTE} staging/src/k8s.io/client-go/v1.28.2-k3s1 git push ${REMOTE} staging/src/k8s.io/cli-runtime/v1.28.2-k3s1 git push ${REMOTE} staging/src/k8s.io/cloud-provider/v1.28.2-k3s1 git push ${REMOTE} staging/src/k8s.io/cluster-bootstrap/v1.28.2-k3s1 git push ${REMOTE} staging/src/k8s.io/code-generator/v1.28.2-k3s1 git push ${REMOTE} staging/src/k8s.io/component-base/v1.28.2-k3s1 git push ${REMOTE} staging/src/k8s.io/component-helpers/v1.28.2-k3s1 git push ${REMOTE} staging/src/k8s.io/controller-manager/v1.28.2-k3s1 git push ${REMOTE} staging/src/k8s.io/cri-api/v1.28.2-k3s1 git push ${REMOTE} staging/src/k8s.io/csi-translation-lib/v1.28.2-k3s1 git push ${REMOTE} staging/src/k8s.io/dynamic-resource-allocation/v1.28.2-k3s1 git push ${REMOTE} staging/src/k8s.io/endpointslice/v1.28.2-k3s1 git push ${REMOTE} staging/src/k8s.io/kms/v1.28.2-k3s1 git push ${REMOTE} staging/src/k8s.io/kube-aggregator/v1.28.2-k3s1 git push ${REMOTE} staging/src/k8s.io/kube-controller-manager/v1.28.2-k3s1 git push ${REMOTE} staging/src/k8s.io/kubectl/v1.28.2-k3s1 git push ${REMOTE} staging/src/k8s.io/kubelet/v1.28.2-k3s1 git push ${REMOTE} staging/src/k8s.io/kube-proxy/v1.28.2-k3s1 git push ${REMOTE} staging/src/k8s.io/kube-scheduler/v1.28.2-k3s1 git push ${REMOTE} staging/src/k8s.io/legacy-cloud-providers/v1.28.2-k3s1 git push ${REMOTE} staging/src/k8s.io/metrics/v1.28.2-k3s1 git push ${REMOTE} staging/src/k8s.io/mount-utils/v1.28.2-k3s1 git push ${REMOTE} staging/src/k8s.io/pod-security-admission/v1.28.2-k3s1 git push ${REMOTE} staging/src/k8s.io/sample-apiserver/v1.28.2-k3s1 git push ${REMOTE} staging/src/k8s.io/sample-cli-plugin/v1.28.2-k3s1 git push ${REMOTE} staging/src/k8s.io/sample-controller/v1.28.2-k3s1 git push ${REMOTE} v1.28.2-k3s1这些标签覆盖了 Kubernetes 的绝大多数 staging 模块api、apimachinery、client-go、kubelet、kube-proxy、kubectl、metrics等最终还会为整个仓库打一个v1.28.2-k3s1总标签。推送标签到 k3s-io 远端设置REMOTE变量并执行push.sh将上一步生成的所有标签推送到 k3s-io 的 fork 仓库export REMOTEk3s-io ./push.sh更新 K3s 依赖到新标签此时工作树中已有一批打了新标签的 Kubernetes 模块。接下来在K3s 主仓库中更新go.mod使其指向这些新标签然后即可提交 PR 供评审。cd ${GOPATH}/src/github.com/k3s-io/k3s git remote add upstream https://github.com/k3s-io/k3s.git git fetch upstream git branch delete ${NEW_K3S_VER} git checkout -B ${NEW_K3S_VER} upstream/${RELEASE_BRANCH} git clean -xfd sed -Ei \|github.com/k3s-io/kubernetes| s|${OLD_K3S_VER}|${NEW_K3S_VER}| go.mod sed -Ei s/k8s.io\/kubernetes v\S/k8s.io\/kubernetes ${NEW_K8S}/ go.mod sed -Ei s/${OLD_K8S_CLIENT}/${NEW_K8S_CLIENT}/g go.mod # since drone perform the builds and tests for the updated tags we no longer need to run make locally. # We now update the go.sum by running go mod tidy: go mod tidy以上sed命令逐一完成三处替换把所有github.com/k3s-io/kubernetes相关的 replace 目标从${OLD_K3S_VER}如v1.28.1-k3s1替换为${NEW_K3S_VER}如v1.28.2-k3s1把k8s.io/kubernetes主模块版本替换为新的${NEW_K8S}全局替换client-go关联版本号${OLD_K8S_CLIENT}→${NEW_K8S_CLIENT}。以当前仓库 go.mod 的实际状态为例可以看到这一替换体系的最终形态——所有k8s.io/*模块均通过replace指向github.com/k3s-io/kubernetes下对应 staging 目录的-k3s1标签k8s.io/api github.com/k3s-io/kubernetes/staging/src/k8s.io/api v1.36.3-k3s1 k8s.io/apimachinery github.com/k3s-io/kubernetes/staging/src/k8s.io/apimachinery v1.36.3-k3s1 k8s.io/client-go github.com/k3s-io/kubernetes/staging/src/k8s.io/client-go v1.36.3-k3s1 k8s.io/kubelet github.com/k3s-io/kubernetes/staging/src/k8s.io/kubelet v1.36.3-k3s1 k8s.io/kubernetes github.com/k3s-io/kubernetes v1.36.3-k3s1由于 Drone CI 会针对更新后的标签自动执行构建与测试本地无需再运行make只需用go mod tidy更新go.sum。同步 Go 版本如果新版本 Kubernetes 要求的 Go 版本有变化需要同步更新 K3s 仓库中的 Dockerfile 与 GitHub Actions 工作流export OLD_GO_VERSIONold-go-version sed -i s/$OLD_GO_VERSION/$GOVERSION/g Dockerfile.* .github/workflows/integration.yaml .github/workflows/unitcoverage.yaml即把Dockerfile.*含Dockerfile、Dockerfile.test、Dockerfile.manifest等具体范围以仓库实际文件为准以及.github/workflows/integration.yaml、.github/workflows/unitcoverage.yaml中的旧 Go 版本统一替换为$GOVERSION。关于 modsync 脚本的说明需要特别注意的是modsync 脚本k3s_modsync.sh仅用于针对特定上游 Kubernetes commit 而非 tag的更新场景。常规 patch release 流程中不需要使用它。仅在需要把 K3s 的依赖与某个上游 commit 对齐时才执行curl -s https://raw.githubusercontent.com/rancher/ecm-distro-tools/master/bin/k3s_modsync.sh | sh -验证 K3s 构建在提交 PR 之前先在本地验证 K3s 可以正常构建SKIP_VALIDATE1 make其中SKIP_VALIDATE1用于跳过仓库校验步骤对应 Makefile 中validatetarget 传递的SKIP_VALIDATE构建参数仅验证编译产物能否产出。若构建失败可能需要同步更新其他持有上游组件 fork 的仓库常见的有k3s-io/klogk3s-io/cri-dockerdk3s-io/containerd对于这些仓库需要为其构建并推送新 tag然后在go.mod中把对应依赖更新到新 tag。创建 PR将所有改动提交并推送到个人 fork 的${NEW_K3S_VER}分支git commit --all --signoff -m Update to ${NEW_K8S} git push --set-upstream origin ${NEW_K3S_VER}随后基于该分支创建 PR务必以对应的发布分支${RELEASE_BRANCH}为合入目标等待 CI 在 PR 上运行测试。CI 通过并得到两个 approve之后即可 squash-merge 该 PRmerge 后的主 CI 运行完成后就可以打 RC 标签了。创建发布候选RC发布由打标签触发。在 GitHub UI 上按以下步骤创建 release按正在处理的发布版本设置 title 与 tag例如常规升级仅升级 Kubernetesv1.28.2-rc1k3s1K3s 自身单独更新K3s 版本号递增从k3s1递增到k3s2如v1.28.2-rc1k3s2描述description留空勾选pre-release复选框发布Publish。若因依赖变更如k3s-io/k3s-upgrade仓库的改动需要新的候选版本重复上述打标签流程并将 rc 序号递增rc1 → rc2 …即可。关于 tag 目标的补充tag 应与 release 标题一致target 指向对应发布分支最新版本挂在main分支上参见 docs/release/expanded/cut_release.md。RC 发布后还需在发布 Slack 频道中通知新的 RC 已可用。检查 system-agent-installer-k3s 发布镜像system-agent-installer-k3s仓库服务于 Rancher 的 v2prov 系统凡是写入 Rancher KDM 的 K3s 版本包括 RC 与正式版都必须在system-agent-installer-k3s中同步发布。因此需要前往rancher/system-agent-installer-k3s仓库核对是否已为与版本号对应的新 release 与 tag 创建了记录在rancher/system-agent-installer-k3s的 Docker Hub tags 页面跟踪构建进度。若自动化未生效则按后续检查发布镜像一节的说明手动触发。检查发布镜像k3s-upgradek3s-upgrade仓库将 K3s 二进制与升级脚本打包成镜像供用户升级到新的 K3s release。该过程通常自动进行但自动化失败时需手动介入前往k3s-upgrade仓库为本次发布手动创建一个新 tag例如v1.28.2-rc1k3s1触发镜像构建Draft 一个新的 release输入 tag如v1.28.2-rc1k3s1确认k3s 镜像与k3s-upgrade 镜像均已存在。构建需要一些时间完成后镜像会出现在各自的 Docker Hub 镜像列表rancher/k3s与rancher/k3s-upgrade中。验证组件发布版本每次发布K3s 都会在 release notes 中附带一张组件及其版本的表格。发布负责人应据此核对各组件Kubernetes、containerd、runc、flannel、cri-dockerd 等的版本是否与本次发布一致。release notes 的具体生成与校验方法可参见 docs/release/expanded/release_notes.md。更新 Rancher KDM此步骤专属于 Rancher 生态目的是更新 Rancher 的Kontainer Driver MetadataKDM数据使 Rancher 能够识别并使用新版本 K3s。在rancher/kontainer-driver-metadata仓库最新 dev 分支上创建一个 PR更新channels.yaml中的 Kubernetes 版本。该 PR 应包含两个 commit修改channels.yaml以更新 Kubernetes 版本运行go generate提交其产生的data/data.json变更第二个 commit 标题为go generate。注意事项若是 Kubernetes 的新 minor 版本需要在channels.yaml中新建条目并正确设置min/max版本约束不确定时应向团队确认取决于 Rancher 计划支持的范围自 v1.21.4 起每次发布无论 minor 还是 patch都要求在channels.yaml中新建条目新条目可以复用其他条目已定义的 server、agent 与 chart 参数。例如v1.21.4定义了如下 server args本小节示例均取自原文档版本对应本次发布中的实际 patch 版本- version: v1.21.4k3s2 minChannelServerVersion: v2.6.0-alpha1 maxChannelServerVersion: v2.6.99 ... serverArgs: serverArgs-v1 tls-san: type: array后续版本可以直接通过 YAML 锚点引用这些参数而无需改动- version: v1.21.5k3s1 minChannelServerVersion: v2.6.0-alpha1 maxChannelServerVersion: v2.6.99 serverArgs: *serverArgs-v1QA 也可能基于 RC 提出 spec 变更请求此时需按 RC 版本更新约束例如- version: v1.28.2-rc1k3s1 minChannelServerVersion: v2.8.0-alpha1 maxChannelServerVersion: v2.8.99 serverArgs: *serverArgs-v7如果不确定新 minor 版本的 min/max 约束可以向项目经理和/或 QA 确认。创建 GA 发布候选QA 验证 RC 可用或后续 RC 已包含修复之后进入正式发布GA阶段在 GitHub Web 界面创建新 release设置 title 为${NEW_K8S}添加包含 release notes 的描述tag 部分留空勾选pre-release复选框先保存为draft直到 RC 测试完成。QA 对某个 RC 签署通过后设置要创建的 tag——该 tag 需与 draft title 中的版本一致确保 prerelease 已勾选发布Publish重复前面的各项检查流程并用 GA 发布标签更新 KDM 规范CI 完成、产物已生成后在 Slack 发布线程中宣布 GA 并告知 K3s 已解除冻结thawed创建一个 tag 匹配的system-agent-installer-k3srelease。24 小时之后取消 prerelease 勾选并保存更新 channel server见下一节。更新 Channel Server发布被验证后需要更新 channel server 配置让stable通道指向新版本。Channel 配置文件位于 K3s 仓库根目录的 channel.yaml只需单行修改# Example channels config channels: - name: stable latest: new-k8s-versionk3s1 # Replace this semver with the version corresponding to the release负责该改动的 Release Captain 需要将上述 stanza 中的latest更新为本次发布对应的新 stable 版本。以当前仓库 channel.yaml 的实际内容为例stable通道当前指向v1.36.3k3s1同时latest/testing通道通过latestRegexp与excludeRegexp分别匹配最新版与 RC 版本每个 minor 版本v1.16至v1.36均有对应的vX.Y通道。这印证了原文档中单行修改 stable的操作边界——升级一个 patch 版本时通常只需改动stable通道这一行。源码佐证版本如何从 go.mod 流转到二进制上述流程最终服务的是让 K3s 二进制携带正确的版本号。从源码可以看出版本信息的来源链条scripts/version.sh 通过go list -m从go.mod读取k8s.io/kubernetes的 replace 版本VERSION_K8S_K3S并剥离-k3s*后缀得到VERSION_K8S它还读取 containerd、cri-tools、runc、flannel、cri-dockerd 等组件的版本用于 release notes 的组件版本表当存在GIT_TAG即 tag 构建时version.sh会校验 tag 是否匹配^$VERSION_K8S[-]不匹配则报错退出——这就是go.mod 必须先行更新、再打 tag这一顺序的底层原因最终版本号写入 pkg/version/version.go 的Version变量未打 tag 时为dev并参与二进制构建。因此发布流程中tag.sh → push.sh → go.mod 更新 → go mod tidy → 构建验证的顺序本质上就是在为这条版本链路准备正确的输入。收尾解除冻结与发布公告完成以上全部流程后请在发布 Slack 线程中公布patch release 已全部完成、代码冻结code freeze已结束。至此一次完整的 K3s Kubernetes 补丁版本发布即告收官从上游变基打标、主仓库依赖更新、PR 合入到 RC/GA 发布、Rancher KDM 同步与 Channel Server 切换所有环节环环相扣。相关命令的完整串联示例可进一步参考 docs/release/expanded/cut_release.mdchannel 更新细节见 docs/release/expanded/channel_server.md整体发布流程可参阅 docs/release/release.md。【免费下载链接】k3sLightweight Kubernetes项目地址: https://gitcode.com/GitHub_Trending/k3/k3s创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表