如何在Jenkins脚本化流水线中启动已注册的EC2节点代理?
解决方案
以下是实现你需求的Jenkins声明式流水线方案,核心通过AWS CLI管控EC2实例生命周期,结合SSH与Jenkins内部机制确保代理上线后执行构建:
前置准备
- 在Jenkins凭证管理中配置AWS密钥对(需具备
ec2:StartInstances、ec2:StopInstances、ec2:DescribeInstances权限) - 配置EC2实例的SSH密钥为Jenkins SSH凭证(类型选"SSH Username with private key")
- 提前在EC2实例中放置Jenkins代理jar包(
agent.jar),或准备好下载脚本;同时从Jenkins节点配置页获取该节点的JNLP连接密钥 - 确保Jenkins服务器能访问EC2实例的SSH端口(22)及Jenkins代理通信端口
流水线代码示例
pipeline { agent any environment { EC2_INSTANCE_ID = 'i-xxxxxxxxx' // 替换为你的EC2实例ID JENKINS_NODE_NAME = 'your-ec2-node' // 替换为已注册的Jenkins节点名 JENKINS_URL = 'http://your-jenkins-server:8080' // 替换为你的Jenkins地址 AGENT_SECRET = 'xxxxxxxxx' // 替换为节点的JNLP密钥 AGENT_WORKDIR = '/var/lib/jenkins/agent' // 替换为代理工作目录 } stages { stage('启动EC2实例') { steps { withCredentials([aws(credentialsId: 'aws-credentials', accessKeyVariable: 'AWS_ACCESS_KEY_ID', secretKeyVariable: 'AWS_SECRET_ACCESS_KEY')]) { // 启动实例 sh 'aws ec2 start-instances --instance-ids ${EC2_INSTANCE_ID}' // 等待实例进入running状态 sh 'aws ec2 wait instance-running --instance-ids ${EC2_INSTANCE_ID}' // 获取实例公网IP(用私网IP的话,替换为PrivateIpAddress) script { EC2_PUBLIC_IP = sh( script: "aws ec2 describe-instances --instance-ids ${EC2_INSTANCE_ID} --query 'Reservations[0].Instances[0].PublicIpAddress' --output text", returnStdout: true ).trim() } // 等待SSH端口就绪 sh "until nc -z ${EC2_PUBLIC_IP} 22; do echo '等待SSH端口就绪...'; sleep 10; done" } } } stage('启动Jenkins代理') { steps { sshagent(['ec2-ssh-key']) { // 替换为你的SSH凭证ID // 远程启动代理(若agent.jar未提前放置,可先加wget ${JENKINS_URL}/jnlpJars/agent.jar命令) sh """ ssh -o StrictHostKeyChecking=no ec2-user@${EC2_PUBLIC_IP} \ 'nohup java -jar agent.jar -jnlpUrl ${JENKINS_URL}/computer/${JENKINS_NODE_NAME}/slave-agent.jnlp -secret ${AGENT_SECRET} -workDir "${AGENT_WORKDIR}" > agent.log 2>&1 &' """ } // 等待节点上线 waitUntil { script { def node = Jenkins.instance.getNode(JENKINS_NODE_NAME) return node != null && node.toComputer().isOnline() } } echo "Jenkins代理 ${JENKINS_NODE_NAME} 已上线" } } stage('执行构建步骤') { agent { node { label JENKINS_NODE_NAME } } steps { echo "在节点 ${JENKINS_NODE_NAME} 上执行构建..." // 此处添加你的具体构建命令,例如: // sh 'mvn clean package' // sh 'docker build -t my-app:latest .' } } } post { always { // 无论构建成败,均停止EC2实例 withCredentials([aws(credentialsId: 'aws-credentials', accessKeyVariable: 'AWS_ACCESS_KEY_ID', secretKeyVariable: 'AWS_SECRET_ACCESS_KEY')]) { sh 'aws ec2 stop-instances --instance-ids ${EC2_INSTANCE_ID}' echo "EC2实例 ${EC2_INSTANCE_ID} 已停止" } } } }
关键细节说明
- 实例就绪校验:用
aws ec2 wait确保实例启动完成,再通过nc检查SSH端口,避免提前执行远程命令失败 - 代理后台运行:用
nohup让代理脱离SSH会话在后台运行,防止连接断开后代理终止 - 节点状态检查:直接调用Jenkins内部API查询节点在线状态,比轮询日志更高效可靠
- 资源兜底回收:
post块的always阶段保证实例无论构建结果如何都会停止,避免闲置资源浪费
内容的提问来源于stack exchange,提问作者howsmydriving42
相关产品推荐
相关产品推荐

