2019年3月19日 星期二

為什麼需要 CI/CD?

Continuous Integration(持續整合)和 Continuous Delivery(持續發佈),有些時候也會用 DevOps 來稱呼,有在關注技術發展的話就會發現這個詞非常火紅,好像每個人都應該要知道的樣子。不過它可以解決什麼問題呢?

傳統的軟體開發是怎麼做的?

先來看看傳統的軟體開發,流程上會做些什麼事?首先團隊會先進行需求分析,然後確立系統規格,接著可能會做系統設計和分工,然後團隊成員就開始實作系統元件。系統元件各自實作時會各自寫對應的單元測試,等到所有元件都做完了,就由特定一群人(也許是資深人員或者是主管等等的)開始整合所有的元件,組合成完整的系統並且交付給測試團隊開始做整合測試。測試都完成以後,就再由負責發佈軟體更新的人們去把軟體發佈到線上的系統,完成一次系統更新。

問題是什麼?

上面描述的是一個完美進行的軟體開發流程。但真實世界中,過程裡會發生許多意外,導致流程沒辦法如同預期般地順利。

  1. 系統元件在開發時,有可能進度不一致,有些元件也許遇到意外的挫折而減慢了速度,因而導致後續的整合和交付測試團隊的時間延後了。這可能導致測試團隊的時間不足,或者是接著引發下述的問題。
  2. 測試團隊在做系統的整合測試時,發現整合後的元件有問題,需要發回給開發團隊 debug。此時開發團隊在 debug 時的門檻會大幅地提昇,因為整合過後的系統複雜度遠高於整合前,對於一個稍大的系統來說,要在整合完成的最後階段找出問題所在,會是個很大的難題。也因此開發團隊可能會花費超乎預期的時間才有辦法找出問題,又或者甚至提出的解法再次引發了其他的 bug,導致難以離開整合測試的階段,並導致最終的軟體交付延遲。
  3. 整合測試完成後,發佈人員將軟體發佈到線上系統,並且將發佈的步驟詳細地紀錄在文件中。然而線上系統在發佈後的運作依然問題不斷,在測試環境中能夠正常運作的系統,發佈到線上環境時卻不如預期。發佈人員也許會嘗試做各種包含設定、系統環境等等的檢查與修改,然後可能在某個階段突然發現一切都正常了,但因為中間做了太多變更,不清楚確切來說到底是哪個(或哪些)變更讓系統正常的。又或者發佈人員確切地知道做了某些步驟讓系統正常了,但在事後的文件紀錄中卻忘記寫上、或者寫得不夠詳細。
  4. 在系統發佈的階段,除了發佈人員以外,開發人員很有可能也需要嚴陣以待,當發現任何問題時要一起投入解決問題。這段時間短則一兩天,長則甚至可能長達一週,讓包含發佈人員和開發人員在內的團隊成員每天都戰戰兢兢。
  5. 這次的軟體發佈很順利地度過了,但下次類似的狀況又再次發生。之前遇到的發佈問題可能也再次出現,但卻不記得上次是如何解決的,也難以從文件紀錄中找到詳細的解決方案。
關鍵概念:敏捷式開發

要解決前述的那些問題,首先有個重要的概念是敏捷式開發。在過去軟體開發的習慣中,之所以風險變得如此難以掌控,有個重要的因素是「每次開發時的範圍都涵蓋地太大」。範圍涵蓋太大會導致各種問題,包括每當要整合的時候都要耗費很多時間、測試時可能會發現很多問題、debug 時因為複雜度高導致難以短時間內完成、發佈時難以保持對發佈的系統的信心等等。這些所有的問題都來自於同一個根本原因,就是這次發佈的軟體涵蓋太多東西,所以我們沒有辦法對它抱持信心,覺得各種原因都可能可以導致它發生問題。那麼如果我們把範圍縮小呢?一個要花費六個月才能完成的大型功能,把它切碎成一個月份量的六次開發與發佈工作,甚至是切碎成兩週份量的十二次開發與發佈工作呢?我們會對於一次發佈 5,000 行程式碼更新的行為感到信心不足,但我們會對發佈 100 行程式碼更新的行為感到擔憂嗎?

