Jenkins分布式構建

分類:IT技術 時間:2016-10-13

Jenkins分布式構建(Jenkins Distributed builds)

前言:

當自動化測試用例需要在多個PC機或虛擬機中執行時,如果在每個虛擬機中均搭建類似tomcat+jenkins的環境,將會造成例如每臺虛擬機資源占用大、對環境的配置維護成本大等弊端,此時,就可以采用Jenkins分布式構建方式了。

一、Jenkins節點配置

1.Master配置

1)進入Master的http://ip:8080/jenkins/網頁界面

2)進入系統管理——節點管理界面

3)點擊“新建節點”

Jenkins分布式構建


 

遠程工作目錄:指定遠程中的節點機器的工作目錄,即Job中checkout出的代碼所在的workspace目錄

標簽:該節點的唯一標識,當在Job中要指定只在該節點進行構建與測試時,通過該唯一標識進行指定

其中啟動方法有四種:

Jenkins分布式構建

Launch slave agents on Unix machines via SSH:                    當節點為Unix slaves時,可以選擇此種方式

Launch slave agents via Java Web Start:                               使用JNLP方式來建立slave與master的連接

Launch slave via execution of command on the Master:           使用命令行方式

Let Jenkins control this Windows slave as a Windows service :Jenkins將把該Windows slave當做Windows service進行控制

對於Windows操作系統的節點,推薦用第二種Launch slave agents via Java Web Start

點擊“保存”後,在Master中一個節點就配置好了

2.slave節點配置

當節點以Launch slaveagents via Java Web Start配置好後,在節點界面將看到如圖所示,其slave有三種啟動方法,本質上其實就一種,即將master中的slave-agetn.jnlp文件下載至slave所在的虛擬機,然後運行文件。

註:上圖中Run from slave command line中的IP地址,如果在jenkins系統配置界面中沒設置過ip的話,將為localhost,因此此時需要自己先查看下自己master機器的ip。

因此為方便,可以將連接方式寫入bat批處理文件中。

1)進入節點虛擬機,先創建剛才配置的遠程工作目錄(D:\\jenkins)

2)創建bat文件,命令為例如:start_jenkins_agent.bat  內容:

javaws http://192.168.10.181:8080/jenkins/computer/Windows_181_to_4400/slave-agent.jnlp

3)雙擊運行文件即可看到slave節點與master連接

註:上圖中,點擊File——Installas a services  可以將該slave agent以Windows系統服務運行,理論上方便於開機自啟動,但作為Windows服務,是無法與GUI進行交互的,因此沒法啟動火狐進行selenium的自動化測試,因此如果自動化測試與GUI相關,這裏千萬別Install as a services。

二、Job配置

Jenkins分布式構建        在Master中新建一個job,其中在配置頁面中勾選Restrict when this project can be run,Label選擇要在哪個節點中運行,這樣就可以指定該job在哪個slave節點中運行了

三、Jenkins slave開機自啟動

1)若要對所用用戶均進行開機自啟動,則將.bat啟動文件的快捷方式放入 ‘\Documents and Settings\All Users\“開始”菜單\程序\啟動’  目錄下

2)若只要對指定用戶進行開機自啟動,則將.bat啟動文件的快捷方式放入 ‘\Documents and Settings\ <用戶名字>\“開始”菜單\程序\啟動’  目錄下

四、Jenkins節點監控

jenkins節點由於系統運行、網絡環境等各種因素,難免會出現系統掛機、節點掉線等情況,因此要想及???發現這些情況,就需要對節點進行監控,

可以采用這裏推薦的監控並重連機制:https://wiki.jenkins-ci.org/display/JENKINS/Monitor+and+Restart+Offline+Slaves

1)由於jenkins節點監控使用的是groovy腳本調用的jenkins內部api,因此需要先安裝groovy plugin插件

2)在Master中新建一個名字為如monitor的job,設置為例如每30分鐘運行一次。

3)新增Excute system Groovy script構建步驟:

輸入groovy腳本(由於wiki中的沒有郵箱認證步驟,因此這裏的腳本增加了郵箱認證):

import hudson.model.*
import hudson.node_monitors.*
import hudson.slaves.*
import java.util.concurrent.*

jenkins = Hudson.instance

import javax.mail.Internet.*;
import javax.mail.*
import javax.activation.*


