Jenkins持續部署-Windows環境持續部署探究1

傑哥很忙發表於2019-05-25

Jenkins持續部署-Windows環境持續部署探究1


目錄

Jenkins持續整合學習-Windows環境進行.Net開發1
Jenkins持續整合學習-Windows環境進行.Net開發2
Jenkins持續整合學習-Windows環境進行.Net開發3
Jenkins持續整合學習-Windows環境進行.Net開發4
Jenkins持續整合學習-搭建jenkins問題彙總
Jenkins持續部署-Windows環境持續部署探究1

前言

在之前的文章中,對Windows環境下的持續整合方案進行探究,接下來對Windows環境下持續部署的方案進行學習與研究。

目的

當jenkins整合編譯成功後,將檔案上傳到指定的伺服器FTP目錄。本文將介紹關於持續部署需要的一些技術方案的實現,在後續文章中繼續對持續整合具體的邏輯進行細化梳理。

方案流程

當jenkins編譯完成之後,我們需要處理以下事項完成持續部署。

20190525121346.png

  1. jenkins編譯成功,則將所有的exe和dll檔案先壓縮打包,檔名可以命名為Job名稱或者版本號
  2. 壓縮完成後將壓縮檔案上傳到指定的FTP
  3. 上傳完成後,則需要關閉伺服器上的指定服務
  4. 關閉完成後替換原始的程式目錄下的檔案
  5. 啟動服務

這裡暫時不探討服務可用性的具體細節,也不討論服務升級失敗的回退工作等具體細節。

技術實現

可以分析出上述流程中涉及到的技術要點。

  1. 呼叫指令碼對指定的檔案進行壓縮,在windows上使用PowerShell執行指令碼再合適不過了。
  2. 通過FTP上傳到伺服器,可以通過jenkins的FTP外掛或者通過PowerShell指令碼將檔案上傳到指定伺服器上。
  3. 關閉伺服器上的指定服務,這裡就需要支援遠端呼叫,在windows上可以通過winrm執行遠端服務呼叫。

PowerShell

Windows PowerShell 是專門為系統管理員設計的 Windows 命令列 Shell。 Windows PowerShell 包括可以單獨或組合使用的互動提示和指令碼編寫環境。這裡不探討PowerShell的使用細節,因為這不是本篇文章的關注重點,具體的關於PowerShell的介紹可以看微軟的官方文件Windows PowerShell 入門

FTP上傳外掛

jenkins上有支援的FTP外掛,比如Publish Over FTP Plugin,下載之後安裝重啟jenkins。

外掛配置

在系統管理-系統設定下找到Publish over FTP項的設定,新增FTP服務的地址,埠,使用者名稱和密碼等相關配置,然後點選TestConfiguration按鈕,若顯示Success表示配置成功。可以手工新增多個FTP配置。
20190523203211.png
點選Advanced按鈕修改埠或超時時間等配置
20190523203430.png
配置完成後到Job中新增FTP上傳功能,在Build中點選Add Build step選擇Send file over FTP
20190523203623.png
Name通過下拉選擇前面配置的FTP站點,在Transfers配置需要上傳的檔案和上傳到遠端的目錄。
20190523203825.png
Source files:支援萬用字元,如上傳所有檔案*.*,或bin/Release/下的所有檔案
Remove prefix:表示上傳檔案去除字首,FTP預設會將檔案的相對路徑一起上傳,若不需要bin/Release則可以配置去除該相對路徑,如bin/Release/Test.exe上傳到FTP上若沒有指定FTP遠端相對路徑,則為FTP根目錄下的Test.exe檔案。
Remote directory:表示上傳到FTP目錄下的哪個相對目錄中,一般來說我們可以按Job名稱分資料夾,可以通配置Jenkins內建的環境變數,如$JOB_NAME/

上傳FTP前需要保證FTP上目錄結構存在,否則會上傳失敗。因此上傳FTP前需要通過指令碼到伺服器的FTP目錄上創對應的資料夾路徑。

