應用程式開發和藍綠部署,基於十二因素應用程式方法論,並以 php 和 docker 為例

應用程式開發和藍綠部署,基於十二因素應用程式方法論,並以 php 和 docker 為例

首先,一點理論。 發生了什麼事 十二要素應用程式?

簡而言之,本文檔旨在簡化 SaaS 應用程式的開發,透過向開發人員和 DevOps 工程師通報現代應用程式開發中最常遇到的問題和實踐來提供協助。

該文件由 Heroku 平台的開發人員創建。

十二要素應用程式可應用於以任何程式語言編寫並使用任意支援服務組合(資料庫、訊息佇列、快取等)的應用程式。

簡單介紹一下該方法所依據的因素:

  1. 程式碼庫 – 在版本控制中追蹤一個程式碼庫 – 多個部署
  2. 依賴項 – 明確聲明並隔離依賴關係
  3. 組態 – 在運作時儲存配置
  4. 支援服務 – 考慮將支援服務作為外掛資源
  5. 建置、發布、運行 – 嚴格分離組裝與執行階段
  6. 流程 – 將應用程式作為一個或多個無狀態進程運行
  7. 連接埠綁定 – 透過連接埠綁定導出服務
  8. 並發 – 使用流程擴展您的應用程式
  9. 一次使用 – 透過快速啟動和乾淨關閉來最大限度地提高可靠性
  10. 應用程式開發/營運平價 – 讓您的開發、登台和生產環境盡可能相似
  11. 記錄 – 將日誌視為事件流
  12. 行政任務 – 使用臨時流程執行行政/管理任務

您可以從以下資源獲取有關 12 個因素的更多資​​訊:

什麼是藍綠部署?

藍綠部署是一種將應用程式交付給 生產 以這樣的方式,最終客戶看不到他的任何變化。 換句話說,部署一個應用程式為零 停機時間.

經典的 BG Deploy 方案如下圖所示。

應用程式開發和藍綠部署,基於十二因素應用程式方法論,並以 php 和 docker 為例

  • 一開始有2台實體伺服器,具有完全相同的程式碼、應用程式、項目,並且有一個路由器(平衡器)。
  • 路由器最初將所有請求定向到其中一台伺服器(зеленый).
  • 當你需要再次發布的時候,整個專案就更新到了另一台伺服器上(),目前未處理任何請求。
  • 代碼開啟後 藍色的 伺服器已完全更新,路由器收到切換命令 切普韋普。
  • 現在所有客戶端都可以看到程式碼運行的結果 藍色 服務器。
  • 一段時間以來, зеленый 如果部署失敗,伺服器將作為備份副本 伺服器,如果發生故障和錯誤,路由器會將用戶流切換回 зеленый 伺服器使用舊的穩定版本,並發送新程式碼進行修訂和測試。
  • 並且在過程結束時,以相同的方式更新 зеленый 伺服器. 更新後,路由器將請求流切換回 зеленый 切普韋普。

一切看起來都很好,乍看之下應該沒有任何問題。
但由於我們生活在現代世界,經典方案中所示的物理切換選項並不適合我們。 暫時記錄一下訊息,稍後我們再回顧。

好的和壞的建議

免責聲明:下面的範例顯示了我使用的實用程式/方法,您絕對可以使用具有類似功能的任何替代方案。

大多數範例都會以某種方式與 PHP 和 Docker 的 Web 開發交叉(這是一個驚喜)。

下面的段落使用具體範例對因子的使用進行了簡單實用的描述;如果您想獲得有關此主題的更多理論,請點擊上面的連結訪問原始來源。

1. 程式碼庫

使用 FTP 和 FileZilla 一次上傳一個檔案到伺服器,不要將程式碼儲存在生產伺服器以外的任何地方。

專案應該始終有一個單一的程式碼庫,即所有程式碼都來自一個 混帳 儲存庫。 伺服器(生產、登台、test1、test2...)使用來自一個公共儲存庫的分支的程式碼。 這樣我們就實現了程式碼的一致性。

2. 依賴關係