在 Continuous Integration 以及 Continuous Delivery 當中,最重要的核心概念就是要把每次的軟體開發與發佈都縮小到很小的範圍,確保我們每次的開發與發佈,都只變更整個系統很小的一部分。因此每次的發佈,不太可能對系統產生巨大的影響;同時因為範圍小,對我們來說也會比較容易掌握可靠度,就算發生問題也能夠快速找到問題。

關鍵概念:版本控制與自動化

接著,在有了敏捷式開發(快速迭代)的基礎之後,下一個重要的概念是自動化。當我們用手動的方式做任何事情時,每次的動作都是不確定性,包括可能打錯字、複製錯誤的指令、連上錯誤的主機等等等,即使我們有完美可靠的文件,也無法保證負責執行步驟的人能夠完美無缺地按照文件的步驟執行。除此之外,針對不同的環境、不同的設定,有許多因素可能造成文件的步驟需要略做調整,而這些調整有可能需要依賴執行人員自身的經驗與知識,因而導致這次軟體發佈的成功不一定能帶來下一次的成功,因為下一次執行的人有可能不具備這些經驗與知識,或者這些經驗與知識未能完整反應在文件上。

要想解決這些問題,首先我們希望把動作全部轉換成可被儲存的指令,讓每次的整合與發佈都是 one-click 就能完成的動作。接著我們希望這些指令都可以被版本控制系統所管理,所以不會發生在整合與發佈階段需要仰賴執行人員的經驗與知識的狀況。要注意的是,這個自動化的整合與發佈,需要連同平常的開發測試環境也一併使用它,這會讓我們在平常開發時,就一起在開發與測試發佈程序。

然而此時我們可能也會想著:這問題其實還沒有被解決呀,整合與發佈的動作被指令化以後,這些指令很可能只能用在特定環境,當我們要發佈到其他環境時,這些指令依然會製造問題。這麼想是很正確的,而這也是為什麼敏捷式開發對這個程序也很重要的原因。

當我們每次的軟體開發與發佈都只涵蓋很小的範圍,我們會比較容易對它產生信心,因為它不太可能大幅地造成整體系統的崩潰。而且我們有了完整的自動化發佈工具,一旦我們發佈的軟體出了什麼問題,我們只需要從版本控制系統中翻出上一版的發佈工具,在幾秒鐘之內就能將系統還原到上一版。在這樣的情況下,軟體發佈就會成為日常工作的一部分,而不是一段時間就要經歷的一次大戰。同時,因為每次的發佈範圍都很小,我們也會經歷過非常多次的自動化發佈,這也意味著這個自動化發佈的流程將會經歷過非常多次的測試(連同開發過程中的測試),每次我們的發佈都是一次測試的機會,讓我們對自動化發佈的程序更具信心。

Continuous Integration / Continuous Delivery

綜合以上,當我們結合了敏捷式開發、版本控制與自動化,並且妥善地利用他們在專案流程中,將可以有效地減低軟體專案後期的整合與發佈的負擔,並且保持對自己生產出來的軟體的信心,維持軟體的品質。開發人員也得以因此不用在系統上線的階段戰戰兢兢地關注著系統的運行,可以早早下班回家陪伴家人~。不過這裡面最重要的是,CI/CD 並不是個引入了什麼軟體或系統就能達成的事情,它需要整個團隊大幅度地改變文化和思考方式,否則它極有可能只是變成造成開發人員更多困擾和拖慢專案速度的另一個推手而已。

參考資料
  1. Continuous Delivery 中文版:利用自動化的建置、測試與部署完美創造出可信賴的軟體發佈
  2. 为什么我们迫切需要持续集成?
  3. 什麼是 CI / CD ?
  4. 什麼是持續整合? – Amazon Web Services
  5. 持續性整合與發佈 (Continuous Integration / Continuous Delivery) 之相關應用
  6. 为什么 DevOps 和 SRE 职位这么难招人?
  7. DevOps常见误解之TOP 3

沒有留言: