我手工改的字段在升级后消失了
目标
亲手制造并确认,在集群里手动修改过的值和标签,在 helm upgrade 之后会怎样;并通过 release 记录比较沿用之前用户值的三个选项的差别。
为什么重要
Helm 3 在升级时用旧清单、新清单、集群实物这三者制作补丁。这一条规则就能解释现场反复出现的两种现象——故障期间用 kubectl scale 调高的副本数会在下次部署时被改回去,而紧急加上的标签会原样保留。因为 Chart 声明了的字段,以声明为准;Chart 不知道的字段,则不去碰。此外在值这一侧还有一条规则。helm upgrade 默认不会沿用上一个 release 的用户值。所以部署脚本里一旦漏掉一个 --set,那个值就会悄悄回到 Chart 默认值。--reuse-values 解决了这个问题,却让值只留在 release 里,在仓库中看不见。用哪一个,不该凭喜好,而应由“部署能否重现”来决定,而要做到这一点,就得亲眼看一次这三个选项实际做了什么。
步骤
- 创建
/root/hc-upgrade/ledgerChart(名称ledger,版本0.1.0)。values.yaml有replicas: 1、image: "registry.local/ledger:1.0.0"、extraLabel: ""三个值。templates/deployment.yaml是名称为<릴리스이름>-ledger(占位符为 release 名称)的 Deployment,在metadata.labels中放app: ledger,只有extraLabel不为空时才加上tier: <그 값>(占位符为该值)。以 release 名称books安装之后,把helm get manifest books保存到/root/hc-upgrade/out/rev1-manifest.yaml。 - 用
kubectl把books-ledgerDeployment 的副本数调到5,并加上标签owner=ops。把那个状态以{"replicas": …, "owner": …, "tier": …}三个键的 JSON 保存到/root/hc-upgrade/out/before-upgrade.json(没有的标签写null)。 - 在完全不改 Chart 和值的情况下运行
helm upgrade books /root/hc-upgrade/ledger。然后把同样三个键的 JSON 保存到/root/hc-upgrade/out/after-upgrade.json,确认手动修改的两项中,哪个保留了、哪个被改回去了。 - 用
--set extraLabel=gold升级,把带有tier标签的状态保存到/root/hc-upgrade/out/label-added.json。接着把extraLabel设为空字符串再次升级,把tier标签消失后的状态保存到/root/hc-upgrade/out/label-removed.json。两个文件都是同样三个键的 JSON。这时也请一并看看owner标签会怎样。 - 用
--set replicas=4 --set extraLabel=silver升级,把helm get values books -o json保存到/root/hc-upgrade/out/values-1.json。接着只给出--set replicas=6再次升级,把同一命令的结果保存到/root/hc-upgrade/out/values-2.json。extraLabel会怎样,就是答案。 - 沿用上一个 release 的用户值,只加上
--set extraLabel=bronze来升级。把helm get values books -o json的结果保存到/root/hc-upgrade/out/values-reuse.json。replicas必须保留上一步的 6,extraLabel必须是 bronze。 - 先用
--set replicas=4 --set extraLabel=silver升级,建立基准。在此基础上,对--set replicas=7加上先回到 Chart 默认值、再叠加上次用户值的选项升级,把结果保存到/root/hc-upgrade/out/values-rtr.json。接着对--set replicas=9加上丢弃上次的值的选项升级,把结果保存到/root/hc-upgrade/out/values-reset.json。 - 用
--set replicas=3运行服务端预览,把输出保存到/root/hc-upgrade/out/dryrun.yaml(release 不能改变)。然后用同样的值加上--force真正升级,把之后的状态以与第 2 步相同的三个键的 JSON 保存到/root/hc-upgrade/out/after-force.json——请确认手动加上的owner标签会怎样。把helm history books -o json保存到/root/hc-upgrade/out/history.json,并在/root/hc-upgrade/out/merge-report.json中写入manual_scale_kept、manual_label_kept、chart_removed_label_deleted、default_upgrade_reuses_values、manual_label_survives_force五个布尔值和final_replicas数字。值从前面步骤保存的文件中读取。
参考
helm get values <릴리스> -o json(占位符为 release 名称)只显示用户给出的值,--all则连 Chart 默认值也显示- 用
kubectl get deploy <이름> -o json | jq '{...}'(占位符为名称)只取需要的字段来比较 helm upgrade --dry-run=server会发送到 API 服务器做验证,但不创建 release- 常见错误:故障期间用
kubectl scale调高的值被下一次部署改回去 - 常见错误:部署脚本里漏掉一个
--set,只有那个值回到默认值 - 官方文档:https://helm.sh/docs/helm/helm_upgrade/ · https://helm.sh/docs/faq/changes_since_helm2/
先部署一个之后要改回去看的东西
创建 /root/hc-upgrade/ledger Chart(名称 ledger,版本 0.1.0)。values.yaml 有 replicas: 1、image: "registry.local/ledger:1.0.0"、extraLabel: "" 三个值。templates/deployment.yaml 是名称为 <릴리스이름>-ledger(占位符为 release 名称)的 Deployment,在 metadata.labels 中放 app: ledger,只有 extraLabel 不为空时才加上 tier: <그 값>(占位符为该值)。以 release 名称 books 安装之后,把 helm get manifest books 保存到 /root/hc-upgrade/out/rev1-manifest.yaml。
在 kwok 集群里 Pod 不会真的运行,但 Deployment 对象会正常创建——本实验只看对象的字段值。有条件地加标签的部分,用 {{- if .Values.extraLabel }} 块包起来,并用前面的 - 让条件为假时不留空行。
在集群里手动修改
用 kubectl 把 books-ledger Deployment 的副本数调到 5,并加上标签 owner=ops。把那个状态以 {"replicas": …, "owner": …, "tier": …} 三个键的 JSON 保存到 /root/hc-upgrade/out/before-upgrade.json(没有的标签写 null)。
是 kubectl scale deploy/books-ledger --replicas=5 和 kubectl label deploy/books-ledger owner=ops --overwrite 两条命令。这是故障应对中常做的事,问题出在下一次部署。取出 JSON 时用 kubectl get deploy books-ledger -o json | jq '{...}'。
一点不改 Chart 就升级
在完全不改 Chart 和值的情况下运行 helm upgrade books /root/hc-upgrade/ledger。然后把同样三个键的 JSON 保存到 /root/hc-upgrade/out/after-upgrade.json,确认手动修改的两项中,哪个保留了、哪个被改回去了。
Helm 3 用旧清单、新清单、集群实物这三者制作补丁。Chart 声明了值的字段,即使集群实物不同,也会按声明一侧对齐。Chart 根本不知道的字段则不去碰。必须能用这两条规则解释结果。
从 Chart 中去掉的字段,在集群里也会被删掉
用 --set extraLabel=gold 升级,把带有 tier 标签的状态保存到 /root/hc-upgrade/out/label-added.json。接着把 extraLabel 设为空字符串再次升级,把 tier 标签消失后的状态保存到 /root/hc-upgrade/out/label-removed.json。两个文件都是同样三个键的 JSON。这时也请一并看看 owner 标签会怎样。
条件变为假,新清单里就没有那个标签了。Helm 会与旧清单对比,生成删除缺失字段的补丁。而 owner 是哪个清单里都没有过的字段,所以不属于补丁对象。由 Chart 管理的与由人加上的,界线就在这里分开。注意:如果升级时一个值也不给,Helm 会原样使用上一个 release 的用户值——所以仅仅去掉 --set,gold 并不会消失。请亲自试一下,确认差别。
升级会丢弃上次的用户值
用 --set replicas=4 --set extraLabel=silver 升级,把 helm get values books -o json 保存到 /root/hc-upgrade/out/values-1.json。接着只给出 --set replicas=6 再次升级,把同一命令的结果保存到 /root/hc-upgrade/out/values-2.json。extraLabel 会怎样,就是答案。
helm get values 只显示用户给出的值(想连 Chart 默认值也看,用 --all)。在默认行为下,升级不会沿用上一个 release 的用户值,只使用这次给出的。部署脚本每次都得把所有 --set 重新写一遍,原因就在这里。
沿用上次的值,只改一个值
沿用上一个 release 的用户值,只加上 --set extraLabel=bronze 来升级。把 helm get values books -o json 的结果保存到 /root/hc-upgrade/out/values-reuse.json。replicas 必须保留上一步的 6,extraLabel 必须是 bronze。
有专门的沿用选项(在 helm upgrade --help 中找含 reuse 的)。看起来方便,但有个陷阱——沿用来的值既不在命令行,也不在仓库,只在 release 里。所以 release 越久,就越没有人知道“现在是用什么值在运行”。
把三个沿用选项并排放在一起
先用 --set replicas=4 --set extraLabel=silver 升级,建立基准。在此基础上,对 --set replicas=7 加上先回到 Chart 默认值、再叠加上次用户值的选项升级,把结果保存到 /root/hc-upgrade/out/values-rtr.json。接着对 --set replicas=9 加上丢弃上次的值的选项升级,把结果保存到 /root/hc-upgrade/out/values-reset.json。
三个选项的名字彼此相似,容易混淆——请在 helm upgrade --help 中把这三个并排读一遍。一个是原样沿用上次的值,一个是先回到默认值再叠加上次的用户值,一个是把上次的值彻底丢掉。可以通过保存下来的两个文件中键的个数差异来区分。
预览、用替换来应用,并整理规则
用 --set replicas=3 运行服务端预览,把输出保存到 /root/hc-upgrade/out/dryrun.yaml(release 不能改变)。然后用同样的值加上 --force 真正升级,把之后的状态以与第 2 步相同的三个键的 JSON 保存到 /root/hc-upgrade/out/after-force.json——请确认手动加上的 owner 标签会怎样。把 helm history books -o json 保存到 /root/hc-upgrade/out/history.json,并在 /root/hc-upgrade/out/merge-report.json 中写入 manual_scale_kept、manual_label_kept、chart_removed_label_deleted、default_upgrade_reuses_values、manual_label_survives_force 五个布尔值和 final_replicas 数字。值从前面步骤保存的文件中读取。
--dry-run=server 会发送到 API 服务器只做验证,不创建 release。--force 以替换方式而不是补丁来应用——在有无法用补丁修改的不可变字段时使用,但因为是替换,对象会被整个换成新清单。那么第 3 步中保留下来的东西,这次会怎样?请先想一想再确认。五个布尔值,对照第 2–5 步和刚保存的 JSON 就能得出。