將資料夾中的所有庫直接下載到專案的根目錄。 只需將新程式碼傳輸到包含當前版本庫的資料夾即可進行更新。 直接在執行 20 多個服務的主機伺服器上安裝所有必要的實用程式。

專案應該始終有一個清晰易懂的依賴項清單(我所說的依賴項也指環境)。 所有依賴項都必須明確定義和隔離。
我們舉個例子 作曲家 и 碼頭工人.

作曲家 — 一個套件管理器,可讓您在 PHP 中安裝函式庫。 Composer 允許您嚴格或寬鬆地指定版本,並明確定義它們。 伺服器上可以有 20 個不同的項目,每個項目都有一個相互獨立的個人套件和庫列表。

碼頭工人 — 一個實用程序,可讓您定義和隔離應用程式運行的環境。 因此,就像作曲家一樣,但更徹底的是,我們可以確定應用程式的工作原理。 選擇特定的 PHP 版本,僅安裝專案運行所需的軟體包,而不添加任何額外的內容。 最重要的是,不會幹擾主機和其他專案的軟體包和環境。 也就是說,伺服器上透過 Docker 運行的所有專案都可以使用絕對任何一組套件和完全不同的環境。

3. 配置

將配置直接儲存在程式碼中作為常數。 測試伺服器的單獨常數,生產伺服器的單獨常數。 使用 if else 構造將取決於環境的應用程式操作直接綁定到專案的業務邏輯中。

配置 - 這是專案部署應該有所不同的唯一方法。 理想情況下,配置應該透過環境變數(env vars)傳遞。

也就是說,即使您儲存多個設定檔 .config.prod .config.local 並在部署時將它們重新命名為 .config (應用程式從中讀取資料的主配置) - 這也不是正確的方法,因為在這種情況下,配置中的資訊將向所有應用程式開發人員公開,並且生產伺服器中的資料將受到損害。 所有配置必須直接儲存在部署系統(CI/CD)中,並針對不同環境產生部署時特定環境所需的不同值。

4. 第三方服務

與環境嚴格綁定,在特定環境下對相同服務使用不同的連線。

事實上,這一點與配置的點有很大的重疊,因為沒有這一點,就無法進行正常的配置數據,一般來說,配置的能力就會下降。

對於本機環境和第三方/生產環境,與外部服務(例如佇列伺服器、資料庫、快取服務)的所有連線必須相同。 換句話說,在任何時候,透過更改連接字串,我都可以用基底#1 替換對基底#2 的調用,而無需更改應用程式程式碼。 或者,展望未來,例如,在擴展服務時,您不必以任何特殊方式為附加快取伺服器指定連線。

5. 建置、發布、執行

伺服器上只有最終版本的程式碼,沒有機會回溯版本。 無需填滿磁碟空間。 任何認為自己可以將帶有錯誤的程式碼發佈到生產中的人都是糟糕的程式設計師!

部署的所有階段必須彼此分開。

有機會翻盤。 使用保存在快速存取中的舊應用程式副本(已組裝並準備戰鬥)進行發布,以便在出現錯誤時可以恢復舊版本。 即有條件有一個資料夾 發布 和資料夾 當前,並在成功部署和組裝資料夾後 當前 透過符號連結連結到內部的新版本 發布 與版本號的常規名稱。

這就是我們記得藍綠部署的地方,它不僅允許您在程式碼之間切換,還可以在所有資源甚至環境之間切換,並具有回滾所有內容的能力。

6. 流程

直接將應用程式狀態資料儲存在應用程式本身內。 在應用程式本身的 RAM 中使用會話。 盡可能使用第三方服務之間的共享。 依賴這樣一個事實:應用程式只能有一個進程並且不允許擴展。

關於會話,僅將資料儲存在由第三方服務(memcached、redis)控制的快取中,因此即使您有 20 個應用程式進程正在運行,其中任何一個存取了緩存,都將能夠繼續與客戶端一起工作用戶在另一個進程中使用應用程式時的相同狀態。 透過這種方法,事實證明,無論您使用多少第三方服務副本,一切都會正常運作,並且不會出現資料存取問題。

