IaC Part20-團隊工作流程
使用代碼來建構和更改基礎設施是一種與傳統方法截然不同的作業方式。 我們間接變更VM和網路配置,而不是透過在提示下key in command或直接編輯配置檔。 編寫代碼然後將其應用到自動化系統中比學習新工具或技能是一個更大的轉變。
IaC改變了參與"設計、建構和管理"基礎設施的個人和團隊的作業方式。 本文在解釋不同的人如何處理基礎設施代碼。 基礎設施的工作流程涉及設計、定義和應用代碼。
管理IaC的團隊的有效流程的一些特徵包括:
- 自動化流程是團隊成員進行更改的最簡單、最自然的方式。
- 技術人員有明確的方法來確保品質、可操作性和政策一致性。
- 團隊能使其系統保持最新狀態。 事情是一致的 — — 在適當的地方,在需要變化的地方,它們都是清晰且管理良好的。
- 團隊對系統的理解嵌入在代碼中,其運作方式在自動化中得到闡明。
- 錯誤很快就會被發現並且很容易糾正。
- 更改定義系統的代碼以及測試和交付該代碼的自動化操作既簡單又安全。
總的來說,良好的自動化工作流程足夠快,可以在緊急情況下修復系統,這樣技術人員就不會試圖進行手動變更來修復它。 而且它足夠可靠,技術人員對它的信任程度超過了他們對自己手動在即時系統上進行配置的信任程度。
本文與最終章都在討論團隊如何處理基礎架構代碼的要素。 重點介紹技術人員在工作流程中所做的事情,而下一章則著重於組織和管理基礎設施代碼庫的方法。
技術人員
可靠的自動化 IT 系統就像 Soylent Green — — 其秘密成分是人。 雖然生產系統中不需要技術人員的手來進行代碼更改,但除了查看測試結果和點擊幾個按鈕之外,還需要技術人員不斷"建置、修復、調整和改進"系統。
大多數基礎設施系統(自動化或其他方式)都涉及一些角色。 這些角色通常不會與個人一一對應 — — 有些人扮演多個角色,有些角色則有多人擔任:
使用者
誰直接使用基礎建設? 在許多組織中,大該都是開發團隊。 這些團隊可以開發應用程式,也可以配置和管理第三方應用程式。
治理專家
許多人為各領域的環境制定政策,包括安全性、法律合規性、架構、效能、成本控制和正確性。
設計者
設計基礎設施的人。 在某些組織中,這些人是架構師,可能分為不同的領域,例如網路或儲存。
工具製造者
提供其他團隊用來建置或運行環境的服務、工具和組件的人員。 範例包括建立可重複使用基礎設施代碼庫的監控團隊或開發人員。
建置者
建置和改變基礎設施的人。 他們可以透過控制台或其他介面、運行腳本或基礎設施代碼的工具來手動執行此操作。
測試者
驗證基礎設施的人。 這個角色不僅限於 QA(品質分析師)。 它包括測試或審查安全或效能等治理領域系統的人員。
維運人員
確保系統繼續正確運作並在系統出現問題時進行修復的人員。
下圖顯示了一個典型的結構,系統變更工作流程的每個部分都有一個專門的團隊。
許多角色可能會跨不同的基礎設施領域劃分,例如網路、儲存或伺服器。 它們還可能跨越多個治理領域,如安全性、合規性、架構和效能。 許多較大的組織創建了巴洛克式的微型專業組織結構。
然而,個人或團隊跨職責的工作也很常見(因為公司沒哪麼大)。 例如,資安團隊可能會制定標準、提供掃描工具並進行安全稽核。 本文稍後我們將探討重新調整職責的方法。
誰來寫代碼
以下是組織回答誰來編寫和編輯基礎設施代碼問題的幾種不同方式:
建置者
一些組織試圖保留傳統的流程和團隊結構。 因此,建置(也有可能是維運人員)基礎架構的團隊使用IaC工具來優化其作業。 使用者請求一個環境,建置團隊使用其工具和腳本建立環境。
治理專家與測試者
制定政策和標準的人以及需要確保變更沒有問題的人可以創建工具來幫助其他人驗證自己的代碼。 這些人可能成為工具製造者或與工具製造者密切合作。
使用價值流程圖改善作業流程
價值流程圖是分解交付週期的有效方法,因此我們可以了解整個等待時間。 透過量測花在各種活動(包括等待)上的時間,我們可以將改進重點放在最花時間的領域。 我們經常優化流程中看似效率最低但對總交付時間影響不大的部分。 例如,團隊實施自動化,將配置伺服器所需的時間從八小時縮短到十分鐘。 配置伺服器的時間大幅減少了 98%。 然而,如果使用者通常等待十天才能有新伺服器,那麼總的下降幅度就遠不如 10% 那樣令人興奮。 如果伺服器請求票證在作業清單中平均等待八天,那麼我們應該將精力集中在那裡。
價值流圖使完成行動的時間可見,以便可以找到最佳的改進機會。 在做出改進的同時,繼續衡量端到端的交付時間和其他指標(例如故障率)。 這樣做有助於避免對流程的某一部分進行最佳化,從而使整個流程變得更糟。
套用代碼到基礎設施
更改基礎架構的典型作業流程從共享來源儲存庫中的代碼開始。 團隊成員將最新版本的代碼pull到他們的工作環境中並在那裡進行編輯。 當他們準備好後,他們將代碼push到原始代碼儲存庫中,並將新版本的代碼應用到各種環境中。
許多人在開始基礎設施自動化時從工作環境中的命令列運行工具。 然而,這樣做有陷阱。
從本地工作站套用代碼
從命令列套用基礎設施代碼對於沒有別人在使用的基礎設施的測試實例非常有用。 但是,從本機工作環境執行該工具會導致基礎架構共用實例出現問題,無論是生產環境還是交付環境。
這個人可能會在套用代碼之前對其本地版本的代碼進行更改。 如果他們在將變更推送到共用儲存庫之前套用代碼,那麼其他人就無法存取該版本的代碼。 如果其他人需要調試基礎設施,這可能會導致問題。
如果套用本機版本代碼的人沒有立即推送他們的更改,其他人可能會拉取並編輯舊版本的代碼。 當他們應用該代碼時,他們將覆蓋第一個人的更改。 這種情況很快就會變得令人困惑且難以釐清(如下圖)。
請注意,鎖定解決方案(例如 Terraform 的狀態鎖定)並不能防止這種情況。 鎖定可以阻止兩個人同時將代碼應用到同一個實例。 但是,截至撰寫本文時,鎖定解決方案並不能阻止技術人員套用不同版本的代碼,只要他們每個人都等待輪到他們。
因此,教訓是,對於任何基礎設施實例,代碼應始終從同一位置套用。 我們可以指定一個人負責每個實例。 但這有很多陷阱,包括對一個人和他們的工作站的危險依賴。 更好的解決方案是擁有一個處理共享基礎設施實例的中央系統。
從集中式系統套用代碼
我們可以使用集中式服務將基礎架構代碼套用到實例,無論是自己託管的應用程式還是第三方服務。 該服務從原始碼儲存庫或工件儲存庫中pull code,並將其套用到基礎設施,從而實施清晰、受控的流程來管理應用程式的代碼版本。
如果兩個人pull和編輯代碼,他們在將代碼與工具使用的分支整合時必須解決代碼中的任何差異。 當出現問題時,很容易看出應用了哪個版本的代碼並進行修正(如下圖)。
集中式服務還確保基礎設施工具的運作一致化,而不是假設人員不會犯錯或「改進(其實是偏離)」作業流程。 它每次都使用相同版本的工具、腳本和支援實用程式。
使用集中式服務與跨環境交付基礎設施代碼的流水線模型非常一致。 無論使用什麼工具或服務來協調流水線中的變更,都將負責運作基礎設施工具以將最新版本的代碼套用到每個環境。
讓集中式服務執行基礎設施代碼的另一個好處是,它迫使的團隊自動化整個流程。 如果從工作站執行工具,很容易留下一些未解決的問題,即執行該工具之前或之後需要手動執行的步驟。 除了確保任務完全自動化之外,集中式服務是最好的選擇。
個人基礎設施實例
在本系列文章中討論的大多數作業流程中,我們會pull code、編輯代碼,然後將其push到共用代碼儲存庫中。 然後透過流水線交付流程將其套用到相關環境中。
理想情況下,我們可以在將代碼變更push到共用儲存庫之前對其進行測試。 這樣做可以確保變更達到預期,並且比等待流水線將代碼運行到線上測試階段更快。 當一項變更在流水線階段失敗時,它還有助於避免破壞構建,從而擾亂在代碼庫上工作的每個人。
團隊可以做一些事情,以便在Push之前更輕鬆地測試代碼變更。
首先,確保每個處理基礎架構程式碼的人都可以建立自己的基礎架構實例。 如在"IaC Part 9 測試Infra Stacks"一文中的「堆疊的離線測試階段」中所述,技術人員在沒有雲端平台的情況下可以在本機測試的內容是有限的。我們可能會想要執行基礎架構的共用「開發」實例。 但如前所述,讓多人將本地編輯的代碼套用於共用實例會變得混亂。 因此,請建立一種方法,讓技術人員啟動自己的基礎設施實例。
其次,保持基礎設施的各個部分較小。 我們應該能夠自行啟動系統任何組件的實例,也許可以使用測試裝置來處理依賴性。 如果技術人員需要啟動整個系統,那麼他們很難在個人實例上作業,除非系統非常小。
第三,技術人員應該使用相同的工具和腳本來套用和測試與共用實例一起使用的基礎設施實例,例如在流水線中。 它有助於為我們可以在這些不同位置使用的工具和腳本建立套件。
工作流程中的原始碼分支
分支(Branches)是共享原始碼儲存庫的一項強大功能,它使技術人員可以更輕鬆地對代碼庫的不同副本(分支)進行變更,然後在準備好時整合他們的作業。 使用分支作為團隊工作流程的一部分有許多策略和模式。 這裡不會詳細闡述它們,可以參考 Martin Fowler 的文章「管理原始碼分支的模式」。
值得強調的是,在IaC的背景下,分支策略的一些差異。 一是生產路徑模式和分支整合模式的差別。 另一個是整合頻率的重要性。
團隊使用生產分支模式的路徑來管理要套用於環境的代碼版本。 生產模式的典型路徑包括發布分支和環境分支。
分支整合模式描述了代碼庫工作人員管理"何時以及如何"整合其作業的方法。 大多數團隊使用主線整合模式,無論是功能分支還是持續整合。
具體的模式或策略並不重要,重要的是如何使用它。 團隊使用分支有效性的最重要因素是整合頻率,即每個人將所有代碼合併到中央儲存庫的相同(主)分支的頻率。 DORA Accelerate 研究發現,團隊內所有代碼的更頻繁整合與更高的業務績效相關。 他們的結果表明,團隊中的每個人都應該每天至少將所有代碼整合在一起(例如,整合到main或trunk)。
合併(Merging)不是整合(Integration)
技術人員有時會將自動在分支上執行測試的建置伺服器與持續整合混淆。 持續整合的實踐以及與更高團隊績效的相關性是基於完全整合每個人正在代碼庫中進行的所有變更。
儘管使用功能分支模式的人可能會經常將當前主分支合併到自己的分支,但他們通常不會將自己的作業整合回主分支,直到他們完成功能的作業。 如果其他人在自己的功能分支上以相同的方式作業,那麼直到每個人都完成他們的功能並將他們的變更合併到主分支之前,代碼才完全整合。
整合涉及兩個方向的合併 — — 個人將自己的變更合併到主分支,以及將主分支合併回他們自己的分支或代碼的本地副本。 因此,持續整合意味著每個人在作業時都這樣做,每天至少一次。
預防配置(Configuration)飄移
IaC Part 2 — 原則一文中描述了配置漂移的危險,其中類似的基礎設施元素隨著時間的推移會變得不一致。 當團隊使用基礎設施編碼工具來自動化部分舊作業方式,而不是完全適應他們的作業方式時,通常會導致配置漂移。 我們可以在工作流程中執行多項操作來避免配置漂移。
最大限度地減少自動化滯後(lag)
自動化滯後是執行自動化流程(例如套用基礎架構代碼)的實例之間經過的時間。 距離上次運行流程的時間越長,失敗的可能性就越大。隨著時間的推移,事情會發生變化,即使沒有人有意識地做出改變。 即使代碼沒有更改,在很長一段時間後套用它仍然可能會失敗,原因有很多:
- 有人更改了系統的另一部分,例如依賴項,其方式只有在重新套用代碼時才會中斷。
- 用於套用代碼的工具或服務的升級或設定變更可能與代碼不相容。
- 儘管如此,套用未更改的代碼可能會帶來傳遞依賴項的更新,例如作業系統套件。
- 有人可能進行了手動修復或改進,但他們忽略了將其折疊回代碼中。 重新套用代碼可以恢復修復。
自動化滯後的必然結果是,套用基礎設施代碼越頻繁,失敗的可能性就越小。 當故障確實發生時,可以更快地發現原因,因為自上次成功運行以來發生的變化較少。
避免一次性套用
一些團隊從地端機房時代的作業方式中繼承的一個習慣是僅套用代碼來進行特定的變更。 他們可能只使用基礎設施代碼來配置新的基礎設施,而不是對現有系統進行更改。 或者他們可以編寫並套用基礎設施代碼來對其系統的特定部分進行一次性更改。 例如,他們為其一台應用程式伺服器編寫了一次性配置更改代碼。 即使團隊使用代碼進行更改並將代碼套用於所有實例,有時他們也可能僅在對代碼進行更改時才套用代碼。 這些習慣可能會造成配置漂移或自動化延遲。
持續套用代碼
消除配置漂移的核心策略是持續將基礎設施代碼套用於實例,即使代碼沒有變更。 許多伺服器配置工具(包括 Chef 和 Puppet)旨在按schedule(通常每小時)重新套用配置。
GitOps 方法涉及將原始代碼分支中的代碼持續套用到每個環境。 我們應該能夠使用中央服務來套用代碼,以不斷地將代碼重新套用到每個實例。
不可變的基礎設施
不可變基礎設施以不同的方式解決配置漂移問題。 無需頻繁地將組態代碼套用到基礎架構實例,只需在建立實例時套用一次。 當代碼變更時,建立一個新實例並將其替換為舊實例。
透過建立新實例進行更改需要複雜的技術來避免停機,並且可能不適用於所有狀況。 自動化滯後仍然是一個潛在的問題,因此使用不可變基礎架構的團隊往往會頻繁地重建實例,就像 phoenix 伺服器一樣。
GitOps
GitOps 是IaC的變體,是將代碼從原始碼分支持續同步到環境。 GitOps 強調將系統定義為代碼。
GitOps 沒有規定測試和交付基礎設施代碼的方法,但它與使用流水線交付代碼相容。 然而,GitOps 不鼓勵使用交付工件,而是透過將代碼合併到原始代碼分支來促進程式碼變更。
GitOps 的另一個關鍵要素是持續將代碼同步到系統。 GitOps 不是讓建置伺服器作業或流水線階段在代碼變更時套用代碼,而是使用連續將代碼與系統進行比較的服務,從而減少配置偏差。
有些團隊將他們的流程描述為 GitOps,但只實現了環境實踐的分支,而沒有持續將代碼同步到環境。 這使得很容易陷入一次性變更流程,以及根據複製貼上的反模式為每個環境複製、貼上和編輯代碼更改的壞習慣。
基於流水線的工作流程中的治理
治理是大多數組織所關心的問題,尤其是較大的組織和那些在金融和醫療保健等受高度監管產業的組織。 技術人員大都很討厭治理一詞,這意味著在完成有用的作業時增加不必要的麻煩。 但治理只是意味著確保根據組織的政策負責任地完成工作。
基礎設施即代碼(IaC) Part-1 概念一文解釋了品質(治理是品質的一個面向)可以提高交付速度,而快速交付變更的能力可以提高品質。 Compliance as Code利用自動化和更具協作性的作業實踐來使這種良性循環發揮作用。
職責重組
將系統定義為代碼創造了重新調整參與基礎設施工作的人員的職責以及這些人員參與工作的方式的機會。 創造這些機會的一些因素是:
重複使用
基礎設施代碼可以在多個環境和系統中進行設計、審查和重複使用。 如果使用已經完成流程的代碼,則不需要為每個新伺服器或環境進行冗長的"設計、審查和核可"作業。
用代碼工作
由於代碼編寫速度很快,因此技術人員可以根據作業代碼和範例基礎架構進行審查並做出決策。 與在圖表和規格上討價還價相比,這可以實現更快、更準確的反饋循環。
一致性
代碼創建的環境比照著作業清單進行作業的人類更一致。 因此,在早期環境中測試和審查基礎設施比在流程後期進行這些測試和審查可以提供更快、更好的回饋。
自動化測試
自動化測試(包括安全性和合規性等治理問題)為基礎設施代碼工作人員提供快速回饋。 他們可以在作業時糾正許多問題,而無需讓專家來解決日常問題。
品質民主化
非專家的人可以更改基礎設施潛在敏感領域的代碼,例如網路和安全策略。 他們可以使用專家創建的工具和測試來健全地檢查他們的變更。 專家仍然可以在將變更套用於生產系統之前對其進行審查和批准。 這種審查方式更有效率,因為專家可以直接查看代碼、測試報告和工作測試實例。
治理管道
可以根據其治理要求讓管理基礎設施程代碼庫和用於向生產實例交付變更的管道。 因此,對安全性策略的變更需要經過審核和簽署步驟,而對較不敏感區域的變更不一定需要此步驟。
左移
我們在"IaC Part 8-持續測試與交付"一文中討論了實施自動化測試和流水線以將代碼變更交付到環境的原則和實踐。 術語"左移"描述了這如何影響工作流程和交付實踐。
代碼在實作過程中經過嚴格測試,位於大多數流程圖所示流程的「左」端。 因此,在將代碼應用到生產之前,組織可以在「正確」端的重量級流程上花費更少的時間。
參與治理和測試的人員重點關注實施過程中發生的情況、與團隊合作、提供工具以及使實踐能夠儘早且經常進行測試。
IaC與治理的範例流程
ShopSpinner 有一個可重複使用堆疊,可用於為應用程式伺服器建立基礎架構,以便為客戶託管其服務實例。 當有人更改此堆疊的代碼時,可能會影響其所有客戶。
其技術領導小組負責架構決策,定義應用伺服器基礎架構必須支援的 CFR(Cross-Functional Requirements)。 這些 CFR 包括使用者可以在客戶實例中下訂單的數量和頻率、介面的回應時間以及伺服器故障的恢復時間。
基礎設施團隊和應用程式團隊與一對 SRE 和 QA 一起實施一些自動化測試,根據 CFR 檢查應用程式伺服器堆疊的效能。 他們將這些測試建置到流水線的幾個階段中,逐步測試堆疊的不同組件。
一旦團隊完成這些測試,技術人員就不需要提交基礎架構變更以供技術領導團隊、SRE 或其他任何人審核。 例如,當工程師變更網路配置時,流水線會自動檢查產生的基礎架構是否仍符合 CFR,然後才能進行變更。將其應用於生產客戶執行個體。 如果工程師犯了一個破壞 CFR 的錯誤,他們會在幾分鐘內發現流水線階段何時變紅燈,並且可以立即糾正。
在某些情況下,變更可能會導致客戶實例出現問題,而自動化測試無法擷取該問題。 該小組可以進行事後剖析(不須指責任何人,有問題的是體系),以回顧所發生的事情。 也許問題在於沒有一個 CFR 涵蓋了這種情況,因此他們需要更改 CFR 或將其添加到清單中。 或者他們的測試可能存在遺漏問題的差距,在這種情況下他們會改進測試套件。
正規化緊急修復程序
許多團隊都有單獨的緊急變更流程,以便他們可以快速提供修復。 需要一個單獨的流程來更快地修復,這表明正常的變更流程可以改進。
緊急變更流程可以透過以下兩種方式之一加快速度。 一是省略不必要的步驟。 另一種是省略必要的步驟。 如果可以在緊急情況下安全地留下一個步驟,當壓力很大且風險很高時,我們可能可以將其排除在正常流程之外。 如果跳過某個步驟的風險令人無法接受,那麼就找到一種更有效地處理它的方法,並且每次都這樣做。
結論
當組織將其基礎設施定義為代碼時,其員工應該會發現自己花在執行日常活動和充當看門人上的時間更少。 相反,他們應該花更多的時間不斷提升自己改進系統本身的能力。 他們的精力將反映在軟體交付和營運績效的四個指標中。