Jenkins + Ansible 集成实战:把配置管理焊进流水线里

Jenkins 和 Ansible 这俩工具,单拎出来大家都不陌生。但搁一块儿用的时候,很多人就犯迷糊了------插件怎么装?路径怎么配?Playbook 放哪?参数怎么传?

我先把环境这块说清楚,免得后面踩坑。咱们这套环境用的是 Ubuntu 24.04 LTS,别拿老版本 CentOS 来套,包管理器都不一样,踩坑了别来找我。

Ubuntu 24 上装 Ansible:

复制代码
# 更新源
sudo apt update

# 装Ansible,Ubuntu 24的仓库里自带,版本不算最新但够用
sudo apt install ansible -y

# 验证一下
ansible --version
# 输出类似:
# ansible [core 2.16.x]
#   config file = /etc/ansible/ansible.cfg
#   configured module search path = ['/home/jenkins/.ansible/plugins/modules', ...]
#   python version = 3.12.x

Ubuntu 24.04 自带 Python 3.12,Ansible 装完直接就能跑,不用折腾 Python 环境,这点比 CentOS 省心多了。如果你非要装最新版的 Ansible,可以用 pip 装:

复制代码
sudo apt install python3-pip -y
pip3 install ansible --break-system-packages

不过生产环境我一般不建议这么搞,--break-system-packages 这参数看着就心虚,用系统仓库的版本稳当些。

Jenkins 的安装:

Ubuntu 24 上装 Jenkins 也简单,但别直接 apt install jenkins,仓库里的版本可能比较旧。建议用官方源:

复制代码
# 先装JDK,Jenkins 2.4xx版本需要JDK 17+
sudo apt install openjdk-17-jdk -y

# 加Jenkins官方源
curl -fsSL https://pkg.jenkins.io/debian-stable/jenkins.io-2023.key | sudo tee /usr/share/keyrings/jenkins-keyring.asc > /dev/null
echo "deb [signed-by=/usr/share/keyrings/jenkins-keyring.asc] https://pkg.jenkins.io/debian-stable binary/" | sudo tee /etc/apt/sources.list.d/jenkins.list > /dev/null

# 装Jenkins
sudo apt update
sudo apt install jenkins -y

# 启动并设为开机自启
sudo systemctl enable --now jenkins

装完浏览器访问 http://你的IP:8080,按提示走初始化流程就行。

SSH 免密配置:

Jenkins 运行用户是 jenkins,你得确保这个用户能免密 SSH 到所有被管节点。不然 Playbook 一跑,全卡在输入密码那一步,直接超时挂掉。

复制代码
# 切到jenkins用户
sudo su - jenkins -s /bin/bash

# 生成密钥对,Ubuntu 24默认用ED25519了,比RSA快还安全
ssh-keygen -t ed25519 -N "" -f ~/.ssh/id_ed25519

# 把公钥推到目标机器
ssh-copy-id -i ~/.ssh/id_ed25519.pub deploy@192.168.1.100

这里有个坑,Ubuntu 24 的 ssh-copy-id 对 ED25519 密钥有时候会抽风,如果报错就手动把公钥内容追加到目标机器的 ~/.ssh/authorized_keys 里。还有,目标机器的 sshd_config 里确认 PubkeyAuthentication yes 是开着的,Ubuntu 24 默认是开的,但万一有人改过呢。

别嫌麻烦,这一步不做,后面全是白搭。

目标机器侧的底线要求:

Ansible 是无代理架构,不需要装客户端,但 Python 环境得有。Ubuntu 24 自带 Python 3.12,完全没问题。就怕那种用精简镜像起的容器或者云主机,Python 给阉割了,那 Ansible 的模块基本跑不起来,报错能让你怀疑人生。遇到这种情况,先 apt install python3 -y 补上再说。


🧩 插件安装:让 Jenkins 认识 Ansible


Jenkins 默认不认识 Ansible,得装插件。这步简单,但别跳过。

