1. 程式人生 > >讓開發自動化 (一) : 部署自動化模式

讓開發自動化 (一) : 部署自動化模式

部署是軟體建立過程中又一個適合實現自動化的方面。通過自動化部署,可獲得一個可靠、可重複的流程,其中好處頗多:更高的準確性、更快的速度和更好的控制。在這個分兩部分的系列文章的 第 1 部分 中,我描述了 8 種部署自動化模式。在本期,我進一步擴大討論範圍,闡述另外 7 種同樣有益的部署方法:

  • Binary Integrity,確保全部目標環境使用相同的工件。
  • Disposable Container,使目標環境處於已知狀態,以減少部署錯誤。
  • Remote Deployment,確保部署可以從一個集中化的機器或叢集與多臺機器互動。
  • Database Upgrades,提供一個集中管理的、指令碼化流程,以便將增量更改應用到資料庫。
  • Deployment Test,根據最近的部署,使用部署前和部署後檢查,確認應用程式按預期執行。
  • Environment Rollback,如果部署失敗,回滾應用程式和資料庫更改。
  • Protected Files,控制對構建系統使用的某些檔案的訪問。

圖 1 解釋了本文闡述的部署模式之間的關係(未使用陰影的那些模式在 第 1 部分 中介紹過):

這 7 個附加的部署自動化模式以之前 8 個模式為基礎,它們有助於建立一鍵式(one-click)部署。

名稱:Binary Integrity

模式:對於每個標記過的部署,每個目標環境中使用相同的歸檔檔案(WAR 或 EAR)。

反模式:對於同一標記,為每個目標環境單獨進行編譯。

就這個話題與同事經過多次討論後,我最終站在了一次編譯,部署到多個目標環境 一邊,而不是在每個目標環境中編譯和打包。例如,一次 Java 開發產生的部署工件是 Web 歸檔(WAR)或企業歸檔(EAR)檔案。這個歸檔應該註冊到版本控制儲存庫中,並一次性貼上標記 — 就像在 DEV 環境中那樣。

圖 2 解釋了一次編譯,部署到多個環境 這一概念:構建機器上生成的同一個 brewery.war 被部署到每個目標環境:

Ant 提供一個 checksum 任務 — 使用 Message-Digest algorithm 5(MD5)hash 演算法 — 以確保構建機器上編譯和打包的檔案就是部署到每個目標環境的檔案。

有人會爭辯說,雖然工件可能相同,但每個目標環境的部署配置是不同的。也就是說,當使用 Single-Command、Scripted Deployment 時,無論它是否為相同的歸檔,很多自動化流程可以改變應用程式的輸出。確實如此;但是,您還需要花不必要的時間解決問題,因為在 STAGE 環境中使用與 QA 環境不同的 JDK 版本編譯和打包軟體。並且,當 DEV 中使用的來自一個集中式依賴管理儲存庫(例如 Ivy 或 Maven)的 JAR 與準備(staging)環境中的那些 JAR 不同時,失敗的機率就會增加。這些風險使我確信,為了確保二進位制程式碼的完整性,必須一次性編譯和打包,以便部署到多個環境。

名稱:Disposable Container

模式:通過將安裝和配置解耦,使 Web 和資料庫容器的安裝和配置自動化。

反模式:手動將容器安裝到每個目標環境並進行配置。

在較早一期的 讓開發自動化 文章 “持續整合反模式,第 2 部分” 中,談到了為什麼清理一個 “受汙染的” 環境有助於防止出現誤判或漏判的構建。Disposable Container 可以減少在使用永續性容器時可能出現的很多問題。Disposable Container 模式基於兩個原則:完全移除所有容器元件,以及將容器的安裝與配置分離。對於有些人,尤其是系統工程師來說,這似乎是一個極端的概念,因為不再要求由一個單獨的團隊管理和模糊化容器,不讓開發人員或其他人接觸到它們。然而,考慮到部署期間經常出現的、代價不菲的問題,它可以讓所有團隊成員的利益最大化。