一般來說我們編譯完成後需要將程式按版本號分目錄存在,比如1.0.X的存放到1.0的目錄中。2.0.X的存放到2.0的目錄中。因此我們可以在Remote directory填寫${JOB_NAME}/$PROCESS_VERSION,如下圖所示
20190524142924.png
$PROCESS_VERSION變數的值我們需要在前面的指令碼中獲取,由於在jenkinsBuild步驟中建立的每個powershell指令碼塊,jenkins都會將其儲存到臨時的XXXX.ps1指令碼檔案中,因此不同的步驟產生的變數是在不同的指令碼檔案中,也就是在不同的作用域中。因此在前面建立的指令碼獲取到的版本號,無法直接在下一個指令碼中獲取。

關於powershell的變數作用域可以檢視Powershell變數的作用域

如下圖所示,第一個指令碼中賦值的$PROCESS_VERSION在後面的指令碼以及FTP目錄中都是獲取不到該變數的。
20190524143518.png
因此我們可以通過將變數儲存到檔案,然後重新載入到Jenkins的環境變數中,Jenkins的環境變數在Jenkins當前Job中都可以獲取到。

環境變數外掛

使用Jenkins的環境變數外掛EnvInject Plugin實現上述功能。安裝完外掛之後重啟Jenkins。
如果我們多個Job需要用到同樣的引數常量,那我們可以將引數直接在Jenkins配置中注入到環境變數中,然後可以通過環境變數$Env:XXXX獲取到我們配置的變數值。

配置全域性環境變數

在系統管理-系統設定下找到Global properties項,勾選環境變數,後即可設定全域性的環境變數。這樣當這些變數修改後,只需要在設定中修改一次,而無需修改每個Job中的指令碼變數值。
20190524144502.png

使用環境變數

我們現在可以直接在Job中使用配置好的全域性環境變數。在構建之後,可以在當前構建項的Environment Variables檢視到已載入的環境變數
20190524144818.png

從檔案注入環境變數

現在我們就可以將將版本號資訊存入到檔案中,然後重新載入到全域性環境變數中了。
首先在通過指令碼獲取到程式的版本號,將它儲存到檔案中,儲存格式為變數名=變數值,如將PROCESS_VERSION="1.0.0.0"儲存到Version.txt檔案中。
然後通過環境變數注入外掛從文字中讀取環境變數,在Build中新增Inject environment variables步驟,在Properties File Path中填寫Version.txt,則會從文字中讀取環境變數,多個環境變數通過換行分割。
20190524150233.png

預設PowerShell儲存的格式是含有BOM的Unicode編碼,而Jenkins讀取ASCII編碼格式。因此需要指定文字輸出編碼為ASCII

指令碼執行

通過Powershell指令碼也可以呼叫.Net庫將檔案壓縮或上傳,這裡暫時不討論指令碼編寫細節問題。後續文章將給出完整的解決方案。

遠端呼叫

在Linux環境下可以通過SSH進行遠端呼叫,而在Windows環境下則可以使用Windows 遠端管理 (Windows Remote Management,簡稱WinRM)。
WinRM是微軟實現的WS-Management協議的, 這是一種基於標準的簡單物件訪問協議(SOAP), 由於它是基於防火牆友好的協議, 因此允許來自不同供應商的硬體和作業系統互動。關於WinRM具體的介紹可以檢視Windows Remote Management

我們可以理解為WinRM提供了一個服務端,同時向外暴露了相關的API,而同時Powershell可以與WinRM進行互動,即Powershell本身就是一個遠端呼叫的客戶端,通過Powershell執行相關的命令與WinRM互動,從而實現遠端呼叫,執行自定義指令碼,甚至是執行伺服器上的指定路徑下的指令碼。

因此我們若需要進行遠端呼叫,首先在對應的伺服器上需要開啟WinRM的相關功能。