路径:管理 Jenkins插件管理可选插件

搜索 Ansible,你会看到几个相关的插件,装这个就行:

Ansible plugin --- 这是官方维护的,功能最全

装完之后重启 Jenkins。Ubuntu 24 上可以用 sudo systemctl restart jenkins,也可以在插件管理页面点"安装完成后重启并等待",影响范围小一些。

重启完了,怎么验证插件装好了?进 管理 JenkinsGlobal Tool Configuration,滑到最下面,如果出现了 Ansible 的配置区域,就说明插件生效了。


⚙️ 全局工具配置:告诉 Jenkins Ansible 在哪


这一步很多人卡住。插件装了,但 Jenkins 不知道 Ansible 装在哪个目录下,调用的时候就会报 ansible: command not found

管理 JenkinsGlobal Tool Configuration,找到 Ansible 区域:

  • 名称 :随便起,建议带版本号,比如 ansible-ubuntu24,后面 Pipeline 里引用的时候好区分

  • 路径:填 Ansible 的可执行文件所在目录

怎么找这个路径?

复制代码
which ansible
# Ubuntu 24上一般输出:/usr/bin/ansible

那路径就填 /usr/bin,注意是目录,不是文件本身。

如果你服务器上装了多个版本的 Ansible(比如用 virtualenv 隔离的),这里可以添加多个,名字区分开就行。Ubuntu 24 上用 python3 -m venv 创建虚拟环境很方便:

复制代码
python3 -m venv /opt/ansible-venv
source /opt/ansible-venv/bin/activate
pip install ansible==2.16.0
deactivate

这种情况下路径就填 /opt/ansible-venv/bin,Jenkins 会在这个虚拟环境里找 ansible。


📁 项目结构:Playbook 别乱扔


在正式创建 Job 之前,先说个事儿------Playbook 文件放哪。

我见过最离谱的做法,是直接把 Playbook 扔在 Jenkins 服务器的 /opt/ansible 目录下,改了也没记录,谁改的不知道,改了啥不知道。出了问题,几个人面面相觑。

正确做法:Playbook 进 Git 仓库。

推荐的项目结构长这样:

复制代码
ansible-config-repo/
├── inventory/
│   ├── dev.ini
│   ├── staging.ini
│   └── prod.ini
├── group_vars/
│   ├── dev.yml
│   ├── staging.yml
│   └── prod.yml
├── playbooks/
│   ├── init-env.yml
│   ├── deploy-app.yml
│   └── rotate-logs.yml
├── roles/
│   ├── common/
│   ├── nginx/
│   └── java/
├── ansible.cfg
└── Jenkinsfile

这样做的好处太多了。版本可追溯,变更可回滚,多人协作不冲突,Jenkins 拉代码的时候一把全带上。这就是配置即代码的思路,别嫌麻烦,后面你会感谢自己的。

顺便说一句,ansible.cfg 建议放仓库根目录,Ansible 会自动优先读取当前目录下的配置文件。内容大概这样:

复制代码
[defaults]
inventory = inventory/prod.ini
host_key_checking = False
forks = 20
timeout = 30
log_path = /var/log/ansible.log

[privilege_escalation]
become = True
become_method = sudo

Ubuntu 24 上 sudo 默认需要密码,如果你配了免密 sudo 就不用管,没配的话后面 Jenkins 调用的时候得加 --become-password-file 参数。


🏗️ 自由风格项目:先跑通再说


新建一个自由风格项目,名字就叫 ansible-config-deploy 吧。

源码管理 选 Git,填你的 Playbook 仓库地址,分支填 main 或者 master,看你仓库默认分支叫啥。

构建环境 里勾选 "Provide Configuration files"(如果你有 ansible.cfg 需要注入的话),一般不用勾,因为 ansible.cfg 已经在仓库里了。

构建 部分,这是核心。点"增加构建步骤",选 Invoke Ansible Playbook