def sendMail (slave, cause) {
  //這裏使用的是參數化構建中的變量,如果不使用此方式,可以註釋掉,而使用下面的toAddress
 toAddress = build.buildVariableResolver.resolve("EMAIL_RECEIVERS")
  
 message = slave + " slave is down. Check http://192.168.10.181:8080/jenkins/computer/" + slave + "\nBecause " + cause
 subject = "【jenkins節點監控】" + slave + " slave is offline"
 //toAddress = "***@***.com;***@***.com"
 fromAddress = "***@***.com"
 host = "SMTP_SERVER"
 port = "SMTP_PORT"

 Properties props = new Properties();
 // 發送郵件的服務器
 props.setProperty("mail.smtp.host", "smtp.***.com");
 // 發送郵件的協議
 props.setProperty("mail.transport.protocol", "smtp");
 // 在連接服務器的時候是否需要驗證,發郵件是需要驗證的
 props.setProperty("mail.smtp.auth", "true");
  
 // 當需要進行驗證的時候,會自動從Session中去取該Authenticator對象
 Authenticator authenticator = new Authenticator() {
    
   @Override
   protected PasswordAuthentication getPasswordAuthentication() {
     return new PasswordAuthentication("your user name", "your passwd"); //輸入用戶名、密碼
   }
    
 };

 Session lSession = Session.getInstance(props,authenticator);
 MimeMessage msg = new MimeMessage(lSession);


 //tokenize out the recipients in case they came in as a list
 StringTokenizer tok = new StringTokenizer(toAddress,";");
 ArrayList emailTos = new ArrayList();
 while(tok.hasMoreElements()){
 emailTos.add(new InternetAddress(tok.nextElement().toString()));
 }
 InternetAddress[] to = new InternetAddress[emailTos.size()];
 to = (InternetAddress[]) emailTos.toArray(to);

  
 msg.setRecipients(MimeMessage.RecipientType.TO,to);
 InternetAddress fromAddr = new InternetAddress(fromAddress);
 msg.setFrom(fromAddr);
 msg.setFrom(new InternetAddress(fromAddress));
 msg.setSubject(subject);
 msg.setText(message)

 Transport transporter = lSession.getTransport("smtp");
 transporter.connect();
 transporter.send(msg);
}


def getEnviron(computer) {
   def env
   def thread = Thread.start("Getting env from ${computer.name}", { env = computer.environment })
   thread.join(2000)
   if (thread.isAlive()) thread.interrupt()
   env
}

def slaveAccessible(computer) {
    getEnviron(computer)?.get('PATH') != null
}


def numberOfflineNodes = 0
def numberNodes = 0
for (slave in jenkins.slaves) {
   def computer = slave.computer
   numberNodes ++
   println ""
   println "Checking computer ${computer.name}:"
   def isOK = (slaveAccessible(computer) && !computer.offline)
   if (isOK) {
     println "\t\tOK, got PATH back from slave ${computer.name}."
     println('\tcomputer.isOffline: ' + slave.getComputer().isOffline()); 
     println('\tcomputer.isTemporarilyOffline: ' + slave.getComputer().isTemporarilyOffline());
     println('\tcomputer.getOfflineCause: ' + slave.getComputer().getOfflineCause());
     println('\tcomputer.offline: ' + computer.offline); 
     
     
   } else {
     numberOfflineNodes ++
     println "  ERROR: can't get PATH from slave ${computer.name}."
     println('\tcomputer.isOffline: ' + slave.getComputer().isOffline()); 
     println('\tcomputer.isTemporarilyOffline: ' + slave.getComputer().isTemporarilyOffline());
     println('\tcomputer.getOfflineCause: ' + slave.getComputer().getOfflineCause());
     println('\tcomputer.offline: ' + computer.offline); 
     sendMail(computer.name, slave.getComputer().getOfflineCause().toString())
     if (slave.getComputer().isTemporarilyOffline()) {
      if (!slave.getComputer().getOfflineCause().toString().contains("Disconnected by")) {
         computer.setTemporarilyOffline(false, slave.getComputer().getOfflineCause())        
      }
     } else {
         computer.connect(true)  
     }
   }
 }
println ("Number of Offline Nodes: " + numberOfflineNodes)
println ("Number of Nodes: " + numberNodes)  

註:jenkins 在1.582版本時修復了一個slave會概率性出現掉線,且無法重連,只至重啟才能再次連接的問題,CancelledKeyException can cause all JNLP slaves to disconnect (and the problem remains until restart):https://issues.jenkins-ci.org/browse/JENKINS-24050

因此建議將jenkins升級至最新的或1.582以上的版本

 

局域網內利用GitLab+Jenkins自動生成GitBook並發布(Nginx) 

linux+Git+Maven+Jenkins+Neuxs自動化編譯環境搭建

CentOS6安裝Jenkins 

使用Jenkins配置Git+Maven的自動化構建

Jenkins+Maven+Git搭建持續集成和自動化部署的配置手記

Jenkins的分布式構建及部署——節點 

本文永久更新鏈接地址


Tags: execution machines Windows checkout command

文章來源:


ads
ads

相關文章
ads

相關文章

ad