啟用WinRM服務

  1. 快速配置

    微軟為了簡化WinRM的配置,提供了一個快捷命令進行預設的快速配置。通過呼叫winrm quickconfig進行快速配置。如下返回則為正常配置成功

    PS C:\Users\Administrator> winrm quickconfig
    在此計算機上,WinRM 已設定為接收請求。
    WinRM 沒有設定成為了管理此計算機而允許對其進行遠端訪問。
    必須進行以下更改:
    
    在 HTTP://* 上建立 WinRM 偵聽程式接受 WS-Man 對此機器上任意 IP 的請求
    啟用 WinRM 防火牆異常。
    配置 LocalAccountTokenFilterPolicy 以遠端向本地使用者授予管理許可權。
    
    進行這些更改嗎[y/n]? y
    
    WinRM 已經進行了更新,以用於遠端管理。
    
    在 HTTP://* 上建立 WinRM 偵聽程式接受 WS-Man 對此機器上任意 IP 的請求
    WinRM 防火牆異常已啟用。
    已配置 LocalAccountTokenFilterPolicy 以遠端向本地使用者授予管理許可權。

    需要注意的是,在我本地win10環境,無法執行快速配置,提示說網路連線型別是公用,但是我改為專用仍然還是報錯,目前暫未解決。

    PS C:\Users\Dm_ca> winrm quickconfig
    已在此計算機上執行 WinRM 服務。
    WSManFault
        Message
            ProviderFault
                WSManFault
                    Message = 由於此計算機上的網路連線型別之一設定為公用,因此 WinRM 防火牆例外將不執行。 將網路連線型別更改為域或專用,然後再次嘗試。
    
    錯誤編號: -2144108183 0x80338169
    由於此計算機上的網路連線型別之一設定為公用,因此 WinRM 防火牆例外將不執行。 將網路連線型別更改為域或專用,然後再次嘗試。
  2. 檢視WinRM服務監聽

    通過winrm enumerate winrm/config/listener可以檢視WinRM服務的當前監聽資訊

    PS C:\Users\Administrator> winrm enumerate winrm/config/listener
    Listener
        Address = *
        Transport = HTTP
        Port = 5985
        Hostname
        Enabled = true
        URLPrefix = wsman
        CertificateThumbprint
        ListeningOn = 10.60.45.239, 127.0.0.1, XXXXXXXXXXX

    若上一步快速配置沒有成功,則會返回以下資訊

    PS C:\Users\Dm_ca> winrm enumerate winrm/config/listener
    WSManFault
        Message
            ProviderFault
                WSManFault
                    Message = 拒絕訪問。
  3. 啟用遠端呼叫

    通過輸入Enable-PSRemoting –Force啟用Powershell遠端呼叫功能。
    powershell PS C:\Users\Administrator> Enable-PSRemoting –Force 在此計算機上,WinRM 已設定為接收請求。 WinRM 已經進行了設定,以用於在此計算機上進行遠端管理。

  4. 啟用Powershell本地指令碼執行

    若需要在服務上執行本地指令碼,則需要啟用本地指令碼執行許可權。通過執行set-ExecutionPolicy RemoteSigned允許本地指令碼執行。

    PS C:\Users\Administrator> set-ExecutionPolicy RemoteSigned
    
    執行策略更改
    執行策略可以防止您執行不信任的指令碼。更改執行策略可能會使您面臨 about_Execution_Policies
    幫助主題中所述的安全風險。是否要更改執行策略?
    [Y] 是(Y)  [N] 否(N)  [S] 掛起(S)  [?] 幫助 (預設值為“Y”): y
  5. 獲取winrm客戶端配置資訊

    通過上述4個步驟,服務端的遠端呼叫已經開啟,由於winrm本身有白名單安全策略,因此需要配置以下客戶端的配置,允許指定的ip執行遠端呼叫。通過輸入winrm get winrm/config/client獲取客戶端配置。

    PS C:\Users\Administrator> winrm get winrm/config/client
    Client
        NetworkDelayms = 5000
        URLPrefix = wsman
        AllowUnencrypted = false
        Auth
            Basic = true
            Digest = true
            Kerberos = true
            Negotiate = true
            Certificate = true
            CredSSP = false
        DefaultPorts
            HTTP = 5985
            HTTPS = 5986
        TrustedHosts
  6. 設定白名單地址

    TrustedHosts表示的是白名單地址。
    通過Set-Item wsman:\localhost\client\trustedhosts *設定允許所有IP呼叫。
    通過Set-Item wsman:\localhost\client\trustedhosts "127.0.0.1,127.0.0.2"設定允許指定IP呼叫

    Set-Item wsman:\localhost\client\trustedhosts "127.0.0.1,127.0.0.2"
    
    WinRM 安全配置。
    此命令修改 WinRM 客戶端的 TrustedHosts 列表。TrustedHosts
    列表中的計算機可能不會經過身份驗證。該客戶端可能會向這些計算機傳送憑據資訊。是否確實要修改此列表?
    [Y] 是(Y)  [N] 否(N)  [S] 暫停(S)  [?] 幫助 (預設值為“Y”): y
    PS C:\WINDOWS\system32> winrm get winrm/config/client
    Client
        NetworkDelayms = 5000
        URLPrefix = wsman
        AllowUnencrypted = false
        Auth
            Basic = true
            Digest = true
            Kerberos = true
            Negotiate = true
            Certificate = true
            CredSSP = false
        DefaultPorts
            HTTP = 5985
            HTTPS = 5986
        TrustedHosts = 127.0.0.1,127.0.0.2
  7. 客戶端遠端呼叫

    當設定好上述配置我們就可以測試以下遠端呼叫是否完成,通過在d盤放一個hellworld.ps1指令碼,填寫以下內容。

    hello world!

    然後就可以在本地powershell中輸入以下指令測試遠端呼叫是否正常返回hello world!

    $account = "administrator"
    $password = "test1"
    $address="127.0.0.1"
    $secpwd = convertto-securestring $password -asplaintext -force
    $cred = new-object System.Management.Automation.PSCredential -argumentlist $account,$secpwd
    invoke-command -computername $address -Credential $cred  -command {d:helloworld.ps1}
    • 其中需要輸入伺服器的使用者名稱和密碼。通過convertto-securestring將明文密碼轉換為安全字串,這樣避免了明文密碼在網路上傳輸洩露。
    • 然後通過使用者名稱和密碼建立一個身份授權物件。
    • 最終通過invoke-command 將伺服器地址傳入以及授權物件傳入即可執行遠端指令碼呼叫。