一鍵式部署

經常有一些團隊和我說:“是的,我們已經實現了自動化部署。”當我問一些簡單的問題時 — 例如 “輸入一條簡單的命令(例如 ant)就可以生成一個有效的軟體應用程式嗎?” — 回答通常是這樣的:“是的,一旦安裝和配置好 Web 容器……”,或者 “是的,一旦設定好資料庫”。我對於一個真正自動化的部署的定義是,應該能夠從一臺乾淨的機器開始,安裝 Java 平臺和 Ant(有一些方法可以免除這個步驟),然後輸入一條簡單命令,即可得到一個可以正常工作的軟體應用程式。如果做不到,就不算是 “一鍵式” 部署,並且在部署過程中將出現代價不菲的人員方面的瓶頸問題。

如圖 3 所示,Disposable Container 模式基於這樣一個原則:一切都應該在系統 中 —(使用 第 1 部分 中提到的 Repository 模式)— 而不是在某個人的頭腦中。

清單 1 中的 Ant 指令碼從 Internet 下載 Tomcat ZIP,移除之前的部署殘留的任何容器,然後解壓、安裝和啟動 Tomcat:


<!-- Check to see if Tomcat is running prior to this -->
...
<exec executable="sh" osfamily="unix" dir="${tomcat.home}/bin" spawn="true">
  <env key="NOPAUSE" value="true" />
  <arg line="shutdown.sh" />
</exec>
<delete dir="${tomcat.home}" />
<get src="${tomcat.binary.uri}/${tomcat.binary.file}" 
  dest="${download.dir}/${tomcat.binary.file}" usetimestamp="true"/>
<unzip dest="${target.dir}" src="${download.dir}/${tomcat.binary.file}" />
<exec osfamily="unix" executable="chmod" spawn="true">
  <arg value="+x" />
  <arg file="${tomcat.home}/bin/startup.sh" />
  <arg file="${tomcat.home}/bin/shutdown.sh" />
</exec>
<xmltask source="${appserver.server-xml.file}"
  dest="${appserver.server-xml.file}">
  <attr path="/Server/Service[@name='${s.name}']/Connector[${port='${c.port}']" 
    attr="proxyPort" 
value="${appserver.external.port}"/>
    <attr path="/Server/Service[${name='${s.name}']/Connector[${port='${c.port}']" 
attr="proxyName"
value="${appserver.external.host}"/>
</xmltask>
<!-- Perform other container configuration -->
...
<echo message="Starting tomcat instance at ${tomcat.home} with startup.sh" />
<exec executable="sh" osfamily="unix" dir="${tomcat.home}/bin" spawn="true">
  <env key="NOPAUSE" value="true" />
  <arg line="startup.sh" />
</exec>

通過使環境處於已知狀態,並以一種受控制的方式部署容器,可以減少很多常見的、引發大部分部署難題的部署錯誤。

名稱:Remote Deployment

模式:使用一個集中式機器或叢集將軟體部署到多個目標環境。

反模式:在每個目標環境中通過手動方式在本地應用部署。

一旦安裝了資料庫和 Web 容器,讓部署在開發人員的工作站 上執行是件非常簡單的事情。然而,開發與生產之間有著巨大的差異。如果組織有多個專案和不同的目標環境(例如測試或準備環境),那麼常常需要從一個單獨的環境集中地管理部署:一臺機器或一個叢集。團隊常使用一臺構建伺服器來管理每個目標環境的部署。在 第 1 部分 中,我介紹了 Headless Execution 模式,該模式採用公共和私有金鑰,所以不必手動登入到每臺機器。如圖 4 所示,Remote Deployment 依賴於 Headless Execution、Single Command 和 Scripted Deployment 模式,因此可以方便地部署到遠端機器:

要從集中構建伺服器遠端部署軟體,需要使用一些機制安全地進行遠端複製和執行命令。我將討論的兩個機制使用 Secure Copy(SCP)和 Secure Shell(SSH)。如清單 2 所示,在 Scripted Deployment 模式下,集中構建機器上生成的 Web 歸檔被遠端地複製到一個目標環境:

<target name="copy-tomcat-dist">
  <scp file="${basedir}/target/brewery.war" 
  trust="true" 
  keyfile="${basedir}/config/id_dsa"
  username="bobama"
  passphrase=""
  todir="pduvall:[email protected]:/usr/local/jakarta-tomcat-5.5.20/webapps" />
</target>

當 WAR 檔案被安全地複製到遠端目標環境時,我就可以在 Java Secure Channel 中使用 SSHExec 之類的任務執行任何 SSH 命令,這一切都是從集中構建機器中遠端執行的。另一種方法是 ssh 到遠端環境,並在本地執行命令。這樣可以減少來回的遠端傳輸,並縮短部署時間。

名稱:Database Upgrade

模式:使用指令碼和資料庫在每個目標環境中應用增量更改。

反模式:在每個目標環境中手動應用資料庫和資料更改。

在圖 5 中,可以看到一個在 Scripted Deployment 中使用自動化指令碼更新資料庫的例子:

在較早一期的讓開發自動化 文章 “實現自動化資料庫遷移” 中,我談到了以自動化的方式應用增量資料庫更改的必要性。和 Scripted Deployment 中的其他部分一樣,資料庫更新指令碼被簽入到儲存庫中。

LiquiBase(參見 參考資料)是用於將增量更改應用到資料庫的工具,可使同樣的更改作為 Scripted Deployment 的一部分應用到每一個目標環境。在清單 3 中,一個 SQL 指令碼被作為 LiquiBase changelog 的一部分呼叫。然後,Scripted Deployment(使用一種構建指令碼工具實現 — 例如 Ant)呼叫這個 changelog(使用 XML 定義)。

<changeSet id="1" author="jbiden">
  <sqlFile path="insert-distributor-data.sql"/>
</changeSet>

要學習和應用自動化資料庫更新,還有相當多的事情要做,但其主旨是在 Scripted Deployment 中執行更新,使所有資料庫更改都在系統 中,而不是一個寫好的程式或存在某個人的頭腦中。

名稱:Deployment Test

模式:將自測試功能編寫到 Scripted Deployments 中。

反模式:通過執行手動功能測試來驗證部署,沒有關注特定於部署的方面。

圖 6 解釋了在部署前後執行部署測試的一個例子:

在清單 4 中,我使用 Ant 執行部署前測試,以確認正在使用的版本是正確的工具版本。在 Scripted Deployment 中,指令碼可以檢查正在使用的埠(這可能導致 Web 容器部署失敗),檢查與資料庫的連線,檢查容器是否已被啟動,以及很多其他內部部署測試。

<condition property="ant.version.success">
  <antversion atleast="${ant.check.version}" />
</condition>
<antunit:assertPropertyEquals name="ant.version.success" value="true" />
<echo message="Ant version is correct." />
<echo message="Validating Java version..."/>
<condition property="java.major.version.correct">
  <equals arg1="${ant.java.version}" arg2="${java.check.version.major}" />
</condition>
<antunit:assertTrue message="Your Java SDK version must be 1.5+. /
  You must install correct version.">
  <isset property="java.major.version.correct"/>
</antunit:assertTrue>

更全面的部署測試可以確保應用程式的功能性 是正確的。通過使用用於 Web 應用程式的 Selenium 或用於客戶機應用程式的 Abbot 之類的工具編寫特定於部署 的自動化功能測試,可以驗證是否已正確應用了部署更改。可以將這些測試看作冒煙測試(smoke tests):只需測試受部署影響的功能。例如,表 1 展示了使用 Selenium 和其他用於 Web 應用程式的工具的一些方式:

部署測試 描述
資料庫 編寫一個自動化功能測試,該測試將資料插入到資料庫。驗證資料是否被輸入到資料庫中。
簡單郵件傳輸協議(Simple Mail Transfer Protocol,SMTP) 編寫一個自動化功能測試,該測試從應用程式傳送一個電子郵件訊息。
Web 服務 使用 SoapAPI 之類的工具提交一個 Web 服務,並驗證輸出。
Web 容器 驗證所有容器服務是否正確執行。
輕量級目錄訪問協議(Lightweight Directory Access Protocol,LDAP) 使用應用程式,通過 LDAP 進行驗證。
日誌記錄 編寫一個測試,該測試使用應用程式的日誌記錄機制編寫日誌。

自動化測試不僅僅用於測試使用者功能。通過建立側重於部署測試的套件,可以檢驗部署的有效性,減少下游錯誤和開發成本。

名稱:Environment Rollback

模式:當部署失敗後,提供自動的 Single Command 更改回滾。

反模式:手動回滾應用程式和資料庫更改。

圖 7 解釋了回滾資料庫更改 — 使用 Database Upgrade — 以及回滾 Web 部署的自動化過程:

不管是否執行自動化部署,當部署失敗時,最好有一種方式可以回滾更改。在某些情況下,錯誤的更改可能導致系統中斷,使組織損失數百萬美元。要執行 Environment Rollback,需要讓目標環境回到部署前的狀態。為此,實際上每個更改都需要一個回滾指令碼。Web 部署常常需要回滾更多的更改。Environment Rollback 的一個例子是在部署前複製歸檔(例如一個 WAR 檔案),併為每個更改提供回滾資料庫指令碼。另外還需要重新應用已應用於 Web 容器的配置更改。

清單 6 演示了一個示例,該示例使用 LiquiBase 為每個前滾語句提供一個回滾語句。我將新增一個名為 brewery的新表,同時提供一個相應的 dropTable 回滾語句。

				
<changeSet id="rollback-database-changes" author="bobama">
  <createTable tableName="brewery">
    <column name="id" type="int"/>
  </createTable>
  <rollback>
    <dropTable tableName="brewery"/>
  </rollback>
</changeSet>

這個簡單的例子僅用於說明問題,並不意味著回滾就是這麼簡單。恢復到前一個部署常常是一個複雜的、費時的過程(需要實現自動化)。用於編寫回滾指令碼的時間應該與部署失敗付出的代價成比例。

名稱:Protected Files

模式:使用儲存庫,只允許經過授權的團隊成員共享檔案。

Antipattern:在團隊成員的機器上管理檔案,或者將檔案儲存在可由已授權團隊成員訪問的共享驅動器上。

圖 8 展示了一個受保護的版本控制儲存庫,它用於存放只有已授權人員或系統可以訪問的檔案:

在某些情況下,並不是所有團隊成員都應該訪問特定於環境的資料。但是,將該資訊與部署指令碼分離又可能使指令碼無法執行。當討論 Headless Execution 模式時,我描述了使用 SSH 金鑰和 Java Secure Channel 工具複製檔案,並安全地執行遠端命令,而不需要人為輸入命令。使用 Externalized Configuration 處理的屬性很可能包含不應該讓所有團隊成員看到的資料。為了確保實現 Headless Execution,同時防止 .properties 檔案中的資料被窺探,我使用的技巧是將這些檔案簽入到一個受保護的儲存庫中。

在清單 7 中,我配置了一個由 Apache 託管的 Subversion 儲存庫,先拒絕所有使用者訪問某個目錄,然後顯式地新增某些使用者:

<DirectoryMatch "^/.*/(/.svn)/">
  Order deny,allow
  Deny from all 
  Allow bobama,jbiden,hclinton
</DirectoryMatch>

通過保護對 Subversion 儲存庫的訪問,可以將一個 Scripted Deployment 設為被允許的使用者,使其不必輸入密碼就可以訪問屬性,從而通過 SSH 金鑰定義的方式實現 Headless Execution。

一鍵式部署

除了這份分兩部分的系列文章中描述的 15 個部署自動化模式外,我還歸納了更多的模式,但是這 15 個模式大概可以應對我遇到的 80% 的部署情況。每個模式都是為了幫助在每個目標環境中實現真正的一鍵式/單命令部署。希望您一切順利!

結束語

編寫這個系列的目的是展示如何以及為何自動化大量軟體開發過程,使開發人員可以將更多的時間花在感興趣的問題上,而不是將時間浪費在重複的、容易出錯的活動上。在這個系列中,我演示瞭如何自動化程式碼檢查以便適當地重構、增量式地升級應用程式資料庫、應用 Continuous Integration 實踐和工具、每次更改時執行自動測試、生成 GUI 安裝程式、建立一鍵式部署、使開發人員自動生成文件、執行依賴管理、利用版本控制儲存庫,以及有效地使用各種構建指令碼和工具。希望您在閱讀這個系列時能夠充滿樂趣。

相關推薦

開發自動化 () : 部署自動化模式

部署是軟體建立過程中又一個適合實現自動化的方面。通過自動化部署,可獲得一個可靠、可重複的流程,其中好處頗多:更高的準確性、更快的速度和更好的控制。在這個分兩部分的系列文章的 第 1 部分 中,我描述了 8 種部署自動化模式。在本期,我進一步擴大討論範圍,闡述另外 7 種

Python自動化開發)【未完待續】

urn sts dha sel def open entos div 初始 1、創建項目    2、創建models from django.db import models # Create your models here. # 主機表 class Host(m

自動化部署web架構

一鍵自動化 lnmp lamp 自動化安裝 逗哥自動化 一鍵自動化部署web架構 (LNMP LAMP 等github見底部) 一、前言 要實現自動化,首先要是文檔化---標準化--流程化--自動化,環境的統一是最低標準,所以我們平臺系統環境全部來源於1個腳本,這樣就可以自動化管理,減少企

自動化服務部署):Linux下安裝JDK

evel pos 的人 lis jdk安裝 參考 8.0 根據 如何 自動化測試的主要目的是為了執行回歸測試。當然,為了模擬真實的用戶操作,一般都是在UAT或者生產環境進行回歸測試。 為了盡量避免內網和外網解析對測試結果的影響,一般將自動化測試服務部署在外網的服務器是比較

雲計算Python自動化運維開發實戰: 交互模式編程

雲計算所謂交互就是跟用戶也就是我們使用python的人交互,你給出指令或代碼,python解釋器給出結果。 調用解釋器不經過腳本文件作為參數,顯示以下提示: python Python 2.7.10 (default, Jul 14 2015, 19:46:27) [GCC 4.2.1 Compatible

SpringBoot + maven + Jenkins + docker 實現docker叢集自動化部署

整體可分為以下幾個步驟:1,建立springboot專案2,搭建docker私服庫3,build映象並上傳到私服庫4,搭建docker swarm叢集5,搭建jenkins並構建部署演示系統使用centos7,jdk1.81,建立Springboot專案:在eclipse上新

003-Ambari自動化部署指令碼

    微信搜尋公眾號:BearData,關注更多內容。 根據前兩篇 “Ambari大資料平臺搭建利器(一)&(二)”, 我們已經完成大資料平臺的搭建,但是我們發現安裝Ambari的步驟比較繁瑣。我們發現手動部署存在以下的劣勢: 每個節點都要執行重複的命令,我們前

jenkins+git+maven+centos7自動化構建部署專案()

基礎環境         建議使用jdk1.5以上版本  (這裡不做jdk安裝講解,去官網下載jdk下載地址)         下載(jdk-7u45-linux-x64.tar.gz版本) jenkins安裝          執行以下命令:               

SaltStack自動化部署高可用負載均衡叢集

本節內容涉及的saltstack配置以及各服務的安裝包和配置檔案均打包上傳到了百度雲,可自由下載使用 實驗環境(rhel6.5 x86_64bit virtual machine) 172.25.5.91 salt-master rhel65-lockey1

jenkins+svn+rsync+php_自動化部署可持續化整合伺服器叢集專案_支援回滾

此文的方案支援回滾,支援回滾,支援回滾,重要的事情說三遍!前言:此文的解決方案,只能解決釋放運維一半的工作量,為何一半?因為需要部署程式碼的伺服器叢集,都事先安裝配置好專案執行所需的環境,例如java專案需要tomcat,php專案需要nginx+php-fpm等。如果問有沒

linux 自動化鍵配置rsync

linux rsync配置功能介紹1、一鍵配置rsync2、不支持多模塊或者多用戶3、-a一切隨機4、不加-a需要手動輸入賬號密碼5、進度條只是好看,並不代表真的進度#!/bin/bashusersuiji=`uuidgen | cut -c 1-10`passwdsuiji=`uuidgen | cut -

如何自動化期中50臺規模集群網站搭建

linux本文出自 “sandshell” 博客,請務必保留此出處http://sandshell.blog.51cto.com/9055959/1956938如何一鍵自動化期中50臺規模集群網站搭建

組合邏輯設計法的編程步驟-自動化

一支 功能表 整體 包括 c編程 生產 發的 工廠 結構 組合邏輯設計法適合於設計開關量控制程序,它是對控制任務進行邏輯分析和綜合,將元件的通、斷電狀態視為以觸點通、斷狀態為邏輯變量的邏輯函數,對經過化簡的邏輯函數,利用PLC邏輯指令可順利地設計出滿足要求且較為簡練的程序。

批量部署 自動化之 - [pssh](轉)

時間 provide 分發 登錄 並發 check ast 可選 git clone 並行執行命令工具簡介 作為運維工程師來講,機器數量到一定級別的時候,批量運維和管理機器就是一件費神的事情,還好有很多可以批量並行執行命令的工具,比如 pssh , python fabr

從零打造B/S 自動化運維平臺   (自動化運維平臺的應用及業務流程)

自動化運維 流程 背景以及需求: 隨著企業業務的不斷發展,運營方面,如何保障業務的高可用及服務質量?很多企業處於“半自動化”狀態,一但出現故障,技術部人員都會加入“救火”的行列,不僅浪費人力物力,而且使業務出現一段“停運時間”,給公司造成一定的損失。解決方案: 如果要解決以上問題,就需要構建一個高

運維自動化之ansible--(playbook模式)

自動化 ansible playbook 運維自動化之ansible--(playbook模式) 一、Ansible Playbook簡介 playbook是ansible用於配置,部署,和管理被控節點的劇本。 通過playbook的詳細描述,執行其中的一系列tasks,可以讓遠端主機達

深圳自動化是個怎麽的學校?

log pla 報名 技術 自動化 都沒有 電氣 咨詢 管理 一帆是深圳地區: 培訓設備較全面的培訓機構。一帆具有自編教材(與實際工程項目接軌)以及網絡教學機構。一帆PLC培訓零基礎入門,只要是願意從事自動化行業,想要靠技術拿到高薪的都可以接受,我們培養的是實戰型的自動化工

Linux環境自動化安裝oracle軟件的構想(附shell腳本)

don 服務器 ons redhat7 cif tex entos sdi class 一、自動化批量安裝ORACLE軟件的構想1、1構想從哪裏來?熟悉PXE+KICKSTART一鍵批量安裝Liunx操作系統的童鞋都知道,該方式可實現快速定制,規範化,自動化的無人值守安裝。

python全棧開發devops運維自動化方向初到高級在線課程分享

devops 運維自動化 python全棧開發 bootstrap 適用人群面向想要devops方向發展的全棧python運維開發工程師課程概述課程範圍:我們的課程由淺入深包含C01到C05五個等級;包含前後端知識,覆蓋培養一個合格python全棧工程師所需要的所有技能;還有Ca系列附加課對開

自動化服務部署(三):Linux下安裝Git

ima yum lan 參考 lease 指令 mage sta shu Git是一個開源的分布式版本控制系統,可以有效、高速的處理從很小到非常大的項目版本管理,是目前使用範圍最廣的版本管理工具。 這篇博客,介紹下Linux下安裝Git的步驟,僅供參考,當然,還是yum安裝