7. 連接埠綁定

只有網頁伺服器應該知道如何與第三方服務一起工作。 或者更好的是,直接在 Web 伺服器內安裝第三方服務。 例如,作為 Apache 中的 PHP 模組。
您的所有服務必須可以透過存取某個位址和連接埠(localgost:5432,localhost:3000,nginx:80,php-fpm:9000)來相互訪問,也就是說,從nginx我可以訪問php-fpm和postgres ,從php-fpm 到postgres 和nginx,實際上我可以從每個服務存取另一個服務。 這樣,一個服務的生存能力就不會與另一個服務的生存能力連結在一起。

8. 並行性

與一個進程一起工作,否則多個進程將無法相處!

留出擴展空間。 Docker swarm 非常適合這個。
Docker Swarm 是一個用於建立和管理不同機器之間的容器叢集以及同一機器上的一堆容器的工具。

使用 swarm,我可以確定為每個進程分配多少資源以及將啟動相同服務的多少個進程,並且內部平衡器在給定連接埠上接收資料時會自動將其代理到進程。 因此,看到伺服器上的負載增加了,我可以添加更多進程,從而減少某些進程的負載。

9. 一次性使用

不要使用佇列來處理進程和資料。 終止一個進程應該會影響整個應用程式。 如果一項服務出現故障,那麼所有服務都會故障。

每個進程和服務都可以隨時關閉,而且這不應該影響其他服務(當然,這並不是說該服務對另一個服務不可用,而是另一個服務在這個服務之後不會關閉)。 所有進程都必須優雅地終止,這樣當它們終止時,不會損壞任何數據,並且系統下次開機時也能正常工作。 也就是說,即使在緊急終止的情況下,資料也不應該被損壞(事務機制在這裡是合適的,資料庫中的查詢只能成組工作,並且如果該群組中至少有一個查詢失敗或使用錯誤,那麼實際上該組中沒有其他查詢最終失敗)。

10.應用程式開發/營運平價

應用程式的生產版本、暫存版本和本機版本必須不同。 在生產中我們使用 Yii Lite 框架和本地 Yii,這樣它在生產中運行得更快!

實際上,所有部署和程式碼工作都應該在幾乎相同的環境中(我們不是在談論實體硬體)。 此外,任何開發員工都應該能夠在必要時將程式碼部署到生產中,而不是某些經過專門培訓的 DevOps 部門,只有憑藉特殊的力量才能將應用程式提升到生產中。

Docker 也在這方面幫助我們。 如果遵守前面的所有要點,使用 docker 將使在生產和本機上部署環境的過程只需輸入一兩個命令。

11. 日誌

我們將日誌寫入檔案和資料庫! 我們不會清除日誌中的檔案和資料庫。 我們買一塊 9000 Peta 位元組的硬碟就可以了。

所有日誌都應被視為事件流。 應用程式本身不應參與日誌處理。 日誌應該輸出到 stdout 或透過 udp 等協定發送,以便使用日誌不會給應用程式帶來任何問題。 Graylog 對此很有用。 Graylog透過udp接收所有日誌(該協定不需要等待有關成功接收資料包的回應)不會以任何方式乾擾應用程序,僅處理結構化和處理日誌。 應用程式邏輯不會改變以使用此類方法。

12. 行政任務

若要更新資料、資料庫等,請在 API 中使用單獨建立的端點,連續執行兩次將導致所有內容重複。 但你並不傻,你不會點擊兩次,而且我們也不需要遷移。

所有管理任務都應在與所有程式碼相同的環境中在發布層級執行。 也就是說,如果我們需要更改資料庫的結構,那麼我們不會透過一些視覺化資料庫管理工具手動更改列名和新增列。 對於此類事情,我們創建單獨的腳本 - 遷移,這些腳本在任何地方和所有環境中以相同的方式執行,並產生常見且可理解的結果。 對於所有其他任務,例如用資料填充項目,應使用類似的方法。

