你可能已經聽說過“GitOps”,但並不知道它到底是什麼,除了GitOps,你可能還聽說過DevOps,或者AIOps、GOps等,是的,現在是“Ops”盛行的時代。
GitOps是一種實現持續交付的模型,它的核心思想是將應用系統的宣告性基礎架構和應用程式存放在Git的版本控制庫中。Choerodon豬齒魚在構建持續交付流水線時參考了GitOps,並進行了實踐,俗話說“兵馬未動,理論先行”,在本文中,將重點闡述GitOps工作流程的原理和模式,以及將它們應用在生產和大規模執行Kubernetes中的一些實踐經驗。
GitOps,90%的最佳實踐,10%有意思的新東西需要我們去構建。 —— 《GitOps - Operations by Pull Request》來自:www.weave.works
這篇文章是根據Weave Cloud的幾篇關於GitOps的文章翻譯整理而來:
主要內容:
- 什麼是GitOps?
- GitOps的主要優點
- GitOps的應用場景——適合雲原生的持續交付
- GitOps的基本原則
- 最佳實踐
- 拉式流水線——Pull Request操作
- GitOps工作流
- 視覺化
- 應用交付的合規性和安全的CI/CD
- GitOps帶來的價值
什麼是GitOps?
GitOps是一種持續交付的方式。它的核心思想是將應用系統的宣告性基礎架構和應用程式存放在Git版本庫中。
將Git作為交付流水線的核心,每個開發人員都可以提交拉取請求(Pull Request)並使用Git來加速和簡化Kubernetes的應用程式部署和運維任務。通過使用像Git這樣的簡單工具,開發人員可以更高效地將注意力集中在建立新功能而不是運維相關任務上(例如,應用系統安裝、配置、遷移等)。
GitOps: versioned CI/CD on top of declarative infrastructure. Stop scripting and start shipping. t.co/SgUlHgNrnY — Kelsey Hightower (@kelseyhightower) January 17, 2018
GitOps的主要優點
通過GitOps,當使用Git提交基礎架構程式碼更改時,自動化的交付流水線會將這些更改應用到應用程式的實際基礎架構上。但是GitOps的想法遠不止於此——它還會使用工具將整個應用程式的實際生產狀態與基礎架構原始碼進行比較,然後它會告訴叢集哪些基礎架構原始碼與實際環境不匹配。
通過應用GitOps最佳實踐,應用系統的基礎架構和應用程式程式碼都有“真實來源”——其實是將基礎架構和應用程式程式碼都存放在gitlab、或者github等版本控制系統上。這使開發團隊可以提高開發和部署速度並提高應用系統可靠性。
將GitOps理論方法應用在持續交付流水線上,有諸多優勢和特點:
- 安全的雲原生CI/CD管道模型
- 更快的平均部署時間和平均恢復時間
- 穩定且可重現的回滾(例如,根據Git恢復/回滾/ fork)
- 與監控和視覺化工具相結合,對已經部署的應用進行全方位的監控
GitOps應用場景——滿足雲原生環境下的持續交付
作為CI / CD流水線的方案,GitOps被描述為軟體開發過程的“聖盃”。 由於沒有單一工具可以完成流水線中所需的所有工作,因此可以自由地為流水線的不同部分選擇最佳工具。可以從開源生態系統中選擇一組工具,也可以從封閉源中選擇一組工具,或者根據使用情況,甚至可以將它們組合在一起,其實,建立流水線最困難的部分是將所有部件粘合在一起。
不管如何選擇構造自己的交付流水線,將基於Git(或者其他版本控制工具)的GitOps最佳實踐應用在交付流水線中都是一個不二選擇,這將使構建持續交付流水線,以及後續的推廣變得更加容易,這不僅從技術角度而且從文化角度來看都是如此。
當然,GitOps也不是萬能的,它也有相應的應用場景。
不可變基礎設施
應用都需要執行在多臺機器上,它們被組織成不同的環境,例如開發環境、測試環境和生產環境等等。需要將相同的應用部署到不同的機器上。通常需要系統管理員確保所有的機器都處於相同的狀態。接著所有的修改、補丁、升級需要在所有的機器中進行。隨著時間的推移,很難再確保所有的機器處於相同的狀態,同時越來越容易出錯。這就是傳統的可變架構中經常出現的問題。這時我們有了不可變架構,它將整個機器環境打包成一個單一的不可變單元,而不是傳統方式僅僅打包應用。這個單元包含了之前所說的整個環境棧和應用所有的修改、補丁和升級,這就解決了前面的問題。 —— 摘自InfoQ的《關於不可變架構以及為什麼需要不可變架構》作者 百佔輝
“不可變基礎設施”這一概念不是剛剛冒出來的,它也不是必須需要容器技術。然而,通過容器,它變得更易於理解,更加實用,並引起了業內廣泛注意。“不可變基礎設施”讓我們以全新的方式理解和麵對應用系統,尤其是使以微服務為代表的分散式系統在部署、運營等方面變得不那麼複雜,而有很好的可控性。
那麼,如何比較方便地在實際的生產過程中應用“不可變基礎設施”,這給業界也提出了另外一個問題。
GitOps是在具體Kubernetes的應用實踐中出現的,GitOps需要依託於“不可變基礎架構”才能發揮其作用。在一定程度上說,“不可變基礎架構”為GitOps的出現創造了必要的條件,反過來GitOps應用Kubernetes的容器編排能力,能夠迅速的使用映象搭建出應用系統所需的元件。
宣告性容器編排
Kubermetes作為一個雲原生的工具,可以把它的“宣告性”看作是“程式碼”,宣告意味著配置由一組事實而不是一組指令組成,例如,“有十個redis伺服器”,而不是“啟動十個redis伺服器,告訴我它是否有效”。
藉助Kubermetes的宣告性特點,應用系統的整個配置檔案集可以在Git庫中進行版本控制。通過使用Git庫,應用程式更容易部署到Kubernetes中,以及進行版本回滾。更重要的是,當災難發生時,群集的基礎架構可以從Git庫中可靠且快速地恢復。
GitOps充分利用了不可變基礎設施和宣告性容器編排,通過GitOps可以輕鬆地管理多個部署。為了最大限度地降低部署後的變更風險,無論是有意還是偶然的“配置偏差”,GitOps構建了一個可重複且可靠的部署過程,在整個應用系統當機或者損壞情況下,為快速且完全恢復提供了所需條件。
GitOps的基本原則
以下是在雲原生環境中GitOps的原則:
- 任何能夠被描述的內容都必須儲存在Git庫中
通過使用Git作為儲存宣告性基礎架構和應用程式程式碼的儲存倉庫,可以方便地監控叢集,以及檢查比較實際環境的狀態與程式碼庫上的狀態是否一致。所以,我們的目標是描述系統相關的所有內容:策略,程式碼,配置,甚至監控事件和版本控制等,並且將這些內容全部儲存在版本庫中,在通過版本庫中的內容構建系統的基礎架構或者應用程式的時候,如果沒有成功,則可以迅速的回滾,並且重新來過。
- 不應直接使用Kubectl
作為一般規則,不提倡在命令列中直接使用kubectl命令操作執行部署基礎架構或應用程式到叢集中。還有一些開發者使用CI工具驅動應用程式的部署,但如果這樣做,可能會給生產環境帶來潛在不可預測的風險。
- 呼叫Kubernetes 的API的介面或者控制器應該遵循 Operator 模式
呼叫Kubernetes 的API的介面或者控制器應該遵循 Operator 模式(什麼是Operator 模式?),叢集的狀態和Git庫中的配置檔案等要保持一致,並且檢視分析它們之間的狀態差異。
最佳實踐
以Git作為事實的唯一真實來源
Git是每個開發人員工具包的一部分。學習起來感覺自然而且不那麼令人生畏,而且工具本身也非常簡單。 通過使用Git作為應用系統的事實來源,幾乎可以操作所有東西。例如,版本控制,歷史記錄,評審和回滾都是通過Git進行的,而無需使用像kubectl這樣的工具。
所以,Git是GitOps形成的最基礎的內容,就像第一條原則“任何能夠被描述的內容都必須儲存在Git庫中 ”描述的那樣:通過使用Git作為儲存宣告性基礎架構和應用程式程式碼的儲存倉庫,可以方便地監控叢集,以及檢查比較實際環境的狀態與程式碼庫上的狀態是否一致。所以,我們的目標是描述系統相關的所有內容:策略,程式碼,配置,甚至監控事件和版本控制等,並且將這些內容全部儲存在版本庫中,在通過版本庫中的內容構建系統的基礎架構或者應用程式的時候,如果沒有成功,則可以迅速的回滾,並且重新來過。
拉式流水線——Pull Request操作
推送流水線
目前大多數CI / CD工具都使用基於推送的模型。基於推送的流水線意味著程式碼從CI系統開始,通過一系列構建測試等最終生成映象,最後手動使用“kubectl”將任何更改推送到Kubernetes叢集。
很多開發人員不願意在CI中啟動CD部署流程,或者使用命令列工具操作啟動CD部署流程的原因可能是這樣做會將叢集的使用者和密碼等公佈出去。雖然可以有措施保護CI / CD 指令碼和命令列,但是這些操作畢竟還是在叢集外部非可信區工作的。所以,類似做法是不可取的,會給系統安全帶來潛在的風險。
具有叢集外讀/寫(R/W)許可權的典型推送流水線:
- CI執行測試,輸出傳遞到容器映像儲存庫。
- CD系統自動部署容器(或根據請求,即手動)。
拉式流水線
在GitOps中,映象被拉出並且憑證保留在叢集中:
Git庫是拉式流水線模式的核心,它儲存應用程式和配置檔案集。開發人員將更新的程式碼推送到Git程式碼庫; CI工具獲取更改並最終構建Docker映象。GitOps檢測到有映象,從儲存庫中提取新映象,然後在Git配置倉庫中更新其YAML。然後,GitOps會檢測到群集已過期,並從配置庫中提取已更改的清單,並將新映象部署到群集。
GitOps的流水線
在上節中介紹了GitOps採用拉式模式構建交付流水線,本節將詳細地介紹在構建GitOps流水時需要注意哪些事情,有哪些最佳實踐。
GitOps流水線
這是一個新圖,顯示部署上游的所有內容都圍繞Git庫工作的。在“拉式流水線”中講過,開發人員將更新的程式碼推送到Git程式碼庫,CI工具獲取更改並最終構建Docker映象。GitOps的Config Update檢測到有映象,從儲存庫中提取新映象,然後在Git配置倉庫中更新其YAML。然後,GitOps的Deploy Operator會檢測到群集已過期,並從配置庫中提取已更改的清單,並將新映象部署到群集。
使用群集內部的Deploy Operator,群集憑據不會在生產環境之外公開。一旦將Deploy Operator安裝到叢集與Git倉庫建立連線,線上環境中的任何更改都將通過具有完全回滾的Git pull請求以及Git提供的方便審計日誌完成。
自動git→叢集同步
由於沒有單一工具可以完成流水線中所需的所有工作,可以從開源生態系統中選擇一組工具,也可以從封閉源中選擇一組工具,或者根據使用情況,甚至可以將它們組合在一起,其實,建立流水線最困難的部分是將所有部件粘合在一起。要實現GitOps,必須要開發出新的元件,用於粘合這些工具,實現拉式交付流水線。
部署和釋出自動化是應用落實GitOps,並使交付流水線工作的基礎。GitOps不僅要保證,當開發人員通過Git更新配置檔案集的時候,GitOps流水線要自動根據最新的配置檔案狀態更新線上環境,而且GitOps還要能夠實時比對Git庫中配置檔案集最新的狀態與線上環境最新的狀態保持一致。
在上節中提到了兩個名詞:Config Update 和 Deploy Operator,根據GitOps的實踐,Config Update 和 Deploy Operator是需要進行設計開發的,它們是實現GitOps流水線必須的關鍵元件。GitOps賦予了它們神奇的魔法,它們既是自動化容器升級和釋出到線上環境的工具,可能也要負責服務、部署、網路策略甚至路由規則等任務。因此,Config Update 和 Deploy Operator是對映程式碼,服務和執行叢集之間所有關係的“粘合劑”。
當然,您可以根據具體的設計,賦予各種其他的功能,但是自動同步是一定需要的,確保如果對儲存庫進行任何更改,這些更改將自動部署到線上環境中。
僅部署容器和配置
GitOps建議不直接將應用程式部署到線上環境中,而是將應用程式和相關配置打包成映象,並儲存到映象庫中,最後,通過映象的方式生成容器,並部署到線上環境中。
容器為什麼如此重要?在GitOps模型中,我們使用不可變基礎架構模式。一旦程式碼在Git中提交,GitOps就不希望任何其他內容發生變化,這樣可以最大限度地降低系統潛在不確定性、不一致性風險。例如,需要將相同的應用部署到不同的機器上。通常需要系統管理員確保所有的機器都處於相同的狀態。接著所有的修改、補丁、升級需要在所有的機器中進行。隨著時間的推移,很難再確保所有的機器處於相同的狀態,同時越來越容易出錯。然而,容器是比較完美地解決了這個問題,當然,使用虛擬機器是可以的,顯然使用容器更加方便。
GitOps的可觀察性
“可觀察性就像生產中的驅動測試一樣。如果你不知道如何確定它是否正常工作,請勿接受 pull request。@mipsytipsy “ - Adriano Bastos複製程式碼
在GitOps中,使用Git庫來儲存應用系統的配置文集和應用程式,它確保開發人員將所有對於應用系統的配置和程式的新增、修改等都通過Git庫進行版本控制,使Git成為配置和程式的唯一真實來源。而GitOps的可觀察性則是確保線上環境的真實狀態與Git庫中的保持一致性。本章節將給大家介紹GitOps的可觀察性。
可觀察性是另一個真理來源
在GitOps中,我們使用Git作為系統所需狀態的真實來源。例如,如果應用系統當機,GitOps可以回滾到之前正確狀態。而可觀察性是系統實際執行狀態的真實來源,系統開發人員或者運維人員可以監控系統的狀態。這是一張顯示流程的圖片。
通過觀察需尋找問題的答案
如果大家使用Kubernetes作為雲原生環境和容器編排工具,相信大家會有這樣的感觸,雖然Kubernetes是一個非常棒的編排容器平臺,但是隨之而來的缺乏友好的視覺化管理介面給開發人員或者運維人員帶來諸多不便。例如:
- 我的部署成功了嗎?我的系統現在處於工作的狀態,我現在可以回家嗎?
- 我的系統與以前有什麼不同?我可以使用Git或我們的系統歷史記錄來檢查嗎?
- 我的改變是否改善了整體使用者體驗?(與系統正確性相對)
- 我在資訊中心找不到我的新服務(例如RED指標)
- 這個故障是否與我上次的服務更新事件有關,還是和其他操作有關係?
大家可能會想到通過監控伺服器的CPU、記憶體、網路等,以及應用的日誌,甚至微服務的呼叫鏈等來解決問題。是的,這個沒有錯,能夠得到一些反饋資訊,但是使用過類似監控的開發人員或者運維人員也會感覺,這些監控儀表盤給我們大量冗繁的資訊,需要認真地甄別,而且有很多資訊在這些儀表盤中是獲得不到的。這意味著需要建立新的儀表盤,用於監控新的指標和內容。
GitOps的可觀察性
可觀察性可被視為Kubernetes 持續交付週期的主要驅動因素之一,因為它描述了在任何給定時間系統的實際執行狀態。觀察執行系統以便理解和控制它。新功能和修復程式被推送到git並觸發部署管道,當準備好釋出時,可以實時檢視正在執行的叢集。此時,開發人員可以根據此反饋返回到管道的開頭,或者將映像部署並釋放到生產叢集。
在這裡GitOps引入一個新的工具:Diffs,用來監控對比系統狀態。即:
- 驗證當前線上系統的狀態是否和Git庫中描述的狀態一致,例如,我上一次釋出是否符合期望?
- 提醒開發人員不一致狀態,以及相應的明細資訊。
在文章前面講過,在Git庫中儲存的實際上是“宣告性基礎設施”,例如Kubernetes的YAML檔案,用以構建應用系統所需的各種元件、域名、網路等配置資訊。Diffs需要讀取Git庫中配置資訊,同時,通過API等讀取叢集的相應資訊,並進行比對。
例如,Kubernetes叢集:所需的Kubernetes狀態可能是“有4個redis伺服器”。Diffs定期檢查群集,並在數量從4變化時發出警報。一般而言,Diffs將YAML檔案轉換為執行狀態查詢。
GitOps是面向釋出的操作模型,請參見下圖。交付速度取決於團隊在此週期中繞過各個階段的速度。
應用交付合規性和安全性
由於以安全的方式跟蹤和記錄更改,因此合規性和審計變得微不足道。使用Diffs等比較工具還可以將Git庫中定義的叢集狀態與實際執行的叢集進行比較,從而確保更改與實際情況相符。
在Git中記錄所有的操作日誌
通過上面文章的敘述,開發人員或者運維人員通過Git作業系統配置和應用程式的新建和更新等。通過Git客戶端git commit /git merge的所有操作都會Git庫記錄下來,審計員可以檢視Git,看看誰做了任何更改,何時以及為何以及如何影響正在執行的系統部署。當然,可以根據自身的需求定製不同的交付合規性。相較於直接進入伺服器操作或者通過Kubctl操作叢集,Git記錄了每一個操作步驟,這些可以為合規性和審計提供完整的操作日誌。
角色和許可權控制
幾乎所有的Git庫都提供角色和許可權控制,與開發和運維無關的人員沒有許可權操作Git庫。而不是直接把伺服器或者叢集的操作許可權散發出去,這樣特別容易引起安全洩露。
GitOps帶來的好處
更加快速地開發
藉助GitOps的最佳實踐,開發人員可以使用熟悉的Git工具,便捷地將應用程式和其對應的配置檔案集持續部署到Kubernetes等雲原生環境,提高業務的敏捷度,快速地相應使用者的需求,有助於增加企業市場的競爭力。
更好地進行運維
藉助GitOps,可以實現一個完整的端到端的交付流水線。不僅可以實現拉式的持續整合流水線和持續部署流水線,而且系統的運維操作可以通過Git來完成。
更強大的安全保證
幾乎所有的Git庫都提供角色和許可權控制,與開發和運維無關的人員沒有許可權操作Git庫。而不是直接把伺服器或者叢集的操作許可權散發出去,這樣特別容易引起安全洩露。
更容易合規的審計
由於以安全的方式跟蹤和記錄更改,因此合規性和審計變得微不足道。使用Diffs等比較工具還可以將叢集狀態的可信定義與實際執行的叢集進行比較,從而確保跟蹤和可審計的更改與實際情況相符。
關於Choerodon豬齒魚
Choerodon豬齒魚是一個開源企業服務平臺,是基於Kubernetes的容器編排和管理能力,整合DevOps工具鏈、微服務和移動應用框架,來幫助企業實現敏捷化的應用交付和自動化的運營管理的開源平臺,同時提供IoT、支付、資料、智慧洞察、企業應用市場等業務元件,致力幫助企業聚焦於業務,加速數字化轉型。