DevOps 日漸成爲研發人員耳熟能詳的一個組合詞,但什麼是 DevOps,爲什麼 DevOps 對於互聯網企業如此重要,真正將其思考透徹的人卻不多,帶着這些困惑,本文將帶你一探 DevOps 的起源、原則和實踐,讓你搞清楚到底何爲 DevOps。
DevOps 的起源可以追溯到 2008 年,在一次敏捷大會的敏捷基礎設施話題組被提及,從起源我們可以瞭解到 DevOps 的發展跟敏捷軟件開發是密不可分的。
DevOps 定義
DevOps 經過這些年的發展,其定義也在不斷變化,先來看三段 DevOps 的 wiki 定義。
1、DevOps 2017 - 2020 年英文 wiki 定義(直譯)
DevOps是一種軟件工程文化和實踐(Practices),旨在整合軟件開發和軟件運維。DevOps運動的主要特點是強烈倡導對構建軟件的所有環節(從集成、測試、發佈到部署和基礎架構管理)進行全面的自動化和監控 DevOps 的目標是縮短開發週期,提高部署頻率和更可靠地發佈,與業務目標保持一致。
2、DevOps 2021 年英文 wiki 定義(直譯)
DevOps 是一系列整合軟件開發和軟件運維活動的實踐(Practices)。目標是縮短軟件開發生命週期並使用持續交付提供高質量的軟件。
另:
DevOps 與敏捷軟件開發是互補關係,DevOps 的許多方面來自於敏捷方法論。
3、DevOps 中文 wiki 定義
DevOps(Development和Operations的組合詞)是一種重視“軟件開發人員(Dev)”和“IT運維技術人員(Ops)”之間溝通合作的文化、運動或慣例。透過自動化“軟件交付”和“架構變更”的流程,來使得構建、測試、發佈軟件能夠更加地快捷、頻繁和可靠。
提取這三段的共同點,可以看到不論定義如何變化,DevOps 所要實現的目標都是一致的——縮短軟件開發生命週期並使用 持續交付 提供高質量的軟件。由於持續交付活動中包含了構建、測試和發佈等活動,我更傾向於用這個定義,可以更好地縮減定義長度。
另外可以看到英文直接翻譯過來的定義中都包含「實踐」 一詞,而中文 wiki 經過一定的翻譯或本地化後變成了「文化、運動或慣例」,其還更強調開發運維之間溝通合作這一點,因此將最新的英文 wiki 定義與中文 wiki 定義相結合,可以幫助我們更好地理解 DevOps,那麼它的最終定義是什麼就交由讀者朋友自己去領會吧。
DevOps 發展背景
爲什麼 DevOps 會如此熱門,時常被人所提及,這與其發展背景是分不開的,主要原因可以概括爲以下幾點:
敏態需求的增加,即探索性工作的增加;
軟件開發從傳統的瀑布流方式到敏捷開發,再到現在對敏捷開發提出了更高的要求,近些年創新型的應用不斷湧現,在這些應用的研發過程中多采用小步快跑、快速試錯的方式,這些探索性工作要求運維能夠具備一天發佈多次的能力,需要企業完成由穩態到敏態的轉變。
軟件開發活動在企業經營活動中佔比的不斷增加;
業務發展對軟件的依賴由輕度依賴、中度依賴發展到目前的重度依賴。
企業存在對消除浪費的需求。
軟件開發活動在企業中的位置越來越重要,而像企業經營活動一樣,軟件開發活動中也存在着許多的浪費,企業管理上必然存在着識別並消除浪費的需求。
軟件開發中的浪費包括不必要和必要的浪費,不必要的浪費有:無人使用的功能、軟件bug、等待測試、等待審批等;必要的浪費包括:工作項移交、測試、項目管理等。
以上主要從企業的角度說明了 DevOps 的發展,這是較爲深層次的原因,表層的推動因素包括:容器化技術的發展、微服務架構的發展等等,這些技術上的創新爲 DevOps 提供了良好的發展條件,以解決企業面臨的這些問題。
DevOps 原則與實踐
瞭解了什麼是 DevOps 及其發展原因後,又該如何具體的進行 DevOps 實踐,我們採用黃金圈法則來思考這一問題。
DevOps 原則是總體指導思想,實踐是具體的執行方法,DevOps 是一個動態的過程,在進行相關實踐的時候可以看看其應用了哪些原則,當違背原則的時候需要思考實踐的合理性。
DevOps 原則
DevOps 包含以下三大原則:
流動原則:加速從開發、運維到交付給客戶的流程;
反饋原則:建設安全可靠的工作體系;
持續學習與實驗原則:採用科學的工作方式,將對組織的改進和創新作爲工作的一部分。
流動原則
堅持少做
產品開始開發時採用 MVP 原則。
產品迭代時要適時做減法。
持續分解問題
大的變更或需求拆解爲一系列小的變更,快速解決。
工作可視化
採用 Sprint 看板將工作可視化。
控制任務數量
減少前置時間,降低測試人員的等待時間。
任務越多,預估越不準確。
減少交接次數
減少不必要的溝通和等待。
持續識別和改善約束點
識別出影響流動的主要前置因素,比如搭建環境、需求文檔。
QA、開發、運維、產品持續提升生產力。
爲非功能性需求預留20%的開發時間,減少技術債務。
消除價值流中的困境和浪費(導致交付延遲的主要因素)
半成品——未完全完成的工作。
額外工序——從不使用的文檔、重複編寫接口文檔等。
額外功能——用戶實際不需要的功能。
任務切換——將人員分配到多個項目或截然不同的工作任務中。
等待、移動、缺陷、非標準化的手動操作。
反饋原則
在複雜系統中安全地工作
管理複雜的工作,識別出設計和操作的問題;
羣策羣力解決問題,從而快速構建新知識;
在整個組織中,將區域性的知識應用到全局範圍;
領導者要持續培養有以上才能的人。
及時發現問題
快速、頻繁和高質量的信息流——每個工序的操作都會被度量和監控。
技術價值流的每個階段(產品管理、開發、QA、安全、運維),建立快速的反饋和前饋迴路(包括自動化構建、集成和測試過程)。
全方位的遙測系統。
在源頭保障質量
過多的檢查和審批流程,使得做決策的地方遠離執行工作的地方,這導致流程有效性降低,減弱了因果關係之間反饋的強度。
讓開發人員也對系統質量負責,快速反饋,加速開發人員的學習。
爲內部客戶優化工作
運維的非功能性需求(如架構、性能、穩定性、可測試性、可配置性和安全性)與用戶功能同樣重要。
持續學習與實驗原則
建立學習型組織和安全文化
將日常工作的改進制度化
把局部發現轉化爲全局優化
在日常工作中注入彈性模式
縮短部署的前置時間、提高測試覆蓋率、縮短測試執行時間,甚至在必要時解耦架構,都屬於在系統中引入類似張力的做法
領導層強化學習文化
領導者幫助一線工作者在日常工作中發現並解決問題。
DevOps 實踐
基於 DevOps 的相關原則,有與其對應的實踐,包括:流動的技術實踐、反饋的技術實踐和持續學習與實驗的技術實踐。在應用這些實踐之前還需認真設計組織結構,使其有利於實踐的開展。
設計組織結構
利用康威定律設計團隊結構。
康威定律:軟件的架構和軟件團隊的結構是一致的。
軟件的架構應該保證小團隊能夠獨立運作,彼此充分解耦,從而避免過多不必要的溝通和協調。
過度職能導向(成本優化)的危害。
執行工作的人通常不理解自己的工作與價值流目標的關係(“我之所以要配置這臺服務器,是因爲別人要我這麼做”)。
如果運維部門的每個職能團隊都要同時服務於多個價值流(即多個開發團隊),那麼問題更是雪上加霜,因爲所有團隊的時間都很寶貴。
組建以市場爲導向的團隊。
將工程師及其專業技能(例如運維、QA和信息安全)嵌入每個服務團隊,或者向團隊提供自助服務平臺,其功能包括配置類生產環境、執行自動化測試或進行部署。
這使每個服務團隊能夠獨立地向客戶交付價值,而不必提交工單給IT運維、QA或信息安全等其他部門。
使職能導向有效。
快速響應。
高度信任的文化。
將測試、運維和信息安全融入日常工作。
保證質量、可用性和安全性不是某個部門的職責,而是所有人日常工作的一部分。
使團隊成員成爲通才。
培養全棧工程師。
給工程師提供學習必要技能的機會,讓他們有能力構建和運行所負責的系統。
松耦合架構,提高生產力和安全性。
保持小規模(“兩個披薩原則”)。
要使職能導向有效,需要由傳統的集中式運維向提供運維服務的方向轉變。
運維融入項目開發工作
創建共享服務(類生產環境、部署流水線、自動化測試工具、生產環境監控臺、運維服務平臺等),提高開發生產力。
運維工程師融入開發團隊。
使產品團隊自給自足,可以完全負責服務的交付和支持。
派遣工程師到項目開發團隊(運維工程師的面試和聘用仍由集中式運維團隊完成)。
爲每個項目團隊分派運維聯絡人(派遣的運維工程師)。
集中式運維團隊管理所有環境,派遣的運維工程師需要理解:新產品的功能、開發原因、程序如何工作、可運維性、可擴展性、監控能力、架構模式、對基礎設施的要求、產品特性的發佈計劃等。
邀請運維聯絡人蔘加開發團隊會議、每日站會、回顧會議。
使用看板圖展示運維工作。
流動的技術實踐
該部分包含以下內容:
運行部署流水線的基礎
自動化環境(開發、測試、正式)搭建。
使用 Shell、IaC(Puppet、Ansible、Terraform)、Docker、Kubernetes、OpenShift 等技術。
所有內容做版本控制。
自動化和手動測試的腳本;
支持代碼打包、部署、數據庫遷移、應用配置的腳本;
項目相關文件(需求文檔、部署過程、發佈說明等);
防火牆配置、服務器配置等腳本。
應用程序代碼版本控制;
數據庫代碼版本控制;
運維配置代碼版本控制;
擴展完成的定義。
在類生產環境中按照預期進行,開發工作才認爲是完成的。
實現快速可靠的自動化測試
持續構建、測試和集成。
代碼分支持續集成到主幹中,並確保通過單元測試、集成測試和驗收測試。
常用工具:Jenkins、TFS、TeamCity、GitLab CI。
對持續集成的配合:自動化測試工具;一旦失敗必須立即解決的文化;代碼持續合入到主幹,而不是持續在特性分支上工作。
構建快速可靠的自動化測試套件。
單元測試:JUnit、Mockito、PowerMock
單元測試度量:測試覆蓋率。
驗收測試:自動化API測試、自動化GUI測試。
並行測試:安全測試、性能測試、單元測試、自動化測試。
測試驅動開發:TDD、ATDD。
讓部署流水線始終保持綠色狀態。
部署流水線失敗時,所有人立即解決問題或者立即回滾代碼,後續的代碼提交應該拒絕。
代碼持續集成
持續集成代碼。
開發人員在自己的分支上獨立工作的時間越長,就越難將變更合入主幹。
小批量開發。
基於主幹開發。
頻繁向主幹提交(通過合併請求)代碼。
自動化和低風險發佈
自動化部署步驟:構建、測試、部署;相關流程包括:
代碼打包、構建;
上傳 Docker 鏡像;
創建預配置的 Kubernetes 服務;
自動化單元測試、冒煙測試;
數據庫遷移自動化;
配置自動化。
應用自動化的自助式部署
開發人員專注於編寫代碼,點擊部署按鈕,通過監控指標看到代碼在生產環境中正常運行,在代碼出錯時能獲得錯誤信息快速修復。
通過代碼審查、自動化測試、自動化部署,控制部署風險,必要時使開發人員也可進行部署操作,測試人員和項目經理可在某些環境中進行部署。
將部署和發佈解耦
部署指在特定環境中安裝制定版本的軟件。
發佈指將產品特性提供給所有客戶或部分客戶使用。
基於環境的發佈模式
藍綠部署
灰度(金絲雀)發佈
基於應用的發佈模式
實現特性開關,好處:輕鬆地回滾、緩解性能壓力、可以屏蔽服務依賴。
實現黑啓動:發佈潛在風險的新特性時,隱式調用,僅記錄測試結果。
持續交付的實踐
持續交付是指,所有開發人員都在主幹上進行小批量工作,或者在短時間存在的特性分支上工作,並且定期向主幹合併,同時始終讓主幹保持可發佈狀態,並能做到在正常的工作時段裏按需進行一鍵式發佈。開發人員在引入任何迴歸錯誤時(包括缺陷、性能問題、安全問題、可用性問題等),都能快速得到反饋。一旦發現這類問題,就立即加以解決,從而保持主幹始終處於可部署狀態。
持續部署的實踐
持續部署是指,在持續交付的基礎上,由開發人員或運維人員自助式地定期向生產環境部署優質的構建版本,這通常意味着每天每人至少做一次生產環境部署,甚至每當開發人員提交代碼變更時,就觸發一次自動化部署。
大多數團隊採用持續交付實踐。
降低發佈風險的架構
松耦合架構
面向服務的架構
安全地演進企業架構
絞殺者應用模式:API封裝已有功能、按新架構實現新功能、API版本化。
雲原生架構
反饋的技術實踐
這部分包含以下內容:
建立遙測系統
什麼是遙測(Telemetry)?
遙測包含監控,實現對網絡實時、高速和更精細的監控技術。
相比於傳統的網絡監控技術,遙測通過推模式,主動向採集器上推送數據信息,提供更實時更高速更精確的網絡監控功能。
遙測的三大維度
Tracing(跟蹤),Metrics(指標),Logging(日誌)。
可觀察性
系統可以由其外部輸出(遙測的數據)推斷其內部狀態的程度。
能發現、預測並解決問題。
集中式監控系統(可使用:Prometheus、SkyWalking)
在業務邏輯、應用程序和環境層收集數據。
負責存儲和轉發事件和指標的事件路由器。
應用程序日誌遙測(ELK、審計日誌、Metrics)
重大應用事件清單:
認證/授權的結果(包括退出);
系統和數據的訪問;
系統和應用程序的變更(特別是特權變更);
數據的變更,例如增加、修改或刪除數據;
無效輸入(可能的惡意注入、威脅等);
資源(內存、磁盤、中央處理器、帶寬或其他任何具有硬/軟限制的資源);
健康度和可用性;
啓動和關閉;
故障和錯誤;
斷路器跳閘;
延遲;
備份成功/失敗。
將建立生產遙測融入日常開發工作。
使用遙測指導問題的解決。
建立自助訪問的可視化遙測信息系統(信息輻射器)
Grafana
SkyWalking
Kibana
發現和填補遙測的盲區(建立充分而完整的遙測)
業務級別:訂單量、用戶數、流失率、廣告展示和點擊等。
應用程序級別:事務處理事件、應用程序故障等。
基礎架構級別:服務器吞吐量、CPU負載、磁盤使用率等。
客戶端軟件級別:應用出錯和崩潰、客戶端的事務處理事件等。
部署流水線級別:流水線狀態、部署頻率等。
智能告警
解決告警疲勞
充分而完整的遙測會引入告警疲勞問題,需要更智能的報警。
使用統計分析方法,而非靜態閾值設置告警
使用均值和標準差(適用於正態分佈的數據):度量數據與均值存在較大標準差時告警。
使用預防故障的告警,而不只是故障發生後的告警
試着問有什麼指標可以預測故障。
異常檢測技術
平滑統計技術:使用移動平均數,利用每個點與滑動窗口中所有其他數據的平均值,來轉換數據。
支持高級異常檢測的工具:Prometheus、Grafana。
應用反饋實現安全部署
通過遙測使部署更安全——部署後能立即發現問題。
價值流中的所有人(開發人員、開發經理、架構師、運維團隊等)共同承擔運維事故的下游責任。
共同承擔值班工作、共同解決生產環境問題。
讓開發人員跟蹤工作對運維人員的影響。
使開發的應用易於部署,提升運維人員幸福感。
讓開發團隊自行管理生產服務。
首先由開發團隊管理,然後才交由集中的運維團隊管理。
運維工程師由生產支持轉變爲顧問或加入團隊,幫助做好部署準備,建立服務發佈指南(包括:支持有效的監控、部署可靠、架構能支持快速頻繁的部署等)。
爲團隊分配SRE人員。SRE定位:SRE就是軟件開發工程師負責了運維工作,SRE非常稀少,只能分配給最重要的團隊。
應用A/B測試
在功能中集成A/B測試
向用戶隨機展示一個頁面的兩個版本之一。
在發佈中集成A/B測試
使用特性開關。
在功能規劃中集成A/B測試
不僅要快速部署和發佈軟件,還要在實驗方面不斷提升,通過實驗主動實現業務目標和客戶滿意度。
建立評審和協作流程
防止「過度控制變更」
反事實思維容易認爲事故是由於缺乏審批流程導致。
建立同行評審,縮短審批流程
DevOps 中高績效的組織更多地依賴同行評審,更少地依賴外部變更批准(層層審批)。
代碼評審
每個人的代碼提交到主幹時,必須由同行進行評審;
每個人應該持續關注其他成員的提交活動;
定義高風險變更,從而決定是否需要請領域專家進行審查;
將大的提交變更拆分成小批量變更。
利用結對編程改進代碼變更
研究表明:結對的程序員比兩個獨立工作的程序員慢了15%,而‘無錯誤’代碼量卻從70%增加到了85%。
測試和調試程序的成本通常比寫初始代碼的成本高出多倍。
評估合併請求的有效性
與在生產環境產生的結果無關。
有效合併請求的基本要素:必須足夠詳細地說明變更的原因、如何做的變更,以及任何已識別的風險和應對措施。
持續學習與實驗的技術實踐
這部分包含以下內容:
將學習融入日常工作
公正文化和學習文化
人爲錯誤往往不是問題的根本原因,可能是複雜系統中存在不可避免的設計問題而導致。
不應該對造成故障的人進行「點名、責備和羞辱」,我們的目標是最大限度地抓住組織學習的機會。
從學習的角度看待錯誤、報錯、失誤、過失等。
相關實踐1:在事後分析中,不指責,公正地進行評判,使工程師自己願意對事情負責,並且熱情地幫助其他人避免同樣的錯誤發生;廣泛地公開事後分析會議結果。
相關實踐2:在生產環境中引入受控的人爲故障(搗亂猴),針對不可避免的問題進行演練。
降低事故容忍度,尋找更弱的故障信號
隨着組織能力的提升,事故數量大幅降低,故障越不應該出現。
在複雜的系統中,放大微弱的故障信號對於防範災難性故障事關重要。
重新定義失敗
高效能DevOps組織的變更頻率是平均水平的30倍,即使失敗率只有平均水平的一半,也顯然意味着故障總數更多。
鼓勵創新並接受因此帶來的風險。
創建故障演練日
幫助團隊模擬和演練事故,使其具備實戰能力。
暴露系統的潛在缺陷。
將局部經驗轉化爲全局改進
[ChatOps] 使用聊天機器人、積累組織知識
自動化工具集成到聊天中,比如(@bot depoy owl to production);
操作結果由機器人發送回聊天室,每個人都能看到發生的一切;
新來的工程師也可以看到團隊的日常工作及執行方式;
看到他人互相幫助時,人們也會傾向於尋求幫助;
使用話題組,建立起組織學習,知識得到快速積累;
加強了透明、協作的文化。
將標準、流程和規範轉化爲便於執行的形式
[ArchOps] 使工程師成爲構建者,而不是砌磚工;
將手動操作流程轉換爲可自動化執行的代碼;
將合規性使用代碼表達出來。
運用自動化測試記錄和傳播知識
自動化界面測試,令使用者知道系統如何使用;
單元測試,令調用者知道方法API如何使用。
項目開發中包含非功能性的運維需求
對各種應用和環境進行充分的遙測;
準確跟蹤依賴關係的能力;
具有彈性並能正常降級的服務;
各版本之間具有向前和向後的兼容性;
歸檔數據來管理生產數據集的能力;
輕鬆搜索和理解各種服務日誌信息的能力;
通過多個服務跟蹤用戶請求的能力;
使用功能開關或其他方法實現簡便、集中式的運行時配置。
把可重用的運維用戶故事納入開發
將重複的運維工作通過編碼進行實現。
技術選型需要考慮運維因素
不能減慢工作流;
思考舉例:TIDB VS MySQL 該如何選擇。
預留組織學習和改進的時間
償還技術債務制度化
定時「大掃除」
開發和運維針對非功能性需求進行優化,橫跨整個價值流。
價值:賦予一線工作人員不斷識別和解決問題的能力。
讓所有人教學相長
所有的工程師都越來越需要某些技能,而不只是開發人員如此。
越來越多的技術價值流採用了DevOps的原則和模式。
[每週學習文化] 每週一次的學習時間,每個同伴既要自己學習,又要教別人。
內部顧問和教練
成立內部的教練和諮詢組織,促進專業知識在組織內的傳播。
實踐重點
DevOps 的實踐包含許多內容,提煉了以下重點方便查閱:
流動原則的實踐
部署流水線的基礎(所有內容做版本控制、在類生產環境按預期工作纔算完成)
實現快速可靠的自動化測試(自動化運行、始終保持流水線處於綠色狀態)
代碼持續集成(小批量開發)
自動化和低風險發佈(自助式部署、部署和發佈解耦、採用持續交付)
降低發佈風險的架構(雲原生架構)
反饋原則的實踐
建立遙測系統(Tracing、Metrics、Logging)
智能告警(使用統計分析方法和預防故障的告警)
應用反饋實現安全部署(部署後立即發現問題、共同承擔責任)
應用A/B測試(功能規劃中集成A/B測試、使用特性開關)建立評審和協作流程(同行評審、減少審批流程、結對編程)
持續學習與實驗原則的實踐
將學習融入日常工作(從學習的角度看待事故、尋找更弱的故障信號)
將局部經驗轉化爲全局改進(ChatOps、讓規範便於執行、非功能性的運維需求)
預留組織學習和改進的時間(定時償還技術債務、教學相長、內部教練)
結語
DevOps 的發展與技術的發展相輔相成,也爲技術人員提供了更多的學習道路和發展方向,借用一句 DevOps 領袖的話來作爲本文的結束語。