升級服務

通過powershell與winrm實現遠端呼叫,服務升級就是將上傳到FTP的程式替換原有的程式即可。

啟動服務

這裡需要說明的一點是,控制檯程式和含有GUI介面的程式可以通過呼叫命令殺掉進行實現關閉程式,但是要通過powershell啟用相關的控制他程式或含有使用者介面的程式,則很難做到。主要原因是在windows環境下遠端命令執行和登入windows使用者一樣,都是基於會話執行。在Windows安全模型設計上,是不支援啟動其他會話的程式。相關問題可以檢視Use Powershell to start a GUI program on a remote machine
換句話說,在會話連線釋放時,則會自動登出會話相關的資源。因此當WinRM遠端呼叫結束後則會釋放臨時會話資源。

為了實現啟用GUI程式,可以使用PsExec。PsExec 是一款輕量級的遠端替換裝置, 可讓您在其他系統上執行程式, 併為控制檯應用程式提供完整的互動功能, 而無需手動安裝客戶端軟體。對於PsExec具體使用暫時沒有驗證過,有時間後面再做探討,這裡不進行深究。

另一種方案是Powershell所能實現的是,基於Windows的定時任務,可以設定在1分鐘後啟動GUI的exe檔案。(Windows任務最小時間單位是1分鐘)實際上來說服務中斷1分鐘可不是好事,雖然能實現啟動服務,但是不建議使用,不做過多探討。

最好的方式是將伺服器上的程式註冊為Windows服務,那麼就很好的支援服務的關閉和啟動。

總結

本文對Windows下的持續部署方案所設計到相關的技術進行了簡單介紹,後續的持續整合將完全使用本篇文章設計到的Powershell指令碼和遠端呼叫相關技術實現,後續持續整合唯一的要點就是持續整合邏輯的指令碼編寫。在後續文章中,將會介紹powershell的壓縮解壓,ftp指令碼上傳,以及通過指令碼生成差量更新包等具體工作。

  1. Windows PowerShell 入門
  2. Powershell變數的作用域
  3. Windows Remote Management
  4. windows伺服器遠端執行命令(PowerShell+WinRM)
  5. winServer-常用winrm命令
  6. Use Powershell to start a GUI program on a remote machine

本文地址:https://www.cnblogs.com/Jack-Blog/p/10922038.html
作者部落格:傑哥很忙
歡迎轉載,請在明顯位置給出出處及連結

相關文章