配置项 填什么 说明
Ansible installation ansible-ubuntu24 选你全局配置里起的名字
Playbook path playbooks/deploy-app.yml 相对于仓库根目录
Inventory 选择"File or host list",填 inventory/prod.ini 也可以选"Inline content"直接写
Credentials 选你配置的 SSH 私钥 用于连接目标机器
Extra parameters -v --diff 看详细输出和变更差异

这里有个细节,Credentials 那栏,你得提前在 Jenkins 的凭据管理里添加一个 SSH Username with private key 类型的凭据,把 jenkins 用户的私钥导进去。Ubuntu 24 上如果你用的是 ED25519 密钥,Jenkins 插件是支持的,没问题。

点保存,然后点"立即构建"。如果一切配置正确,控制台输出里你会看到 Ansible 的标准输出,绿色的 okchanged,那叫一个舒坦。


🔥 Pipeline 才是正道:代码化你的配置流程


自由风格项目能跑通,但不够灵活。真正在生产环境用,还得是 Pipeline。Pipeline 可以把整个流程写进 Jenkinsfile,跟着代码走,版本可控,参数化也更方便。

下面这个 Jenkinsfile 是我实际在用的,精简了一下,核心逻辑都在:

复制代码
pipeline {
    agent any
  
    parameters {
        choice(name: 'ENV', choices: ['dev', 'staging', 'prod'], description: '目标环境')
        string(name: 'VERSION', defaultValue: 'latest', description: '部署版本号')
        choice(name: 'TAGS', choices: ['all', 'deploy', 'config', 'restart'], description: '执行标签')
        booleanParam(name: 'DRY_RUN', defaultValue: false, description: '是否试运行')
    }
  
    environment {
        ANSIBLE_DIR = "ansible-config-repo"
    }
  
    stages {
        stage('拉取 Playbook 仓库') {
            steps {
                git branch: 'main', url: 'https://your-repo/ansible-config-repo.git'
            }
        }
      
        stage('语法检查') {
            steps {
                sh """
                    cd ${ANSIBLE_DIR}
                    ansible-playbook playbooks/deploy-app.yml \
                        --syntax-check \
                        --inventory inventory/${params.ENV}.ini
                """
            }
        }
      
        stage('执行 Playbook') {
            steps {
                script {
                    def extraArgs = ""
                    if (params.TAGS != 'all') {
                        extraArgs += " --tags ${params.TAGS}"
                    }
                    if (params.DRY_RUN) {
                        extraArgs += " --check --diff"
                    }
                  
                    ansiblePlaybook(
                        playbook: "${ANSIBLE_DIR}/playbooks/deploy-app.yml",
                        inventory: "${ANSIBLE_DIR}/inventory/${params.ENV}.ini",
                        extraVars: [
                            env: "${params.ENV}",
                            version: "${params.VERSION}"
                        ],
                        extraArgs: extraArgs,
                        colorized: true
                    )
                }
            }
        }
      
        stage('执行结果通知') {
            steps {
                script {
                    echo "部署完成,环境:${params.ENV},版本:${params.VERSION}"
                }
            }
        }
    }
  
    post {
        failure {
            echo "❌ Playbook 执行失败,请检查日志!"
        }
    }
}

逐个说几个关键点:

参数化构建 是精髓。ENV 控制目标环境,VERSION 控制部署版本,TAGS 控制跑哪些任务,DRY_RUN 是试运行开关。这样一套 Pipeline,开发测试生产环境都能用,不用建三个 Job。

语法检查 那个 stage 别删。这是保险绳,Playbook 语法有问题,在测试环境就拦住了,不至于跑到生产环境才报错。虽然 --syntax-check 只检查语法不检查逻辑,但总比没有强。

extraVars 是 Jenkins 和 Ansible 之间传参的桥梁。Jenkins 这边的参数,通过 extraVars 注入到 Ansible 的变量里,Playbook 里直接用 {``{ env }}{``{ version }} 引用就行,非常丝滑。