PHP、Laravel、Laradock、Docker-Compose 中的範例實現

PS 所有範例均在 MacOS 上進行。 其中大多數也適用於 Linux。 Windows 使用者請原諒我,我已經很久沒有使用 Windows 了。

讓我們想像一下這樣一種情況:我們的 PC 上沒有安裝任何版本的 PHP,而且什麼都沒有安裝。
安裝最新版本的 docker 和 docker-compose。 (這個可以上網查到)

docker -v && 
docker-compose -v

應用程式開發和藍綠部署,基於十二因素應用程式方法論,並以 php 和 docker 為例

1.我們把 拉拉多克

git clone https://github.com/Laradock/laradock.git && 
ls

應用程式開發和藍綠部署,基於十二因素應用程式方法論,並以 php 和 docker 為例

關於Laradock,我會說它是一個非常酷的東西,裡麵包含了很多容器和輔助的東西。 但我不建議在生產中不進行修改就使用 Laradock,因為它具有冗餘性。 最好基於 Laradock 中的範例創建自己的容器,這會更加優化,因為沒有人需要同時存在的所有內容。

2. 配置 Laradock 來運行我們的應用程式。

cd laradock && 
cp env-example .env

應用程式開發和藍綠部署,基於十二因素應用程式方法論,並以 php 和 docker 為例

2.1. 在某個編輯器中開啟 habr 目錄(laradock 克隆到的父資料夾)。 (以我的 PHPStorm 為例)

在這個階段我們只給專案一個名稱。

應用程式開發和藍綠部署,基於十二因素應用程式方法論,並以 php 和 docker 為例

2.2. 啟動工作區影像。 (就您而言,圖像需要一些時間來構建)
工作區是專門為開發人員使用框架而準備的映像。

我們進入容器內部使用

docker-compose up -d workspace && 
docker-compose exec workspace bash

應用程式開發和藍綠部署,基於十二因素應用程式方法論,並以 php 和 docker 為例

2.3. 安裝 Laravel

composer create-project --prefer-dist laravel/laravel application

應用程式開發和藍綠部署,基於十二因素應用程式方法論,並以 php 和 docker 為例

2.4. 安裝完成後,我們檢查項目所在的目錄是否已建立並殺死 compose。

ls
exit
docker-compose down

應用程式開發和藍綠部署,基於十二因素應用程式方法論,並以 php 和 docker 為例

2.5. 讓我們回到 PHPStorm 並在 .env 檔案中設定 Laravel 應用程式的正確路徑。

應用程式開發和藍綠部署,基於十二因素應用程式方法論,並以 php 和 docker 為例

3. 將所有程式碼加入Git。

為此,我們將在 Github(或其他任何地方)上建立一個儲存庫。 讓我們進入終端機中的 habr 目錄並執行以下程式碼。

echo "# habr-12factor" >> README.md
git init
git add README.md
git commit -m "first commit"
git remote add origin [email protected]:nzulfigarov/habr-12factor.git # здесь будет ссылка на ваш репо
git push -u origin master
git status

讓我們檢查一下是否一切正常。

應用程式開發和藍綠部署,基於十二因素應用程式方法論,並以 php 和 docker 為例

為了方便起見,我建議使用 Git 的一些視覺化介面,在我的例子中是 GitKraken。 (這是一個推薦連結)

4. 開始吧!

開始之前,請確保連接埠 80 和 443 上沒有掛起任何內容。

docker-compose up -d nginx php-fpm

應用程式開發和藍綠部署,基於十二因素應用程式方法論,並以 php 和 docker 為例

因此,我們的項目由 3 項獨立的服務組成:

  • nginx - 網路伺服器
  • php-fpm - 用於接收來自 Web 伺服器的請求的 php
  • 工作區 - 開發人員的 php

目前,我們已經創建了一個滿足 4 點中的 12 點的應用程序,即:

1. 程式碼庫 — 所有程式碼都在一個儲存庫中(小提示:在 laravel 專案中新增 docker 可能是正確的,但這並不重要)。

