Helm安装/升级时如何动态设置.Chart.AppVersion无需编辑Chart.yaml
流水线部署Helm应用时,需要实现Chart.AppVersion动态注入能力,保证执行helm history命令时返回的APP VERSION字段对应当次实际部署的应用版本,且不需要提前编辑仓库内的Chart.yaml文件。
默认配置下helm history返回的APP VERSION字段固定读取Chart.yaml中预设的静态值,和实际部署的应用版本不匹配,异常输出示例:
REVISION UPDATED STATUS CHART APP VERSION DESCRIPTION 1 Mon Jun 8 11:39:51 2020 superseded spring-1.0.0 1.0.0 Install complete 2 Mon Jun 8 12:19:21 2020 superseded spring-1.0.0 1.0.0 Upgrade complete 3 Mon Jun 8 12:20:51 2020 deployed spring-1.0.0 1.0.0 Upgrade complete
该现象是Helm的原生设计逻辑,相关问题在Helm官方Issue #8194中有明确记录。
期望实现效果:支持通过命令参数直接传入动态版本变量,helm history输出的各修订版APP VERSION字段和当次部署版本一一对应,期望输出示例:
REVISION UPDATED STATUS CHART APP VERSION DESCRIPTION 1 Mon Jun 8 11:39:51 2020 superseded spring-1.0.0 1.0.1 Install complete 2 Mon Jun 8 12:19:21 2020 superseded spring-1.0.0 1.0.2 Upgrade complete 3 Mon Jun 8 12:20:51 2020 deployed spring-1.0.0 1.0.3 Upgrade complete
当前临时方案是通过sed直接替换源码目录下Chart.yaml的version和appVersion字段为git describe生成的版本号后再执行部署,命令如下:
sed -i "s/^version:.*$/version: $(git describe)/" chart/Chart.yaml sed -i "s/^appVersion:.*$/appVersion: $(git describe)/" chart/Chart.yaml helm upgrade app ./chart
该方案会直接修改仓库内的Chart源文件,流程繁琐且存在文件误提交、并发流水线冲突的风险,需要更优雅的无文件修改实现方案。
方案1:原生参数实现(推荐,适用于Helm 3.8及以上版本)
Helm从3.8版本开始,helm install、helm upgrade、helm template等命令原生支持--app-version参数,直接在部署命令中传入动态版本即可,全程不触碰源Chart.yaml文件:
# 从git获取实际版本号 APP_VER=$(git describe) CHART_VER=$(git describe) # 部署时直接传入版本参数 helm upgrade app ./chart --install \ --version "$CHART_VER" \ --app-version "$APP_VER"
执行完成后执行helm history即可看到APP VERSION字段正确显示传入的动态版本号,完全匹配预期效果。
方案2:helm package动态注入(适用于Helm 3全版本,兼容3.8以下低版本)
如果使用的Helm版本低于3.8,可以通过helm package命令的参数动态注入版本,直接部署打包生成的临时tgz包,不会修改源目录下的任何文件:
APP_VER=$(git describe) CHART_VER=$(git describe) # 动态注入版本打包到临时目录,不修改源文件 helm package ./chart \ --version "$CHART_VER" \ --app-version "$APP_VER" \ -d /tmp/helm-tmp # 部署临时生成的chart包 helm upgrade app /tmp/helm-tmp/chart-${CHART_VER}.tgz --install # 部署完成后清理临时文件 rm -rf /tmp/helm-tmp
方案3:临时目录隔离替换(全版本兼容,适配所有Helm版本包括Helm 2)
如果需要适配更老的Helm版本,或者需要在部署前对Chart做其他临时修改,可以先把整个Chart目录复制到流水线临时工作目录,所有修改操作都在临时目录内执行,完全不影响源码目录的文件:
APP_VER=$(git describe) CHART_VER=$(git describe) TMP_CHART_DIR=/tmp/helm-tmp-chart # 复制chart到临时目录 rm -rf $TMP_CHART_DIR cp -r ./chart $TMP_CHART_DIR # 在临时目录内替换版本字段 sed -i "s/^version:.*$/version: ${CHART_VER}/" $TMP_CHART_DIR/Chart.yaml sed -i "s/^appVersion:.*$/appVersion: ${APP_VER}/" $TMP_CHART_DIR/Chart.yaml # 部署临时目录的chart helm upgrade app $TMP_CHART_DIR --install # 清理临时目录 rm -rf $TMP_CHART_DIR
--app-version参数对传入值没有格式限制,支持语义化版本、Git Commit Hash、构建号等任意字符串格式的版本标识- 禁止直接在源码仓库目录执行sed替换Chart.yaml的操作,避免本地文件被意外提交到代码库,同时防止多流水线并发执行时出现文件读写冲突
- Helm 2已停止官方维护,存在已知安全风险,建议尽快升级到Helm 3版本
内容的提问来源于stack exchange,提问作者Calvin