DRY_RUN 这个参数强烈建议加上。--check --diff 组合拳,不会真正修改目标机器,但会告诉你"如果真跑了,会改成什么样"。生产环境部署前先跑一次 DRY_RUN,心里有底。


🧨 踩坑实录:这些坑我替你踩过了


坑一:Jenkins 用户找不到 ansible 命令

明明命令行手动跑没问题,Jenkins 里一跑就报 ansible: command not found。这是因为 Ubuntu 24 上 Jenkins 服务的环境变量和你登录 shell 的环境变量不一样。Jenkins 服务是通过 systemd 启动的,它不会读你的 .bashrc

解决办法有两个。一是在 Global Tool Configuration 里把路径配对,Jenkins 插件会自动处理 PATH。二是如果用的是 Pipeline 的 sh 方式调用,在 Jenkinsfile 里手动加 PATH:

复制代码
environment {
    PATH = "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:${env.PATH}"
}

如果你是用 virtualenv 装的 Ansible,PATH 里还得加上虚拟环境的 bin 目录。

坑二:SSH 连接超时

Ansible 默认的 SSH 超时时间挺短的,目标机器如果响应慢(比如在跑高负载任务),就会超时断开。

ansible.cfg 里加上:

复制代码
[ssh_connection]
timeout = 30
ssh_args = -o ControlMaster=auto -o ControlPersist=60s -o StrictHostKeyChecking=no

ControlPersist 是 SSH 多路复用,连一次之后保持连接 60 秒,后续任务复用这个通道,速度能快不少。Ubuntu 24 的 OpenSSH 版本是 9.6,对 ControlPersist 支持很好,放心用。StrictHostKeyChecking=no 是防止首次连接时卡在确认指纹那一步,测试环境用没问题,生产环境慎用。

坑三:大批量执行时 Ansible 卡死

如果你 Inventory 里有几百台机器,Ansible 默认是分批执行的,但 fork 数默认只有 5。几百台机器排着队跑,那得跑到猴年马月。

ansible.cfg

复制代码
[defaults]
forks = 50

具体设多少看你的 Jenkins 服务器配置和目标机器数量,别设太大,把网络和系统资源撑爆了。Ubuntu 24 默认的文件描述符限制是 1024,几百台机器并发连接可能会撞上这个限制,跑之前 ulimit -n 65535 调一下,或者改 /etc/security/limits.conf 永久生效。

坑四:Playbook 里用了 sudo 但没配免密

Ansible 需要 sudo 权限执行某些任务,但目标机器的 sudo 需要输密码。Ubuntu 24 上这个问题更常见,因为 Ubuntu 默认就是用 sudo 而不是 root 登录的。

两种解法:

一是在目标机器的 /etc/sudoers.d/ 下给部署用户加免密:

复制代码
# 在目标机器上执行
echo "deploy ALL=(ALL) NOPASSWD: ALL" | sudo tee /etc/sudoers.d/deploy
sudo chmod 440 /etc/sudoers.d/deploy

/etc/sudoers.d/ 目录管理比直接改 /etc/sudoers 安全,不会把主配置文件搞乱。

二是在 Jenkins 的 Ansible 调用里加上 --become--become-password-file 参数,指向一个存了 sudo 密码的文件。生产环境推荐第一种,安全一点的做法是用 Ansible 的 become 配合 sudo 免密。

坑五:Ubuntu 24 的 cgroup v2 导致某些 Ansible 模块异常

这个坑比较隐蔽。Ubuntu 24 默认用 cgroup v2,如果你用 Ansible 的 docker_container 模块管理容器,某些旧版本的 Docker 不兼容 cgroup v2,会导致模块执行失败。解决办法要么升级 Docker 到兼容版本,要么在 grub 里加启动参数切回 cgroup v1。不过这属于 Docker 的问题,跟 Ansible 本身关系不大,遇到了别往 Ansible 身上甩锅。


