自动化部署、通知、分布式构建与并行构建(jenkins pipeline)
jenkins与ansible集成
简单案例
pipeline { agent any stages { stage('deploy') { steps { ansiblePlaybook( playbook: "${env.WORKSPACE}/playbook.yml", inventory: "${env.WORKSPACE}/hosts", credentialsId: 'vagrant' ) } } } }
应该需要在Jenkins上安装一下
[root@mcw15 plugins]# yum install -y ansible
打开配置
[root@mcw15 plugins]# vim /etc/ansible/ansible.cfg [root@mcw15 plugins]# grep host_key_checking /etc/ansible/ansible.cfg host_key_checking = False [root@mcw15 plugins]#
也可以添加工具,添加不同的ansible版本,然后不同的项目用不同的ansible
不通:
[root@mcw15 mcwansible]# [root@mcw15 mcwansible]# ansible -i hosts example -m ping 10.0.0.13 | UNREACHABLE! => { "changed": false, "msg": "Failed to connect to the host via ssh: Permission denied (publickey,password).", "unreachable": true } [root@mcw15 mcwansible]#
分发公钥
[root@mcw15 mcwansible]# ssh-copy-id -i /root/.ssh/id_rsa.pub 10.0.0.13 /usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "/root/.ssh/id_rsa.pub" /usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed /usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keys root@10.0.0.13's password: Number of key(s) added: 1 Now try logging into the machine, with: "ssh '10.0.0.13'" and check to make sure that only the key(s) you wanted were added. [root@mcw15 mcwansible]# ls fenfa.sh hosts [root@mcw15 mcwansible]# cat hosts [example] 10.0.0.13 [root@mcw15 mcwansible]# ansible -i hosts example -m ping 10.0.0.13 | SUCCESS => { "ansible_facts": { "discovered_interpreter_python": "/usr/bin/python" }, "changed": false, "ping": "pong" } [root@mcw15 mcwansible]#
example2的先不让通
[root@mcw15 mcwansible]# vim hosts [root@mcw15 mcwansible]# cat hosts [example] 10.0.0.13 [example2] 10.0.0.22 [root@mcw15 mcwansible]# ansible -i hosts example2 -m ping 10.0.0.22 | UNREACHABLE! => { "changed": false, "msg": "Failed to connect to the host via ssh: Warning: Permanently added '10.0.0.22' (ECDSA) to the list of known hosts.\r\nPermission denied (publickey,password).", "unreachable": true } [root@mcw15 mcwansible]#
加个root作为凭证
暂时用这个项目做pipeline吧
新增两个文件
hosts
[example] 10.0.0.13 [example2] 10.0.0.22
playbook.yml
- hosts: example2 tasks: - debug: msg="{{ lookup('env','BUILD_TAG') }}"
Jenkins file
pipeline { agent any stages { stage('deploy') { steps { ansiblePlaybook( playbook: "${env.WORKSPACE}/playbook.yml", inventory: "${env.WORKSPACE}/hosts", credentialsId: 'vagrant' ) } } } }
手动触发构建,失败
没这个步骤,步骤列表可以看到没有这个,现在有了docker了,之前安装了插件之后
java.lang.NoSuchMethodError: No such DSL method 'ansiblePlaybook' found among steps [
安装ansible插件:https://plugins.jenkins.io/ansible
安装之后,重新构建。报错,权限。可能是我们在Jenkins上加的凭证vagrant没有起到效果吧
把2去掉,用example,这个已经用密钥做了免密登录的
构建结果一样
此时在机器上是正常执行命令的
好吧,凭证填写了但是没有确定
新增之后再次触发
这次可以看到,已经成功了
并且从在yml中用lookup获取到了Jenkins任务运行的环境变量
此时改为example2,这个机器和Jenkins本身没有免密,执行命令的时候也会出现权限问题。看这里通过Jenkins凭证,是否可以正常执行
可以看到,example2的也正常可以运行剧本
另外的案例
Jenkinsfile
pipeline { agent any stages { stage('Syntax check ansible playbook') { steps { ansiblePlaybook( disableHostKeyChecking: true, playbook: "${env.WORKSPACE}/playbook.yml", inventory: "${env.WORKSPACE}/hosts", credentialsId: 'vagrant', extras: '--syntax-check' ) } } stage('deploy') { steps { ansiblePlaybook( disableHostKeyChecking: true, playbook: "${env.WORKSPACE}/playbook.yml", inventory: "${env.WORKSPACE}/hosts", credentialsId: 'vagrant', // skippedTags: 'debugtag', forks: 2, limit: 'example,example2', tags: 'debugtag,testtag', extraVars: [ login: 'mylogin', secret_key: [value: 'g4dfKWENpeF6pY05', hidden: true] ] // startAtTask: 'task4' ) } } } }
host
[example] 10.0.0.13 [example2] 10.0.0.22
playbook.yml
- hosts: example2 tasks: - debug: msg="{{ lookup('env','BUILD_TAG') }}"
手动触发构建,任务执行成功
不过查看,只执行了example2,没有执行example的,不过这符合正常,因为我们在剧本里写死了是example2的主机运行
ansibleVault步骤
不同资产不同的ansible登录方式
指定这个机器 用这个machangwei用户和密码
10.0.0.22
ansible_ssh_user: machangwei ansible_become_method: sudo ansible_ssh_pass: 123456
hosts
[example] 10.0.0.13 [example2] 10.0.0.22
playbook.yml
- hosts: example2 tasks: - debug: msg="{{ lookup('env','BUILD_TAG') }}"
jenkinsfile,
检查的时候用Jenkins凭证,但是执行的时候用的是host_vars里面的machangwei用户了,如果密码有问题,那么执行的时候会报错了
pipeline { agent any stages { stage('Syntax check ansible playbook') { steps { ansiblePlaybook( disableHostKeyChecking: true, playbook: "${env.WORKSPACE}/playbook.yml", inventory: "${env.WORKSPACE}/hosts", credentialsId: 'vagrant', extras: '--syntax-check' ) } } stage('deploy') { steps { ansiblePlaybook( disableHostKeyChecking: true, playbook: "${env.WORKSPACE}/playbook.yml", inventory: "${env.WORKSPACE}/hosts", // credentialsId: 'vagrant', // skippedTags: 'debugtag', forks: 2, // limit: 'example,example2', // tags: 'debugtag,testtag', // extraVars: [ // login: 'mylogin', // secret_key: [value: 'g4dfKWENpeF6pY05', hidden: true] // ] // startAtTask: 'task4' ) } } } }
点击构建,查看检查的时候,是Jenkins凭证,用的root检查的语法。然后执行的时候,没有指定用户,也就是用的host_vars里面的machangwei用户成功运行了,sudo运行的,并且两个机器上都有machangwei系统用户,都是有sudo权限的。
我们这里想要验证下,的确是用的host_vars里面的machangwei用户,可以将里面的密码从123456改为1234567,如果构建数字54失败,报权限错误,那么的确是符合预期的。也就是我们可以根据不同的主机,进行不同的登录方式
结果就是我们想的那样,报错无效的密码,权限拒绝了。
通知
邮箱配置和邮件通知
pipeline { agent any stages { stage('Syntax check ansible playbook') { steps { ansiblePlaybook( disableHostKeyChecking: true, playbook: "${env.WORKSPACE}/playbook.yml", inventory: "${env.WORKSPACE}/hosts", credentialsId: 'vagrant', extras: '--syntax-check' ) } } stage('deploy') { steps { ansiblePlaybook( disableHostKeyChecking: true, playbook: "${env.WORKSPACE}/playbook.yml", inventory: "${env.WORKSPACE}/hosts", // credentialsId: 'vagrant', // skippedTags: 'debugtag', forks: 2, // limit: 'example,example2', // tags: 'debugtag,testtag', // extraVars: [ // login: 'mylogin', // secret_key: [value: 'g4dfKWENpeF6pY05', hidden: true] // ] // startAtTask: 'task4' ) } } } post { failure { mail body: 'failure body', from: '1xxx32@163.com', to: '8xx15@qq.com',subject: 'build status :(' } } }
报错,没有安装邮件的插件Mailer Plugin吗?
查看是安装了的
这次没有报错了,按照上面的例子,
先测试一下,发给下面的测试接收邮箱
提示发送成功,但是却没看到发送以及接收邮件,先不管了,先保存一下
修改添加邮件发送
虽然部署阶段失败,但是post发送邮件这里显示成功的
查看日志输出,执行了post了。但是并没有看到邮件的发出和接收
重新做下系统配置,配置邮箱
注意,之前没有填写smtp服务器,是不行的。得填写,并且密码不是平时登录邮箱的密码,而是授权码。
授权码是用于登录第三方邮件客户端的专用密码。
上面再次点击测试,可以看到已经发送并接收到了邮件
此时再次点击构建,部署失败,就会执行post里失败发送邮件的部分
失败日志
对比pipeline配置,查看邮件内容,发现没有发送邮件,检查了下,刚刚改造邮箱的系统配置后,没有保存。保存一下,重新点击立即构建,然后可以看到发送构建失败的邮件了
对比查看
使用Email Extension 插件发送通知
安装 Emai Extension 插件: https://plugins.jenkins.io/email-ext
使用这个
配置
把之前配置的邮件通知的清空
修改,然后立即构建
报错:
加个凭证,我们上面没有加邮箱的账号密码
失败,不知道咋弄,有时间再研究吧
pipeline { agent any stages { stage('Syntax check ansible playbook') { steps { ansiblePlaybook( disableHostKeyChecking: true, playbook: "${env.WORKSPACE}/playbook.yml", inventory: "${env.WORKSPACE}/hosts", credentialsId: 'vagrant', extras: '--syntax-check' ) } } stage('deploy') { steps { ansiblePlaybook( disableHostKeyChecking: true, playbook: "${env.WORKSPACE}/playbook.yml", inventory: "${env.WORKSPACE}/hosts", // credentialsId: 'vagrant', // skippedTags: 'debugtag', forks: 2, // limit: 'example,example2', // tags: 'debugtag,testtag', // extraVars: [ // login: 'mylogin', // secret_key: [value: 'g4dfKWENpeF6pY05', hidden: true] // ] // startAtTask: 'task4' ) } } } post { failure { emailext body: """<p>EXECUTED: job <b>\'${env.JOB_NAME}:${env.BUILD_NUMBER}\' </b></p><p>View console output at "<a href="${env.BUILD_URL}"> ${env.JOB_NAME}:${env.BUILD_NUMBER}</a>"</p> <p><i>(Build log is attached)</i></p>""", compressLog: true, attachLog: true, recipientProviders: [culprits(), developers(), requestor(),brokenBuildSuspects()], replyTo: '1xx2@163.com', subject: "Status: ${currentBuild.result?:'SUCCESS'} - Job \'${env.JOB_NAME}:${env.BUILD_NUMBER}\'", to: "13xx2@163.com" } } }
钉钉通知
参考:https://blog.csdn.net/qq_42259469/article/details/136813262
pipeline { agent any stages { stage('Syntax check ansible playbook') { steps { ansiblePlaybook( disableHostKeyChecking: true, playbook: "${env.WORKSPACE}/playbook.yml", inventory: "${env.WORKSPACE}/hosts", credentialsId: 'vagrant', extras: '--syntax-check' ) } } stage('deploy') { steps { ansiblePlaybook( disableHostKeyChecking: true, playbook: "${env.WORKSPACE}/playbook.yml", inventory: "${env.WORKSPACE}/hosts", // credentialsId: 'vagrant', // skippedTags: 'debugtag', forks: 2, // limit: 'example,example2', // tags: 'debugtag,testtag', // extraVars: [ // login: 'mylogin', // secret_key: [value: 'g4dfKWENpeF6pY05', hidden: true] // ] // startAtTask: 'task4' ) } } } post { failure { dingtalk( robot: 'Jenkins-Dingding', type:'MARKDOWN', title: "success: ${JOB_NAME}", text: ["- 失败构建:${JOB_NAME}项目!\n- 持续时间:${currentBuild.durationString}\n- 任务:#${JOB_NAME}\n- 请注意: @庞xx,@史xx 需要检查构建失败原因"], ) } } }
钉钉插件:dingding-notifications
配置一下
加密用的是钉钉里的加签
pipeline这里只需要改 robot: 'Jenkins-Dingding',这里,用Jenkins系统配置里的id
构建失败
执行失败钉钉通知
发出通知
通知消息,多加了一行让谁注意,只是文本,没有@通知的能力
HTTP请求通知
我们先写一个第三方系统
from flask import Flask, render_template, send_file, session,request import json app=Flask(__name__,template_folder='./') app.debug=True @app.route("/",methods=["GET","POST"]) def index(): if request.method == "POST": print(request.headers) print(request.data) return 'ok' return render_template('index.html') if __name__ == '__main__': app.run("0.0.0.0",9527)
开启并访问项目
提交请求
安装插件
开启项目
修改Jenkinsfile。我们这里第三方系统,没有认证,所以这里就忽略认证这一步了,也就是注释了authentication
pipeline { agent any stages { stage('Syntax check ansible playbook') { steps { ansiblePlaybook( disableHostKeyChecking: true, playbook: "${env.WORKSPACE}/playbook.yml", inventory: "${env.WORKSPACE}/hosts", credentialsId: 'vagrant', extras: '--syntax-check' ) } } stage('deploy') { steps { ansiblePlaybook( disableHostKeyChecking: true, playbook: "${env.WORKSPACE}/playbook.yml", inventory: "${env.WORKSPACE}/hosts", // credentialsId: 'vagrant', // skippedTags: 'debugtag', forks: 2, // limit: 'example,example2', // tags: 'debugtag,testtag', // extraVars: [ // login: 'mylogin', // secret_key: [value: 'g4dfKWENpeF6pY05', hidden: true] // ] // startAtTask: 'task4' ) } } } post { failure { script{ def response = httpRequest(url:'http://192.168.0.106:9527/',acceptType:"APPLICATION_JSON", contentType:"APPLICATION_JSON", httpMode: "POST", // authentication: "http_request", customHeaders:[ [name: "headername", value:"headerValue"], [name: "token",value:"secret", maskValue: true] ], requestBody:"{'buildNumber':'${env.BUILD_NUMBER}'}", timeout: 5, validResponseCodes: "200:302") echo "${response.status}" echo "${response.content}" } } } }
点击立即构建
查看日志,pipeline里面已经开启了请求,并且一直卡在这里不动
查看第三方系统的服务端,可以看到,已经接收并处理了pipeline发起的请求通知,并且包含了token和headername两个自定义请求头,以及我们发送过去的内容,也就是Jenkins的构建数字。
从服务端的记录时间看,18分收到请求,但是过了快十分钟了,pipeline对第三方系统发起请求之后,这里卡住一直不往下进行,没有去结束pipeline了,这不知道啥情况
因为上一个构建没有停止,这下一个构建,还在等待可用的执行器,也就是资源还没释放
只是前两个一直没取消成功
一开始卡住的时候没看到这个终止,现在出现 了,那就终止一下
也可以把它从post里面改到stage里面
执行ansible之前,就执行这里并卡柱了,这个构建数字是85
查看服务端已经处理了请求
分布式构建 与并行构建
通过JNLP协议增加agent
指定端口
跟书中例子不同,协议少了很多项
agent连接master的方式
登录到Jenkinsagent机器。我们这里用mcw12,执行上面的增加agent的命令,也就是下载jar包并启动。我们先用unix并且不用密码的
连接之后,就卡在这里,是前台运行,后面可以改成后台运行
再次回到Jenkins node列表,可以看到node1有信息了,应该从之前没信息的不可用,变为可用节点了
crt c 终止前台运行
查看node1情况,又是不可用节点了
点进去看状态提示,连接中断
查看日志,连接成功以及连接中断都有记录
查看负载情况
Jenkins agent机器上查看信息,以及日志
^C[root@mcw12 jenkinsagent]# ls agent.jar secret-file [root@mcw12 jenkinsagent]# ls /app/ remoting [root@mcw12 jenkinsagent]# ls /app/remoting/ jarCache logs [root@mcw12 jenkinsagent]# ls /app/remoting/jarCache/ 0F 1D 34 7F AD B2 CE DC EF [root@mcw12 jenkinsagent]# ls /app/remoting/logs/ remoting.log.0 [root@mcw12 jenkinsagent]# less /app/remoting/logs/remoting.log.0 [root@mcw12 jenkinsagent]# [root@mcw12 jenkinsagent]# cat /app/remoting/logs/remoting.log.0 Aug 24, 2024 2:01:56 PM hudson.remoting.Launcher createEngine INFO: Setting up agent: node1 Aug 24, 2024 2:01:56 PM hudson.remoting.Engine startEngine INFO: Using Remoting version: 3198.v03a_401881f3e Aug 24, 2024 2:01:56 PM org.jenkinsci.remoting.engine.WorkDirManager initializeWorkDir INFO: Using /app/remoting as a remoting work directory Aug 24, 2024 2:01:56 PM hudson.remoting.Launcher$CuiListener status INFO: Locating server among [http://10.0.0.25:8080/] Aug 24, 2024 2:01:57 PM org.jenkinsci.remoting.engine.JnlpAgentEndpointResolver resolve INFO: Remoting server accepts the following protocols: [JNLP4-connect, Ping] Aug 24, 2024 2:01:57 PM hudson.remoting.Launcher$CuiListener status INFO: Agent discovery successful Agent address: 10.0.0.25 Agent port: 9812 Identity: 52:34:14:5f:aa:87:d8:d8:c9:a3:23:e7:32:15:da:d8 Aug 24, 2024 2:01:57 PM hudson.remoting.Launcher$CuiListener status INFO: Handshaking Aug 24, 2024 2:01:57 PM hudson.remoting.Launcher$CuiListener status INFO: Connecting to 10.0.0.25:9812 Aug 24, 2024 2:01:57 PM hudson.remoting.Launcher$CuiListener status INFO: Server reports protocol JNLP4-connect-proxy not supported, skipping Aug 24, 2024 2:01:57 PM hudson.remoting.Launcher$CuiListener status INFO: Trying protocol: JNLP4-connect Aug 24, 2024 2:01:57 PM org.jenkinsci.remoting.protocol.impl.BIONetworkLayer$Reader run INFO: Waiting for ProtocolStack to start. Aug 24, 2024 2:01:57 PM hudson.remoting.Launcher$CuiListener status INFO: Remote identity confirmed: 52:34:14:5f:aa:87:d8:d8:c9:a3:23:e7:32:15:da:d8 Aug 24, 2024 2:01:57 PM hudson.remoting.Launcher$CuiListener status INFO: Connected [root@mcw12 jenkinsagent]#
然jar包在后台运行起来
[root@mcw12 jenkinsagent]# ls agent.jar secret-file [root@mcw12 jenkinsagent]# java -jar agent.jar -url http://10.0.0.25:8080/ -secret @secret-file -name node1 -workDir "/app" & [1] 4121 [root@mcw12 jenkinsagent]# Aug 24, 2024 2:09:39 PM org.jenkinsci.remoting.engine.WorkDirManager initializeWorkDir INFO: Using /app/remoting as a remoting work directory Aug 24, 2024 2:09:39 PM org.jenkinsci.remoting.engine.WorkDirManager setupLogging INFO: Both error and output logs will be printed to /app/remoting Aug 24, 2024 2:09:39 PM hudson.remoting.Launcher createEngine INFO: Setting up agent: node1 Aug 24, 2024 2:09:39 PM hudson.remoting.Engine startEngine INFO: Using Remoting version: 3198.v03a_401881f3e Aug 24, 2024 2:09:39 PM org.jenkinsci.remoting.engine.WorkDirManager initializeWorkDir INFO: Using /app/remoting as a remoting work directory Aug 24, 2024 2:09:39 PM hudson.remoting.Launcher$CuiListener status INFO: Locating server among [http://10.0.0.25:8080/] Aug 24, 2024 2:09:39 PM org.jenkinsci.remoting.engine.JnlpAgentEndpointResolver resolve INFO: Remoting server accepts the following protocols: [JNLP4-connect, Ping] Aug 24, 2024 2:09:39 PM hudson.remoting.Launcher$CuiListener status INFO: Agent discovery successful Agent address: 10.0.0.25 Agent port: 9812 Identity: 52:34:14:5f:aa:87:d8:d8:c9:a3:23:e7:32:15:da:d8 Aug 24, 2024 2:09:39 PM hudson.remoting.Launcher$CuiListener status INFO: Handshaking Aug 24, 2024 2:09:39 PM hudson.remoting.Launcher$CuiListener status INFO: Connecting to 10.0.0.25:9812 Aug 24, 2024 2:09:39 PM hudson.remoting.Launcher$CuiListener status INFO: Server reports protocol JNLP4-connect-proxy not supported, skipping Aug 24, 2024 2:09:39 PM hudson.remoting.Launcher$CuiListener status INFO: Trying protocol: JNLP4-connect Aug 24, 2024 2:09:39 PM org.jenkinsci.remoting.protocol.impl.BIONetworkLayer$Reader run INFO: Waiting for ProtocolStack to start. Aug 24, 2024 2:09:39 PM hudson.remoting.Launcher$CuiListener status INFO: Remote identity confirmed: 52:34:14:5f:aa:87:d8:d8:c9:a3:23:e7:32:15:da:d8 Aug 24, 2024 2:09:39 PM hudson.remoting.Launcher$CuiListener status INFO: Connected [root@mcw12 jenkinsagent]#
再次查看,node1状态已经正常
已经连接
脚本命令行,我们试试
按照他给的例子执行命令,可以看到,的确是在node1 ,也就是mcw12上执行了命令,并返回了结果。
日志
一些系统信息
也可以点击断开连接
复制现有node1,新增node2
创建,然后不修改配置直接保存,
发现好像jdk版本低了
[root@mcw14 opt]# echo 2ebe228de99679c32e9a2a8ea459f450264b71454db97da0bdffbd6161e6e1f9 > secret-file [root@mcw14 opt]# curl -sO http://10.0.0.25:8080/jnlpJars/agent.jar [root@mcw14 opt]# java -version openjdk version "1.8.0_372" OpenJDK Runtime Environment (build 1.8.0_372-b07) OpenJDK 64-Bit Server VM (build 25.372-b07, mixed mode) [root@mcw14 opt]# mkdir /app [root@mcw14 opt]# java -jar agent.jar -url http://10.0.0.25:8080/ -secret @secret-file -name node2 -workDir "/app" Error: A JNI error has occurred, please check your installation and try again Exception in thread "main" java.lang.UnsupportedClassVersionError: hudson/remoting/Launcher has been compiled by a more recent version of the Java Runtime (class file version 55.0), this version of the Java Runtime only recognizes class file versions up to 52.0 at java.lang.ClassLoader.defineClass1(Native Method) at java.lang.ClassLoader.defineClass(ClassLoader.java:756) at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142) at java.net.URLClassLoader.defineClass(URLClassLoader.java:473) at java.net.URLClassLoader.access$100(URLClassLoader.java:74) at java.net.URLClassLoader$1.run(URLClassLoader.java:369) at java.net.URLClassLoader$1.run(URLClassLoader.java:363) at java.security.AccessController.doPrivileged(Native Method) at java.net.URLClassLoader.findClass(URLClassLoader.java:362) at java.lang.ClassLoader.loadClass(ClassLoader.java:418) at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:352) at java.lang.ClassLoader.loadClass(ClassLoader.java:351) at sun.launcher.LauncherHelper.checkAndLoadMain(LauncherHelper.java:621) [root@mcw14 opt]#
升级jdk版本和master的一样之后,再次执行,就可以加入到集群了。jdk1.8不行,是因为master是java17,所以node也得同样版本么,不清楚。
[root@mcw14 opt]# java -jar agent.jar -url http://10.0.0.25:8080/ -secret @secret-file -name node2 -workDir "/app" & [1] 2304 [root@mcw14 opt]# Aug 25, 2024 12:05:35 AM org.jenkinsci.remoting.engine.WorkDirManager initializeWorkDir INFO: Using /app/remoting as a remoting work directory Aug 25, 2024 12:05:35 AM org.jenkinsci.remoting.engine.WorkDirManager setupLogging INFO: Both error and output logs will be printed to /app/remoting Aug 25, 2024 12:05:35 AM hudson.remoting.Launcher createEngine INFO: Setting up agent: node2 Aug 25, 2024 12:05:35 AM hudson.remoting.Engine startEngine INFO: Using Remoting version: 3198.v03a_401881f3e Aug 25, 2024 12:05:35 AM org.jenkinsci.remoting.engine.WorkDirManager initializeWorkDir INFO: Using /app/remoting as a remoting work directory Aug 25, 2024 12:05:36 AM hudson.remoting.Launcher$CuiListener status INFO: Locating server among [http://10.0.0.25:8080/] Aug 25, 2024 12:05:36 AM org.jenkinsci.remoting.engine.JnlpAgentEndpointResolver resolve INFO: Remoting server accepts the following protocols: [JNLP4-connect, Ping] Aug 25, 2024 12:05:36 AM hudson.remoting.Launcher$CuiListener status INFO: Agent discovery successful Agent address: 10.0.0.25 Agent port: 9812 Identity: 52:34:14:5f:aa:87:d8:d8:c9:a3:23:e7:32:15:da:d8 Aug 25, 2024 12:05:36 AM hudson.remoting.Launcher$CuiListener status INFO: Handshaking Aug 25, 2024 12:05:36 AM hudson.remoting.Launcher$CuiListener status INFO: Connecting to 10.0.0.25:9812 Aug 25, 2024 12:05:36 AM hudson.remoting.Launcher$CuiListener status INFO: Server reports protocol JNLP4-connect-proxy not supported, skipping Aug 25, 2024 12:05:36 AM hudson.remoting.Launcher$CuiListener status INFO: Trying protocol: JNLP4-connect Aug 25, 2024 12:05:36 AM org.jenkinsci.remoting.protocol.impl.BIONetworkLayer$Reader run INFO: Waiting for ProtocolStack to start. Aug 25, 2024 12:05:36 AM hudson.remoting.Launcher$CuiListener status INFO: Remote identity confirmed: 52:34:14:5f:aa:87:d8:d8:c9:a3:23:e7:32:15:da:d8 Aug 25, 2024 12:05:36 AM hudson.remoting.Launcher$CuiListener status INFO: Connected [root@mcw14 opt]#
测试断开连接:
重新连接启用
再过一会,可以看到,连接上了
已经恢复为正常可用节点
通过swarm插件增加agent
swarm插件: https://plugins.jenkins.io/swarm
swarm客户端: https://repo.jenkins-ci.org/releases/org/jenkins-ci/plugins/swarm-client/3.9/swarm-client-3.9.jar
安装插件
在装了jdk的机器上下载客户端
[root@mcw14 ~]# java -version openjdk version "1.8.0_372" OpenJDK Runtime Environment (build 1.8.0_372-b07) OpenJDK 64-Bit Server VM (build 25.372-b07, mixed mode) [root@mcw14 ~]# cd /opt/ [root@mcw14 opt]# ls otp_src_23.3 otp_src_23.3.tar.gz rabbitmq-server-3.8.16-1.el7.noarch.rpm sonarqube sonarqube-7.6.zip [root@mcw14 opt]# wget https://repo.jenkins-ci.org/releases/org/jenkins-ci/plugins/swarm-client/3.9/swarm-client-3.9.jar [root@mcw14 opt]# ls otp_src_23.3 otp_src_23.3.tar.gz rabbitmq-server-3.8.16-1.el7.noarch.rpm sonarqube sonarqube-7.6.zip swarm-client-3.9.jar [root@mcw14 opt]#
启动jar包,添加node失败,后面有时间再看这种方式的吧,暂时没有解决
[root@mcw14 opt]# java -jar swarm-client-3.9.jar -username machangwei -password 123456 -master http://10.0.0.25:8080/jenkins -name swarm-node Aug 25, 2024 12:03:54 AM hudson.plugins.swarm.Client main INFO: Client.main invoked with: [-username machangwei -password 123456 -master http://10.0.0.25:8080/jenkins -name swarm-node] Aug 25, 2024 12:03:54 AM hudson.plugins.swarm.Client run INFO: Discovering Jenkins master SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder". SLF4J: Defaulting to no-operation (NOP) logger implementation SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details. Aug 25, 2024 12:03:55 AM hudson.plugins.swarm.SwarmClient discoverFromMasterUrl SEVERE: Failed to fetch swarm information from Jenkins, plugin not installed? Aug 25, 2024 12:03:55 AM hudson.plugins.swarm.Client run SEVERE: RetryException occurred hudson.plugins.swarm.RetryException: Failed to fetch swarm information from Jenkins, plugin not installed? at hudson.plugins.swarm.SwarmClient.discoverFromMasterUrl(SwarmClient.java:229) at hudson.plugins.swarm.Client.run(Client.java:146) at hudson.plugins.swarm.Client.main(Client.java:119) Aug 25, 2024 12:03:55 AM hudson.plugins.swarm.Client run INFO: Retrying in 10 seconds
agent部分详解
any
目前有三个节点,node1,node2都还没有运行过任务
修改文件,点击立即构建
构建成功
查看日志,运行在node2
查看node2的工作目录,workspace也是新建的目录,
[root@mcw14 opt]# ls /app/ remoting workspace [root@mcw14 opt]# ls /app/remoting/ jarCache logs [root@mcw14 opt]# ls /app/workspace/ parameters-example parameters-example@tmp [root@mcw14 opt]#
此时查看下node2构建历史,没看到
不过负载统计可以看到刚刚在猛增
通过标签指定agent
给node2添加标签
node1 只有一个标签,node2两个
指定jdk8的标签,也就是node1或者node2
pipeline { agent { label 'jdk8' } stages { stage('Build') { steps { echo "machangwei build" } } } }
点击构建,运行在node2上了
反复执行,都是调度到node2,改一下,node1添加一个标签
添加一个并且,
pipeline { agent { label 'jdk8 && machangwei' } stages { stage('Build') { steps { echo "machangwei build" } } } }
这次可以看到,是调度到node1了,只要node1符合。
改成agent下面用node,这样还可以用自定义工作目录
pipeline { agent { node { label 'jdk8 && machangwei' customWorkspace '/var/lib/custom' } } stages { stage('Build') { steps { echo "machangwei build" } } } }
构建执行,原本是/app目录下,后面又显示运行在custom这个不存在的目录
可以看到,的确是把代码都拉取到自定义的目录下了,并且这个目录也是新建的
如果两个地方都写了,那么两个地方都有运行的一部分内容
pipeline { agent { node { label 'jdk8 && machangwei' customWorkspace '/var/lib/custom' } } stages { stage('Build') { agent { label 'jdk8 && windows' } steps { echo "machangwei build" } } } }
不分配节点
每个阶段都运行在指定的agent,那么最外层的那个agent就设置为none
pipeline { agent none stages { stage('Build') { agent { label 'jdk8 && windows' } steps { echo "machangwei build" } } stage('Deploy') { agent { label 'jdk8 && machangwei' } steps { echo "machangwei deploy" } } } }
带有windows标签的是node2,带有machangwei标签的是node1,如下,build在node2运行,deploy阶段在node1运行,符合我们pipeline的指定agent要求
when指令的beforeAgent选项
下面的有点问题,测试没有符合预期
pipeline { agent none stages { stage('Build') { agent { label 'jdk8 && windows' } steps { echo "machangwei build" } } stage('Deploy') { agent { label 'jdk8 && machangwei' } when { beforeAgent true branch 'prod' } steps { echo "machangwei deploy" } } } }
我们把上面那节的jenkinsfile添加一个when判断,
并且新增prod分支
立即构建,因为目前默认拉取的是main分支,不符合when的条件 prod,分支是否是prod返回的不是true,所以这个阶段跳过没运行
修改该项目的指定拉取分区为prod
查看已经是拉取prod分支了,但是还是没有执行deploy这个阶段
我们打印一下环境变量,可以看到虽然是prod分支,但是环境变量里面是origin/prod,所以跟pipeline里面写的prod没有匹配上,
去掉环境变量的打印,并且将分支名称改为origin/prod
发现结果还是一样,还是没有匹配上
将构建任务交给docker
下面的有异常,实验未成功
pipeline { agent { docker { label 'docker' image 'busybox' } } stages { stage('Build') { steps { echo "machangwei build" sh "touch machangwei.txt" } } } }
新增一个节点,加上docker标签
新增节点,直接将它加到jenkins master机器上运行
添加节点
[root@mcw15 opt]# ls containerd nexus-3.71.0-06 nexus-3.71.0-06-unix.tar.gz rakudo-pkg sonatype-work swarm-client-3.9.jar [root@mcw15 opt]# ps -ef|grep java jenkins 36131 1 0 Aug24 ? 00:05:33 /usr/bin/java -Djava.awt.headless=true -jar /usr/share/java/jenkins.war --webroot=%C/jenkins/war --httpPort=8080 root 86112 38851 0 12:01 pts/1 00:00:00 grep --color=auto java [root@mcw15 opt]# echo 1c21371902ac3ad7b0a2497b066d80f5d90662737a4cf6df88073c6cec547c9d > secret-file [root@mcw15 opt]# curl -sO http://10.0.0.25:8080/jnlpJars/agent.jar [root@mcw15 opt]# mkdir /app [root@mcw15 opt]# java -jar agent.jar -url http://10.0.0.25:8080/ -secret @secret-file -name "node-docker" -workDir "/app" & [1] 86161 [root@mcw15 opt]# Aug 25, 2024 12:02:40 PM org.jenkinsci.remoting.engine.WorkDirManager initializeWorkDir INFO: Using /app/remoting as a remoting work directory Aug 25, 2024 12:02:40 PM org.jenkinsci.remoting.engine.WorkDirManager setupLogging INFO: Both error and output logs will be printed to /app/remoting Aug 25, 2024 12:02:40 PM hudson.remoting.Launcher createEngine INFO: Setting up agent: node-docker Aug 25, 2024 12:02:40 PM hudson.remoting.Engine startEngine INFO: Using Remoting version: 3198.v03a_401881f3e Aug 25, 2024 12:02:40 PM org.jenkinsci.remoting.engine.WorkDirManager initializeWorkDir INFO: Using /app/remoting as a remoting work directory Aug 25, 2024 12:02:40 PM hudson.remoting.Launcher$CuiListener status INFO: Locating server among [http://10.0.0.25:8080/] Aug 25, 2024 12:02:40 PM org.jenkinsci.remoting.engine.JnlpAgentEndpointResolver resolve INFO: Remoting server accepts the following protocols: [JNLP4-connect, Ping] Aug 25, 2024 12:02:40 PM hudson.remoting.Launcher$CuiListener status INFO: Agent discovery successful Agent address: 10.0.0.25 Agent port: 9812 Identity: 52:34:14:5f:aa:87:d8:d8:c9:a3:23:e7:32:15:da:d8 Aug 25, 2024 12:02:40 PM hudson.remoting.Launcher$CuiListener status INFO: Handshaking Aug 25, 2024 12:02:40 PM hudson.remoting.Launcher$CuiListener status INFO: Connecting to 10.0.0.25:9812 Aug 25, 2024 12:02:40 PM hudson.remoting.Launcher$CuiListener status INFO: Server reports protocol JNLP4-connect-proxy not supported, skipping Aug 25, 2024 12:02:40 PM hudson.remoting.Launcher$CuiListener status INFO: Trying protocol: JNLP4-connect Aug 25, 2024 12:02:40 PM org.jenkinsci.remoting.protocol.impl.BIONetworkLayer$Reader run INFO: Waiting for ProtocolStack to start. Aug 25, 2024 12:02:41 PM hudson.remoting.Launcher$CuiListener status INFO: Remote identity confirmed: 52:34:14:5f:aa:87:d8:d8:c9:a3:23:e7:32:15:da:d8 Aug 25, 2024 12:02:41 PM hudson.remoting.Launcher$CuiListener status INFO: Connected
已经正常。这个应该一个服务器里面可以跑多个node程序的。这样应该可以提高并发处理能力。增加执行器。
docker插件安装了的,不过不是我们用的那个
下面这个才是:https://plugins.jenkins.io/docker-plugin,而不是下面那个workflow
安装好插件重启jenkins服务的时候,各个agent也是会被终止重连
[root@mcw14 opt]# Aug 25, 2024 12:16:15 PM hudson.remoting.Launcher$CuiListener status INFO: Terminated Aug 25, 2024 12:16:28 PM org.jenkinsci.remoting.engine.JnlpAgentEndpointResolver waitForReady INFO: Controller isn't ready to talk to us on http://10.0.0.25:8080/tcpSlaveAgentListener/. Will try again: response code=503 Aug 25, 2024 12:16:38 PM hudson.remoting.Launcher$CuiListener status INFO: Performing onReconnect operation. Aug 25, 2024 12:16:39 PM jenkins.slaves.restarter.JnlpSlaveRestarterInstaller$EngineListenerAdapterImpl onReconnect INFO: Restarting agent via jenkins.slaves.restarter.UnixSlaveRestarter@7a46cfb1 Aug 25, 2024 12:16:39 PM org.jenkinsci.remoting.engine.WorkDirManager initializeWorkDir INFO: Using /app/remoting as a remoting work directory Aug 25, 2024 12:16:39 PM org.jenkinsci.remoting.engine.WorkDirManager setupLogging INFO: Both error and output logs will be printed to /app/remoting Aug 25, 2024 12:16:39 PM hudson.remoting.Launcher createEngine INFO: Setting up agent: node2 Aug 25, 2024 12:16:39 PM hudson.remoting.Engine startEngine INFO: Using Remoting version: 3198.v03a_401881f3e Aug 25, 2024 12:16:39 PM org.jenkinsci.remoting.engine.WorkDirManager initializeWorkDir INFO: Using /app/remoting as a remoting work directory Aug 25, 2024 12:16:39 PM hudson.remoting.Launcher$CuiListener status INFO: Locating server among [http://10.0.0.25:8080/] Aug 25, 2024 12:16:39 PM org.jenkinsci.remoting.engine.JnlpAgentEndpointResolver resolve INFO: Remoting server accepts the following protocols: [JNLP4-connect, Ping] Aug 25, 2024 12:16:39 PM hudson.remoting.Launcher$CuiListener status INFO: Agent discovery successful Agent address: 10.0.0.25 Agent port: 9812 Identity: 52:34:14:5f:aa:87:d8:d8:c9:a3:23:e7:32:15:da:d8 Aug 25, 2024 12:16:39 PM hudson.remoting.Launcher$CuiListener status INFO: Handshaking Aug 25, 2024 12:16:39 PM hudson.remoting.Launcher$CuiListener status INFO: Connecting to 10.0.0.25:9812 Aug 25, 2024 12:16:39 PM hudson.remoting.Launcher$CuiListener status INFO: Server reports protocol JNLP4-connect-proxy not supported, skipping Aug 25, 2024 12:16:39 PM hudson.remoting.Launcher$CuiListener status INFO: Trying protocol: JNLP4-connect Aug 25, 2024 12:16:39 PM org.jenkinsci.remoting.protocol.impl.BIONetworkLayer$Reader run INFO: Waiting for ProtocolStack to start. Aug 25, 2024 12:16:41 PM hudson.remoting.Launcher$CuiListener status INFO: Remote identity confirmed: 52:34:14:5f:aa:87:d8:d8:c9:a3:23:e7:32:15:da:d8 Aug 25, 2024 12:16:41 PM hudson.remoting.Launcher$CuiListener status INFO: Connected
jenkins日志
需要新增一个插件,并且docker-plugin插件需要降低版本,
版本适配了,也不需要依赖包了
使用这个之后,发现还是不行。可能是版本太低,不支持吧
WorkflowScript: 3: Invalid agent type "docker" specified. Must be one of [any, label, none] @ line 3, column 9.
配置docker私有仓库
并行构建
如下,分别在Chrome,Firefox,IE等浏览器的不同版本对用一个web应用进行UI测试,用下面方法,按照顺序执行,测试效率太慢了
pipeline { agent any stages { stage('Build') { steps { echo "Building..." } } stage('Test on Chrome') { steps { echo "Testing..." } } stage('Test on Firfox') { steps { echo "Testing..." } } } }
修改,使用并行构建
pipeline { agent any stages { stage('Run Tests') { failFast true parallel { stage('Test On Chrome') { agent { label "chrome" } steps { echo "Chrome UI测试" } } stage('Test on Firfox') { agent { label "firefox" } steps { echo "Firfox UI测试" } } stage('Test on IE') { agent { label "ie" } steps { echo "IE UI测试" } } } //end of parallel } // end of run test } // end of stages } // end of pipeline
给三个agent上分别添加上上面对应的三个标签
总共花了778ms,而之前的pipeline执行是花了959ms,这效率变高了
从日志输出也可以看出,整个pipeline在master上运行,然后三个阶段分别在三个agent上运行,并且不是按照顺序完成一个,才开始下一个阶段的运行,而是并行。如果是顺序执行的话,那么running on 节点的日志输出不会放在一起出来,而是中间隔了好多行其它输出,也就是等一个阶段的所有输出结算之后,才会进行第二个阶段的日志输出。也就是这里是已经实现了并行,提高了效率。
在不同的分支上应用并行构建
并行步骤