簡介
之前通過jenkins+ansible實現了系統初始化的功能,另外內部還有一套tftp+dhcp+pxe實現的操作系統自動安裝。雖然給工作帶來了方便,但是仍需運維人員進行人工干預,藉助於jenkins的流水線,我們在此將兩項工作進行結合,自動化執行。
規劃
jenkins構建時,通過傳入IP及選擇不同的操作系統模板參數,使用相應的修改後模板,進行不同規範的操作系統安裝。
注意: 結合我們的生產環境規範,我們將操作系統模板分爲兩個,一個是ks_root(只有跟目錄的系統),一個是ks_app(根+/App 目錄的系統)
流程:
- 提前建好vsphere虛擬機
- 配置pxe配置文件
- 手動重啓vsphere虛擬機並選擇pxe安裝系統
- 恢復pxe配置文件,防止正常系統重啓進入pxe安裝
- 等待10min安裝完系統,調用init_os job進行系統初始化
準備
job | 備註 |
---|---|
init_os | jenkins的一個job,結合ansible實現的系統初始化功能 |
pxe環境 | 一套tftp+dhcp+pxe實現的操作系統自動安裝環境 |
以上兩項任務在此不做過多說明。
pipeline實現
一.pipeline設置參數
此操作將定義全局的環境變量:
HOST_IP 分配的ip地址
KS_TEMPLATE 使用的pxe模板文件,ks_app和ks_root
編寫pipeline
以下使用聲明式pipeline,將分階段分析:
1.分析IP階段
stage('分析IP') {
steps {
sh label: '', script: '''
#!/bin/bash
echo "\033[34m判斷IP合法性 \033[0m"
[ `echo ${HOST_IP} | awk -F . '{print NF}'` -ne 4 ] && { echo -e "\033[31m${HOST_IP}不合法,請查看IP \033[0m"; exit 1; }
count=`ping -c 4 ${HOST_IP} |grep "100% packet loss" | wc -l`
[ $count -ne 0 ]&& echo "\033[32m${HOST_IP}未分配,請正常使用 \033[0m" || { echo "\033[31m${HOST_IP}已分配,請更換其他IP \033[0m"; exit 1; }'''
}
post {
success {
echo "\033[34m配置pxe \033[0m"
sshPublisher(publishers: [sshPublisherDesc(configName: 'prod-3.137', transfers: [sshTransfer(cleanRemote: false, excludes: '', execCommand: '''
echo "\033[34m更改IP地址 \033[0m"
cd /var/www/html/ks/nodes/
sed -i "s/IP=/IP=${HOST_IP}/g" ${KS_TEMPLATE}
[ $? -eq 0 ] && echo "\033[32m更改IP地址成功 \033[0m" || { echo "\033[31m更改IP地址失敗 \033[0m" ; exit 1; }
echo "\033[34m修改tftp配置文件 \033[0m"
cd /tftpboot/pxelinux.cfg
sed -i "s/nodes/nodes\\/${KS_TEMPLATE}/g" default
[ $? -eq 0 ] && echo "\033[32m修改tftp配置文件成功 \033[0m" || { echo "\033[31m修改tftp配置文件失敗 \033[0m" ; exit 1; }''', execTimeout: 120000, flatten: false, makeEmptyDirs: false, noDefaultExcludes: false, patternSeparator: '[, ]+', remoteDirectory: '', remoteDirectorySDF: false, removePrefix: '', sourceFiles: '')], usePromotionTimestamp: false, useWorkspaceInPromotion: false, verbose: false)])
}
}
}
其中:
1.判斷ip是否合法並且在生產環境中未分配:
使用了"sh: Shell Script"在此判斷了ip是否爲X.X.X.X,而沒有實現X是否合法,可以補充。
a.如果ip不合法,流水線將終止;
b.如果ip合法,但ip已經分配,則流水線將終止;
c.如果ip合法,且ip未分配,則通過"post: Post Stage or Build Conditions"實現若a、b成功,則執行post中的pxe的模板文件修改的操作:主要爲將ip,寫入到模板配置文件;並設置tftp的相關設置。
2.使用"sshPublisher : send build artifacts over ssh",遠程登錄pxe服務器修改pxe配置文件
主要調用構建時選擇的HOST_IP、KS_TEMPLATE
2.pxe系統安裝階段
stage("pxe系統安裝") {
steps {
echo "\033[34mpxe系統安裝 \033[0m"
sleep 600
}
}
進入此階段前,我們需要提前建好vsphere虛擬機或服務器;
進入此階段後,我們需要手動重啓服務器並選擇pxe進入操作系統安裝;
整個系統安裝我們預估在6分鐘左右,在此我設置"sleep 600" (10分鐘)等待操作系統完全安裝完畢並重啓。
我們也可以使用"input: Input"來提示pipeline的互動繼續及放棄操作。
注意:
由於我們使用的vsphere,本計劃使用python+pyvmomi上線虛擬機的自動重啓,但是此操作需要虛擬機提前安裝vmwaretools,而安裝vmwaretools前提是需要操作系統。因此我們使用手動重啓。
感興趣的朋友可以看下GitHub vmware/pyvmomi,使用sample中的例子進行vsphere的管理。
3.恢復pxe階段
stage("恢復pxe") {
steps {
sshPublisher(publishers: [sshPublisherDesc(configName: 'prod-3.137', transfers: [sshTransfer(cleanRemote: false, excludes: '', execCommand: '''
echo "\033[34m刪除IP地址配置 \033[0m"
cd /var/www/html/ks/nodes/
sed -i "s/IP=${HOST_IP}/IP=/g" ${KS_TEMPLATE}
[ $? -eq 0 ] && echo "\033[32m刪除IP地址成功 \033[0m" || { echo "\033[31m刪除IP地址失敗 \033[0m" ; exit 1; }
echo "\033[34m恢復tftp配置文件 \033[0m"
cd /tftpboot/pxelinux.cfg
sed -i "s/\\/${KS_TEMPLATE}//g" default
[ $? -eq 0 ] && echo "\033[32m恢復tftp配置文件成功 \033[0m" || { echo "\033[31m恢復tftp配置文件失敗 \033[0m" ; exit 1; }''', execTimeout: 120000, flatten: false, makeEmptyDirs: false, noDefaultExcludes: false, patternSeparator: '[, ]+', remoteDirectory: '', remoteDirectorySDF: false, removePrefix: '', sourceFiles: '')], usePromotionTimestamp: false, useWorkspaceInPromotion: false, verbose: false)])
}
}
操作系統安裝完成後,我們需要恢復pxe模板設置,防止生產環境中有系統重啓情況導致系統重裝。
使用"sshPublisher : send build artifacts over ssh",遠程登錄pxe服務器修改pxe配置文件使用"sshPublisher : send build artifacts over ssh",遠程登錄pxe服務器修改pxe配置文件。
4.系統初始化階段
stage("系統初始化") {
steps {
echo "\033[34m正在進行系統初始化 \033[0m"
build job: 'init_os', parameters: [string(name: 'host_ip', value: "${HOST_IP}")]
}
}
此階段,pipeline將調用init_os job,並傳出HOST_IP參數,進行操作系統的初始化,主要爲:
a.repo、selinux、ntp、內核參數
b.ssh安全設置
c.zabbix 客戶端及其他
d.規範化目錄
e.防火前初始化腳本
5.整個piple的完整代碼
pipeline {
agent any
options {
ansiColor('xterm')
timestamps()
}
stages {
stage('分析IP') {
steps {
sh label: '', script: '''
#!/bin/bash
echo "\033[34m判斷IP合法性 \033[0m"
[ `echo ${HOST_IP} | awk -F . '{print NF}'` -ne 4 ] && { echo -e "\033[31m${HOST_IP}不合法,請查看IP \033[0m"; exit 1; }
count=`ping -c 4 ${HOST_IP} |grep "100% packet loss" | wc -l`
[ $count -ne 0 ]&& echo "\033[32m${HOST_IP}未分配,請正常使用 \033[0m" || { echo "\033[31m${HOST_IP}已分配,請更換其他IP \033[0m"; exit 1; }'''
}
post {
success {
echo "\033[34m配置pxe \033[0m"
sshPublisher(publishers: [sshPublisherDesc(configName: 'prod-3.137', transfers: [sshTransfer(cleanRemote: false, excludes: '', execCommand: '''
echo "\033[34m更改IP地址 \033[0m"
cd /var/www/html/ks/nodes/
sed -i "s/IP=/IP=${HOST_IP}/g" ${KS_TEMPLATE}
[ $? -eq 0 ] && echo "\033[32m更改IP地址成功 \033[0m" || { echo "\033[31m更改IP地址失敗 \033[0m" ; exit 1; }
echo "\033[34m修改tftp配置文件 \033[0m"
cd /tftpboot/pxelinux.cfg
sed -i "s/nodes/nodes\\/${KS_TEMPLATE}/g" default
[ $? -eq 0 ] && echo "\033[32m修改tftp配置文件成功 \033[0m" || { echo "\033[31m修改tftp配置文件失敗 \033[0m" ; exit 1; }''', execTimeout: 120000, flatten: false, makeEmptyDirs: false, noDefaultExcludes: false, patternSeparator: '[, ]+', remoteDirectory: '', remoteDirectorySDF: false, removePrefix: '', sourceFiles: '')], usePromotionTimestamp: false, useWorkspaceInPromotion: false, verbose: false)])
}
}
}
stage("pxe系統安裝") {
steps {
echo "\033[34mpxe系統安裝 \033[0m"
sleep 600
}
}
stage("恢復pxe") {
steps {
sshPublisher(publishers: [sshPublisherDesc(configName: 'prod-3.137', transfers: [sshTransfer(cleanRemote: false, excludes: '', execCommand: '''
echo "\033[34m刪除IP地址配置 \033[0m"
cd /var/www/html/ks/nodes/
sed -i "s/IP=${HOST_IP}/IP=/g" ${KS_TEMPLATE}
[ $? -eq 0 ] && echo "\033[32m刪除IP地址成功 \033[0m" || { echo "\033[31m刪除IP地址失敗 \033[0m" ; exit 1; }
echo "\033[34m恢復tftp配置文件 \033[0m"
cd /tftpboot/pxelinux.cfg
sed -i "s/\\/${KS_TEMPLATE}//g" default
[ $? -eq 0 ] && echo "\033[32m恢復tftp配置文件成功 \033[0m" || { echo "\033[31m恢復tftp配置文件失敗 \033[0m" ; exit 1; }''', execTimeout: 120000, flatten: false, makeEmptyDirs: false, noDefaultExcludes: false, patternSeparator: '[, ]+', remoteDirectory: '', remoteDirectorySDF: false, removePrefix: '', sourceFiles: '')], usePromotionTimestamp: false, useWorkspaceInPromotion: false, verbose: false)])
}
}
stage("系統初始化") {
steps {
echo "\033[34m正在進行系統初始化 \033[0m"
build job: 'init_os', parameters: [string(name: 'host_ip', value: "${HOST_IP}")]
}
}
}
}
6.構建輸出