在基于KubeSphere的Jenkins的流水线中切换nodejs版本
近期有个项目组有个Vue
项目需要在基于KubeSphere
的Jenkins
流水线中用高版本的nodejs
进行编译,自己一开始尝试通过在流水线中直接升级nodejs
版本,但并未成功,后来参考KubeSphere
论坛上的相关说明才解决该问题,简单记录下。
问题&尝试
项目中使用的KubeSphere
版本为v3.3.1
,基于nodejs
环境对某个 Vue3
项目进行编译打包时,KubeSphere
提示构建过程出错。Google搜索一番过后,大部分都说要升级nodejs
版本,自己当前的版本为v10.16.3
,确实有些低,于是尝试用如下指令升级版本
rm -rf node_modules package-lock.json yarn.lock
npm cache clean --force
npm config set registry https://mirrors.xxx.com/repository/NPM/
npm install node@16.16.0
npm install
node -v
npm run build:qiankun
重新执行后依旧报错,同时node -v
输出的结果依然是v10.16.3
,版本不是预期的升级后版本。
为啥npm install node@16.16.0
这条指令执行正常,而node -v
输出的仍然为旧版本呢?
在构建之前添加如下两条指令进行分析
$PWD/node_modules/node/bin/node -v
node config list
输出结果如下
可以看出npm install node@16.16.0
只是升级当前工程的nodejs
版本,但是全局的版本还是旧的而编译时使用的是全局版本,导致问题出现。
将该指令变为npm install node@16.16.0 -g
再次执行,结果提示权限不足
至于为什么权限不足,原因也很简单,因为我们是在Jenkins
流水线中执行该指令的,Jenkins
每次执行都会创建一个临时目录,其出于安全考虑并没有赋予执行过程全部的权限。
通过Jenkins
升级nodejs
版本这条路走不通,那能否通过对相关工程源码进行修改,让其兼容低版本呢?内部讨论后出于下述考量,此方案也不可行:
- 降低工程依赖的
nodejs
版本会涉及到大量的功能逻辑,需要进行全面的测试,确保没有引入新问题 - 后续其它工程模块可能也会使用高版本的
nodejs
,从出于扩展的角度考虑此问题早晚都要解决
软件开发领域理论上要求 高版本要能兼容低版本,能否通过统一升级Jenkins
中所用的nodejs
版本来解决此问题呢?虽然理论分析确实可行,不过此种方式只能升级到特定版本,无法同时兼容多个版本,同时所有的前端项目构建都会受到影响,灵活性不高。
既然遇到了这个问题,个人希望一次性解决,最好能在流水线中指定所需的版本,与其它的流水线完全隔离!
解决
由于自己采用的是KubeSphere
来集成Jenkins
,其他人是否遇到了类似问题?通过相关关键词搜索后发现一篇文章kubesphere3.1.1,devops工程如何升级node.js,其遇到的问题和我自己的很类似。
根据该问题中的回复,需要对Jenkins
流水线文件头部的配置进行修改
原始配置如下
agent {
node {
label 'nodejs'
}
}
修改为
agent {
kubernetes {
inheritFrom 'nodejs base'
containerTemplate {
name 'nodejs'
image 'node:16.16.0'
}
}
}
同时将前端构建指令修改如下
rm -rf node_modules package-lock.json yarn.lock
npm cache clean --force
npm config set registry https://mirrors.xxx.com/repository/NPM/
npm install
node -v
npm run build:qiankun
再次执行相关构建,输出类似如下,可以看出nodejs
版本已经修改为我们希望的版本,且能正常编译通过
基于上述方式修改后,初次执行时可能会出现类似如下错误,出错的原因是相关镜像还没下载下来,多执行几次即可。
当流水线全部执行完毕时,发现无法识别docker
指令,导致无法进行编译构建。
继续在该问题下寻找答案,发现KubeSphere
官方的技术支持人员有给出答案
将docker
构建阶段的容器从nodejs
修改为base
即可,重新执行流水线可正常执行1,至此问题解决完毕。
stage('镜像构建') {
agent none
steps {
container('base') {
sh '''echo $NODE_PORT
cat cicd/Dockerfile
docker build -f cicd/Dockerfile --build-arg PRODUCT_PHASE=$PRODUCT_PHASE -t orienlink-evaluator-web:$BUILD_TAG .'''
}
}
}
}
后记
虽然此文以nodejs
举例,但对于其它的语言也可适用,假设使用的是Golang
,对应的Jenkins
流水线文件头部可修改如下
agent {
kubernetes {
inheritFrom 'go base'
containerTemplate {
name 'go'
image 'go:1.22.2'
}
}
}
通过上述方式可实现基于流水线级别的版本变更与隔离,使用起来更加方便。
-
完整的
Jenkins
流水线参见lucumt-nodejs-version-change.groovy ↩︎