🛡️ 生产环境的几条铁律


Playbook 必须走 Git。 前面说过,不重复了。谁改了什么,什么时候改的,一键可查。出了事能回滚,比什么都重要。

测试环境验证完再上生产。 听起来是废话,但真正做到的团队没几个。我现在的做法是,Jenkins 里配两个 Job,一个跑 staging,一个跑 prod,prod 的 Job 加一个人工审批环节,必须点确认才往下走。多这一步,能挡住 80% 的低级错误。

敏感信息用 Ansible Vault 管。 数据库密码、API Key 这些东西,别明文写在 Playbook 里。用 ansible-vault encrypt 加密,Jenkins 调用的时候通过 --vault-password-file 传入解密密码。解密密码本身存在 Jenkins 的凭据管理里,别写死在 Jenkinsfile 上。

Ubuntu 24 上用 ansible-vault 没什么特别的,命令都一样:

复制代码
# 加密敏感变量文件
ansible-vault encrypt group_vars/prod/vault.yml

# 编辑加密文件(会提示输入密码)
ansible-vault edit group_vars/prod/vault.yml

Jenkins Pipeline 里调用的时候,把 vault 密码存成一个文件,路径传给 ansiblePlaybookvaultCredentialsId 参数,让它从 Jenkins 凭据里取密码,安全又方便。

定期清理过期的 Inventory。 机器下线了但 Inventory 里还留着,Ansible 跑到一半连不上,整个 Playbook 就挂了。养成习惯,机器下线同步更新 Inventory,或者用动态 Inventory(比如从 CMDB 或者云 API 自动拉取机器列表),省心很多。Ubuntu 24 上跑动态 Inventory 脚本没问题,Python 3.12 兼容性很好。


📝 总结


Jenkins 和 Ansible 的集成,说白了就是让 Jenkins 当调度中心,Ansible 当执行引擎。Jenkins 负责触发时机、参数管理、流程编排、结果通知;Ansible 负责在目标机器上干活。各司其职,配合默契。

核心步骤就四步:装插件 → 配路径 → 写 Playbook 进 Git → 建 Pipeline 跑起来。听着简单,但每一步都有细节容易翻车。Ubuntu 24 上环境变量、SSH 免密、sudo 权限、cgroup 兼容性,这些小问题叠加起来,够你折腾一整天的。

自动化配置管理这事儿,早做早享受。别等到半夜被报警叫起来,才发现手动运维的苦。把重复的活交给机器,把时间留给更有价值的事情,这才是运维该有的样子。

相关推荐
Avan_菜菜13 小时前
FRP 内网穿透完整实战:从 HTTP 映射到 HTTPS 自签代理
运维·nginx·https
SelectDB2 天前
Litefuse 开源并推出单进程轻量模式,25 秒就能跑起来的 Agent 可观测与评估平台
运维·后端·自动化运维
XIAOHEZIcode3 天前
Linux系统鼠标偏移常见原因以及修复方案
linux·运维·游戏
用户0328472220704 天前
如何搭建本地yum源(上)
运维
大树887 天前
金刚石散热越强,管路越先见顶
大数据·运维·服务器·人工智能·ai
摇滚侠7 天前
Linux CentOS7 rpm 安装 MySQL 5.7
linux·运维·mysql
霸道流氓气质7 天前
领域驱动设计(DDD)在 Spring Boot 微服务中的实践指南
运维·spring boot·微服务
Inhand陈工7 天前
基于台达PLC与映翰通IG502的智慧水产养殖精准投喂与远程运维解决方案
运维·人工智能·物联网·阿里云·信息与通信
酣大智7 天前
ARP代理--工作原理
运维·网络·arp·arp代理
shushangyun_7 天前
2026年快消品B2B系统推荐:支持终端门店订货、促销政策自动化的工具?
java·运维·网络·数据库·人工智能·spring·自动化