2. 依賴項 - 我們所有的依賴項都明確寫入 application/composer.json 和每個容器的每個 Dockerfile 中。

3. 支援服務 — 每項服務(php-fom、nignx、workspace)都有自己的生命週期,並從外部連接,當使用一項服務時,另一項服務不會受到影響。

4. 流程 — 每項服務都是一個流程。 每個服務都不維護內部狀態。

5. 連接埠綁定

docker ps

應用程式開發和藍綠部署,基於十二因素應用程式方法論,並以 php 和 docker 為例

正如我們所看到的,每個服務都在自己的連接埠上運行,並且可供所有其他服務存取。

6. 並發

Docker 允許我們產生相同服務的多個進程,並在它們之間自動進行負載平衡。

讓我們停止容器並通過標誌運行它們 - 規模

docker-compose down && 
docker-compose up -d --scale php-fpm=3 nginx php-fpm

應用程式開發和藍綠部署,基於十二因素應用程式方法論,並以 php 和 docker 為例

正如我們所看到的,已經創建了 php-fpm 容器的副本。 我們不需要改變任何使用這個容器的東西。 我們也繼續在連接埠 9000 上存取它,Docker 為我們調節容器之間的負載。

7. 一次使用 - 每個容器都可以被殺死而不傷害另一個容器。 停止或重新啟動容器不會影響應用程式在後續啟動期間的運作。 每個貨櫃也可以隨時提升。

8. 應用程式開發/營運平價 - 我們所有的環境都是一樣的。 透過在生產伺服器上執行系統,您無需更改命令中的任何內容。 一切都將以同樣的方式基於 Docker。

9. 記錄 — 這些容器中的所有日誌都會進入串流並在 Docker 控制台中可見。 (這樣的話,其實其他自製的容器,如果不愛護的話也可能不會出現這種情況)

 docker-compose logs -f

應用程式開發和藍綠部署,基於十二因素應用程式方法論,並以 php 和 docker 為例

但有一個問題是 PHP 和 Nginx 中的預設值也會將日誌寫入檔案。 要滿足這12個因素,必須 關閉 分別將日誌寫入每個容器配置中的檔案。

Docker 還提供了不僅將日誌傳送到 stdout 的功能,還提供了將日誌傳送到我上面提到的graylog 之類的功能。 在graylog內部,我們可以隨意操作日誌,我們的應用程式不會以任何方式註意到這一點。

10. 行政任務 — 所有管理任務都由 Laravel 解決,這要歸功於 Artisan 工具,正如 12 Factor 應用程式的創建者所希望的那樣。

作為範例,我將展示一些命令是如何執行的。
我們進入容器。

 
docker-compose exec workspace bash
php artisan list

應用程式開發和藍綠部署,基於十二因素應用程式方法論,並以 php 和 docker 為例

現在我們可以使用任何命令。 (請注意,我們沒有配置資料庫和緩存,因此一半命令將無法正確執行,因為它們被設計為與快取和資料庫一起使用)。

應用程式開發和藍綠部署,基於十二因素應用程式方法論,並以 php 和 docker 為例

11. 配置 和12。 建置、發布、運行

我想將這一部分專門討論藍綠部署,但事實證明它對於本文而言過於廣泛。 我將就此單獨寫一篇文章。

簡而言之,這個概念是基於 CI/CD 系統,例如 詹金斯 и 亞特實驗室持續集成。 在兩者中,您都可以設定與特定環境關聯的環境變數。 因此,在這種情況下,c點將得到滿足 配置.

還有一點是關於 建置、發布、運行 透過名為的內建函數解決 管道.

管道 讓您將部署流程分為多個階段,突出顯示組裝、發布和執行階段。 同樣在 Pipeline 中,您可以建立備份,甚至任何東西。 這是一個具有無限潛力的工具。

申請代碼位於 Github上.
克隆此儲存庫時不要忘記初始化子模組。

PS:所有這些方法都可以與任何其他實用程式和程式語言一起使用。 最主要的是本質沒有差別。

來源: www.habr.com

添加評論