Jenkins调用Ansible-playbook无法访问Vault变量bh的问题排查
bh变量未定义的问题 看起来你遇到的核心问题是Ansible没能成功加载到加密文件bh_vault.yml里的变量,导致角色调用时找不到bh这个对象。咱们一步步拆解原因并修复:
问题根源
报错'bh' is undefined说明Playbook根本没加载到bh_vault.yml里的内容。最可能的原因是**stand变量没从Jenkins传递到Ansible**,导致vars_files里的路径inventories/{{ stand }}/bh_vault.yml解析错误,找不到加密文件,自然也就没有bh变量了。
具体修复步骤
1. 把Jenkins的环境变量传递给Ansible的stand变量
你的Jenkins任务里用了env.Stand指定inventory目录,但Playbook里加载变量文件依赖的是stand变量,这俩没关联起来。需要在ansiblePlaybook的extras参数里添加变量传递:
修改Jenkins的Groovy代码:
withCredentials([file(credentialsId: 'my_vault', variable: 'VAULT_TOKEN')]){ ansiblePlaybook( // 其他原有参数保持不变 playbook: 'clusterControl.yml', inventory: 'inventories/${env.Stand}/hosts', extras: " ${ansible_log_level} -e 'stand=${env.Stand}' --ssh-extra-args='-o StrictHostKeyChecking=no' --vault-password-file '${VAULT_TOKEN}'" ) }
关键就是加了-e 'stand=${env.Stand}',把Jenkins里的Stand环境变量赋值给Ansible的stand变量,这样vars_files才能正确找到对应目录下的bh_vault.yml。
2. 统一Playbook里的变量逻辑(可选但推荐)
你的Playbook里hosts用的是{{ domain | default('stand') }},但加载变量文件用的是{{ stand }},如果这俩变量本应是同一个值,建议统一起来避免混淆:
--- - hosts: "{{ domain | default('stand') }}" strategy: free gather_facts: no vars_files: # 改成和hosts一致的变量,避免路径解析错误 - "inventories/{{ domain | default('stand') }}/bh_vault.yml" roles: - { role: 03_clusterControl, when: ' "win" in (group_names | string) ' } - { role: 03_clusterControl_linux, when: ' "lin" in (group_names | string) ' }
3. 验证Vault解密是否正常(排除干扰)
虽然当前报错不是解密失败,但可以先手动确认一下:
在Jenkins服务器上,用凭证文件里的密码解密bh_vault.yml,看看内容能不能正常读取:
ansible-vault decrypt inventories/你的Stand值/bh_vault.yml --vault-password-file /path/to/VAULT_TOKEN文件
如果解密失败,说明Jenkins的my_vault凭证存储的密码文件有问题,需要检查凭证配置。
4. 检查角色里的变量引用
确保你的03_clusterControl和03_clusterControl_linux角色中,引用bh.ip、bh.username的方式没有拼写错误,比如角色的tasks文件里应该是:
- name: 示例任务 debug: msg: "目标服务器IP: {{ bh.ip }}"
变量名要和bh_vault.yml里的bh结构完全匹配。
验证修复
修改完成后重新运行Jenkins任务,只要stand变量正确传递,vars_files成功加载到加密文件,bh变量就能被正常识别,remote_user的报错也就消失了。
内容的提问来源于stack exchange,提问作者Stepan

