拓冰建站拓冰建站
首页 / 资讯中心 / 正文

Jenkins Config File Provider插件实战:统一管理构建配置文件

1. 为什么需要Config File Provider插件1.1 从一件事说起配置文件管理之痛先抛个场景。假设你手上有十几个Jenkins任务每个任务构建前都需要往特定目录放一份Maven的settings.xml或者往Tomcat的配置目录塞一份server.xml又或者需要给后端项目准备一份application-prod.properties。这些配置文件内容不一样但每个任务都需要用到。你可能会说直接把文件放到代码仓库里不就行了问题是很多配置文件涉及环境差异、密钥信息、灰度开关放在代码仓库里既不安全也不方便统一管理。更麻烦的是如果配置文件包含数据库密码、私钥这类敏感信息一旦代码仓库泄露后果你懂的。另一个常见做法是把配置文件塞进Jenkins的workspace里。听着简单但只要你配置了“构建前清空工作区”每次构建前文件就没了或者你在Pipeline里用了checkout代码一拉就把配置文件覆盖了。这个场景我踩过不止一次所以后来我基本都改用Config File Provider插件来统一管这些文件。Config File Provider插件是Jenkins官方维护的一个工具插件专门用来管理构建过程中需要用到的各种配置文件。你可以在Jenkins的全局管理界面里预先定义好一组文件然后在Pipeline或者普通任务里按需引用构建开始时插件会自动把文件注入到指定的位置。它的核心价值在于把“配置”和“业务代码”彻底分离让配置文件的维护权限收归到统一的入口同时又能按环境、按任务灵活切换。1.2 这个插件到底解决了什么问题先说最直接的解决了配置文件散落各处的问题。以前你可能需要维护多个Jenkins任务的配置文件文件稍一改动就要去逐个任务里同步。有了Config File Provider你在“Managed files”里维护一份文件多个任务引用同一份改一次就能全局生效不会出现改了A任务忘了B任务这种尴尬。再一个是解决了敏感信息泄露的问题。配置文件的内容以加密形式存放在Jenkins的全局配置里不会出现在代码仓库也不会出现在构建控制台日志中。Jenkins还提供了Replace Tokens功能可以在注入文件时动态替换变量比如把数据库地址、账号密码通过参数传进去这样一份模板就能应对多变的环境。还有一个好处是对Pipeline特别友好。在声明式Pipeline里你可以用configFileProvider步骤在某个代码块内临时注入文件代码块执行完文件自动清理不影响下一次构建。这种“用完即走”的机制比手动写script去创建删除文件优雅得多。适用人群也很明确如果你在用Jenkins做持续集成、持续部署需要管理Maven的settings.xml、Nginx配置、Tomcat配置文件、Kubernetes的kubeconfig、各种properties/yaml配置文件或者需要把配置模板和环境变量组合起来使用这个插件基本就是标配。2. 插件安装与配置入口2.1 安装步骤安装插件没什么特别的和装其他Jenkins插件一样。进入“系统管理 → 插件管理 → 可选插件”搜索“Config File Provider”找到后点击安装等待安装完成后重启Jenkins即可。要注意的是插件对Jenkins版本有要求如果用的是比较旧的Jenkins版本建议先看一眼插件描述里的下限版本要求免得装完报依赖错误。插件安装之后你会发现系统管理菜单里多了一个条目叫做“Managed files”。这就是整个插件的核心管理界面所有需要被管理的配置文件都在这里维护。进入界面后左侧是文件列表右侧是操作按钮你可以新建、编辑、复制、删除任意一个配置文件。这里有一个小小的操作习惯我在新建文件之前一般会先创建一个清晰的命名规则。比如“maven-settings-dev”“maven-settings-prod”“kubeconfig-preprod”把环境和用途写清楚。配置文件一多命名如果不规范后面引用的时候真的会找半天。2.2 插件设置里的全局选项在“系统管理 → 系统配置”里你会看到Config File Provider相关的全局设置。这里值得提的有两个选项Replace Tokens默认勾选即可。这个选项决定是否在注入文件时使用占位符替换比如文件内容里写了${DATABASE_URL}注入后会被替换成你在任务里定义的环境变量值。Encode Files如果勾选这个选项插件会把文件内容做一层转码防止特殊字符被Jenkins解析。这个选项我一般保持默认只有在文件内容里出现特殊符号导致构建出错时才打开。还有一个容易被忽略的点插件的配置文件是存储在Jenkins的配置文件目录下的也就是$JENKINS_HOME/config-files/目录里。所以做Jenkins备份或迁移时别忘了把config-files目录一起备份。迁移后如果发现配置文件没同步多半是只搬了JENKINS_HOME但漏掉了config-files子目录。3. 创建与管理配置文件3.1 支持的文件类型说明Config File Provider插件支持的文件类型有JSON、XML、YAML、properties、Groovy脚本以及自定义文件类型。理论上说只要是你想注入到构建环境里的文本类配置文件基本都能覆盖。如果是二进制文件比如jar包、zip包这个插件就不适合了建议直接用凭据或者依赖仓库管理。具体操作上点击“Managed files → Add a new config → 选择类型”。每种类型对应的编辑器会不一样比如JSON类型会给一个简单的JSON校验XML类型会做基础格式检查。不过别指望它有多智能它只是保证基本格式正确不会校验内容的业务逻辑。我在实际使用中一般是用一个占位文件先创建好再通过编辑功能把完整内容贴进去这样比在文本框里直接写长内容更不容易出错。3.2 配置文件的关键参数不管选择哪种类型新建配置文件都有几个核心参数需要填参数名作用注意事项Name配置文件名称建议用有意义的名称如tenant-config-prod.yaml方便在任务中识别Comment备注说明可选建议写上用途方便团队其他人理解Content文件内容支持在里面写模板变量配合Replace Tokens使用Provide as a file是否以文件形式注入勾选后还可以指定目标文件名不勾选则会以参数形式注入Target folder目标文件夹指定注入到构建工作区的哪个目录不填则用默认路径重点说下Target folder。如果不填插件默认会把文件注入到当前工作区的根目录如果填了比如填写conf/那么构建开始后会在工作区的conf目录下生成这个文件。这个参数在Freestyle任务里比较常用在Pipeline里我们通常会通过targetLocation参数来控制后面会展开讲。3.3 配置文件版本管理还有个功能很多人可能没注意到就是配置文件的版本管理。你在“Managed files”列表里点击一个配置文件右侧会出现“Versions”入口。插件会记录每次修改的历史版本如果你想回滚到之前的某一份配置可以直接选一个历史版本恢复。这个功能在线上出问题时特别好用。有一次我的项目组改了一个Nginx配置文件模板改完构建出来的包行为异常排查了半天最后点开Versions发现是配置文件模板改出了问题一键回滚到上一个版本问题立刻解决。建议每次对线上使用的配置文件做修改后都留意下变更内容至少在版本历史里有据可查。4. 在Pipeline里使用Config File Provider4.1 基础语法与导入方式Pipeline中使用这个插件核心就一个步骤configFileProvider。使用前需要在Jenkinsfile开头把这句写进去Library(my-shared-library) _ // 如果用了共享库可以先忽略这句不对实际上使用configFileProvider不需要额外导入什么因为这个步骤是插件在运行时自动注册到全局的。不过在Groovy闭包里使用要确保你的Pipeline是声明式还是脚本式两种写法有细微差别。声明式Pipeline的基础用法是这样的pipeline { agent any stages { stage(Build) { steps { configFileProvider( [configFile(fileId: my-config-file-id, targetLocation: conf/application.properties, variable: APP_CONFIG_FILE)] ) { sh cat conf/application.properties } } } } }这里的关键参数有三个fileId配置文件的唯一标识可以在“Managed files”列表里找到点开某个配置文件地址栏里那个ID就是它或者用配置文件详情页里的ID字段。targetLocation注入到工作区后的路径如果只写文件名那就放在工作区根目录下。要放到子目录直接写“conf/application.properties”就行。variable指定一个环境变量名插件会把注入后的完整文件路径放到这个变量里之后在闭包内就可以用这个变量来访问文件。4.2 实战用configFileProvider注入Maven的settings.xml这个场景我估摸是使用频率最高的。在构建Java项目时Maven需要从私服拉取依赖这时必须指定一份settings.xml里面包含私服地址、镜像配置和本地仓库地址等。如果没有Config File Provider你通常得在构建机本地放一份settings.xml或者在Jenkinsfile里通过写文件的方式生成一份这两种方式都不灵活。用插件改造之后就简单了。先在“Managed files”里新建一个XML类型的配置文件内容大概是settings xmlnshttp://maven.apache.org/SETTINGS/1.0.0 mirrors mirror idnexus/id mirrorOf*/mirrorOf urlhttp://nexus.example.com/repository/maven-public//url /mirror /mirrors profiles profile iddefault-profile/id repositories repository idcentral/id urlhttp://nexus.example.com/repository/maven-public//url /repository /repositories /profile /profiles activeProfiles activeProfiledefault-profile/activeProfile /activeProfiles /settings然后在Pipeline的构建阶段这样写stage(Build) { steps { configFileProvider( [configFile(fileId: maven-settings-nexus, targetLocation: settings.xml, variable: MAVEN_SETTINGS)] ) { sh mvn clean package -s ${MAVEN_SETTINGS} } } }这样做的好处非常明显settings.xml的内容不再出现在Jenkinsfile里不会再被提交到代码仓库也不会出现在构建日志中。需要切换私服、调整镜像规则时只需在插件配置页面改一次所有引用了这个文件的任务都能生效不用挨个去改Pipeline。4.3 多个配置文件同时注入有时候一个构建阶段需要同时注入多个配置文件比如前端项目需要一份子应用的配置后端项目需要一份application.yml还可能需要一份Nginx的server配置。configFileProvider支持传入一个文件列表脚本式Pipeline写法如下stage(Prepare Config) { steps { script { configFileProvider([ configFile(fileId: frontend-config, targetLocation: frontend/conf.js, variable: FRONTEND_CONFIG), configFile(fileId: backend-yaml, targetLocation: backend/config/application.yaml, variable: BACKEND_CONFIG), configFile(fileId: nginx-server-conf, targetLocation: deploy/nginx/server.conf, variable: NGINX_CONFIG) ]) { sh echo frontend config at ${FRONTEND_CONFIG} echo backend config at ${BACKEND_CONFIG} // 这里可以继续执行构建脚本 } } } }注意configFileProvider的闭包执行完注入的文件默认不会被自动删除。如果你希望文件在闭包结束后自动清理可以传一个参数比如configFileProvider( [configFile(fileId: temp-config, targetLocation: temp.conf)], true ) { // 一切结束后文件会被删除 }第二个参数传true表示使用后自动清理。我建议对临时用到的配置文件都开这个避免把构建工作区搞得一团乱尤其是多个任务复用同一个工作区的场景下文件残留会导致下一次构建误用到旧配置这种问题真的很难排查。5. 在Freestyle任务里使用Config File Provider虽然现在Pipeline已经成了主流但很多老项目还在用Freestyle任务而且Freestyle里这个插件的配置方式也简单适合不熟Groovy的人快速上手。5.1 构建环境配置创建一个Freestyle任务打开任务配置在“构建环境”那一栏里勾选“Provide Configuration files”然后就能看到当前任务可以引用的配置文件列表。把需要使用的配置文件选进去每一项都可以单独设置Target注入到工作区后的完整路径或者文件名Variable注入后绑定的环境变量名后续命令里可以用Replace Tokens是否对该文件执行Token替换这里有个细节Target路径如果写成相对路径比如“config/app.properties”那么文件会注入到当前工作区的config目录下。这个目录如果不存在插件会自动创建不需要你自己先mkdir。如果你想让文件放到别的绝对路径下也可以直接写绝对路径前提是Jenkins运行用户对这个目录有写权限。5.2 替换Token的典型用法Freestyle任务里Replace Tokens这个勾选项单独提出来说一下因为在实际部署中它很常用。假设你维护了一份公共的application.properties模板里面有这样的占位内容spring.datasource.url${DATABASE_URL} spring.datasource.username${DATABASE_USERNAME} spring.datasource.password${DATABASE_PASSWORD}在Freestyle任务里你可以让这个任务定义为参数化构建定义三个字符串参数DATABASE_URL、DATABASE_USERNAME、DATABASE_PASSWORD。启动构建时填上对应的值插件在注入application.properties时会把模板中的占位符替换成实际参数值。这样同一个配置文件模板配合不同的任务参数就能为不同环境生成不同配置不用再复制多份配置文件。不过这里要留意一个老坑如果配置文件内容里本身带有“${...}”字符但你又不想让它被替换就需要在模板中需要用转义写法或者关闭Replace Tokens选项。我记得插件的文档里提供了一种写法“$”后面跟上花括号前的反斜杠。具体写法可以自己试一下我记得实际效果是把“${”替换为“${”。这种细微的语法问题只靠看文档容易忽略我建议你在测试任务里先验证一遍再上生产。6. 常见问题与排查技巧6.1 文件没有出现在预期路径这是问得最多的情况。明明在configFileProvider里配置了targetLocation构建完成后却找不到文件或者文件路径不对。排查思路三步走第一步确认configFileProvider闭包里的代码是否真的执行到了。有些时候Pipeline流程因为条件判断提前跳过了这个stage文件自然没注入。第二步确认targetLocation有没有写清楚。只写文件名时文件落在工作区根目录写了相对路径时相对的是工作区写了绝对路径就落在绝对路径下。尤其注意如果你在进入configFileProvider之前执行了dir(subdir)相对路径就会变成相对于subdir目录这个细节很容易踩。第三步确认插件是否正常工作。可以打开“系统管理 → 系统日志”在日志里加一个“jenkins.plugins.config_file_provider”的Logger级别调到FINE之后再次构建就能看到详细的文件注入日志文件有没有被注入、注入到哪个目录一清二楚。6.2 权限问题与凭据冲突第二个高发问题是“文件内容里包含了密码但构建日志把密码打印出来了”。这里其实涉及Jenkins的日志脱敏Config File Provider不会自动帮你隐藏文件内容如果自己写的sh命令里执行了cat配置文件内容就会在控制台显示。所以建议在配置文件里不要直接写明文密码而是用Token替换机制把密码放到Jenkins凭据里然后在构建时读取凭据并替换到配置文件里。还有一类问题是配置文件注入后文件的所有者是Jenkins运行用户如果后续构建步骤需要以root权限操作这个文件可能会遇到权限不足的报错。比如用sudo命令读取注入的文件时提示Permission denied。解决办法也比较粗暴给目标文件加上sudo chmod权限就行或者调整Jenkins运行账号的权限组让后续命令能以同一权限读取文件。这个问题在Docker容器里的Jenkins使用场景下格外明显因为容器里用户的权限划分比较严格。6.3 插件版本与Jenkins版本不兼容随着Jenkins版本升级到2.3xxConfig File Provider插件也做了不少调整。如果你用的插件版本比较老在新建配置文件时可能会发现界面上少了“YAML”或者“JSON”的选项那是因为老版本只支持XML和properties。遇到这种情况优先检查插件版本是否过旧升级到最新版往往能解决问题。还有一点Jenkins 2.381版本之后插件在默认的Global Settings里多了一些跟Folder相关的配置项如果你在Folder文件夹级别的任务里找不到“Managed files”入口需要先在全局配置里允许文件夹级别配置。这个问题我升级之后遇到过一开始还以为插件坏了后来才发现是文件夹权限的锅。6.4 快速排查汇总表现象可能原因解决办法文件没有注入targetLocation写错 / 阶段未执行开启FINE日志查看config_file_provider的日志文件内容带${}被错误替换Replace Tokens选项未关闭在免替换处用转义写法或者关闭Replace Tokens找不到Managed files入口用户权限不足 / 未启用文件夹级配置检查用户角色权限查看全局配置是否允许配置文件被反复修改但构建使用旧内容Jenkins使用了缓存或工作区残留清理工作区检查文件版本历史插件安装后Pipeline不识别configFileProvider插件未重启 / 版本不匹配安装后重启Jenkins升级插件版本在Docker容器内注入文件失败容器文件系统权限限制检查容器挂载路径权限使用volume持久化配置目录7. 我的一些使用体会和扩展建议用这个插件也有几年了说几个实实在在的体会。第一个体会是配置文件的命名和注释一定要规范。你可能觉得这根本不是技术问题但当你管理了上百个配置文件时准确的命名和注释能省下大把时间。我的建议是命名采用“用途-环境-类型”的格式比如“maven-settings-dev-xml”一眼就能看出是Maven开发环境的XML配置。第二个体会是尽量少在一个配置文件里堆太多内容一个配置文件负责一个功能。有人图省事把数据库配置、Redis配置、消息队列配置全塞到一个properties文件里然后用Token替换来控制不同环境。短期看是省事但等你的配置项超过20个时替换规则会变得非常复杂排错也难。更好的做法是拆成多个配置文件通过configFileProvider一次性注入多个文件每个文件职责单一维护起来清晰很多。第三个体会是这个插件和凭据管理Credentials搭配使用才是完整方案。Config File Provider负责文件层面的注入凭据负责敏感信息层面的存储两者配合才能做到既灵活又安全。比如你可以在配置文件中写入“${KEYSTORE_PASSWORD}”然后把KEYSTORE_PASSWORD存成Jenkins凭据在构建时通过withCredentials取出并替换。这样既不会有明文密码出现在配置文件里也能防止日志泄露。最后这个插件本身不限于构建Maven项目。它的思路通用性很强任何需要在构建、测试、部署阶段准备配置文件的场景都能套用这个模式。后面你可以再研究下和Ansible、Kubernetes、Docker Compose部署的配合把配置文件注入和部署编排结合起来能省掉不少手工运维的活。
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门