Try   HackMD

The Twelve-Factor App - A methodology to build a better SaaS app

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →
Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →

2022/10/31 updated 更棒的整理:[Architecture] The 12 factor App 筆記

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →

如今,軟體通常會作為一種服務來交付,它們被稱為網路應用程式或軟體即服務(SaaS)應用。12-Factor 為想要實現以下目標的 SaaS 應用提供了方法論:

  • 使用聲明式的自動化配置,從而使新的開發者花費最少的學習成本加入這個項目
  • 和作業系統之間盡可能的劃清界限,在各個系統中提供最大的可移植性
  • 適合部署在現代的雲端平台,從而在伺服器和系統管理方面節省資源
  • 開發環境產品環境的差異降至最低,使得持續交付的方法得以實施以最大化敏捷開發
  • 可以在工具、架構和開發流程不發生明顯變化的前提下實踐擴展

當我們在替 application 維運時,很容易碰到了一些問題。我發現常見的問題與其中 6 個原則很有關係,故摘要它們出來:

  • I. Codebase
  • III. Config
  • IV. Backing services
  • VI. Processes
  • VIII. Concurrency
  • X. Dev/prod parity

這些原則與觀念將有助於我們在設計開發階段想得更清楚,讓你的 app 更適應雲平台的部署與維運方式。

I. Codebase

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →

  • 程式碼應該要在不同的 deploys 之間保持一致 (local development environment 也是一種 deploy)
  • 故如果程式碼內部出現以下這種邏輯,應就得視你的 app 為不一致的:
    ​​​​if env==dev:
    ​​​​    read ENV_URL_FOR_DEV;
    ​​​​else if env==prod:
    ​​​​    read ENV_URL_FOR_PROD;
    ​​​​...
    ​​​​if env==dev:
    ​​​​    use ENV_URL_FOR_DEV do somwthing
    ​​​​  else if env==prod:
    ​​​​    use ENV_URL_FOR_PROD do somwthing
    
  • 上述的邏輯將導致每增添一種 deploy,就得顯示地去改動 source code 以滿足特定環境所需
  • 應同時考慮 III. Config 談論的原則,讓環境 (configurations) 來決定 app 的行為、而不是讓 app 感知環境後做出意料之外的行為

III. Config

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →
每一種環境的部署,對於周邊環境的需求總是不確定的。你無法保證未來新業務所需的環境能夠套用過去的經驗。

  • 應利用「環境變數」儲存 config,因為「環境變數」可以很方便地在不同環境中做出改變、且不用改動任何一行 code。

    Image Not Showing Possible Reasons
    • The image file may be corrupted
    • The server hosting the image is unavailable
    • The image path is incorrect
    • The image format is not supported
    Learn More →
    使用環境變數作為引入配置的手段為第一優先。都使本地開發與各環境部署更加簡潔。

    只有極少數的需求會強迫透過載入檔案的方式來取得配置。就算有這種例外,「檔案的路徑」也需要設計成能夠透過環境變數給予。

    一樣,你無法掌握部署環境的 file system 的全貌,故將職責交給部署的人去明確指定該檔案的位置即可。

  • 你可能會想要將環境變數做出組別 (development, test, production),但你很快就會發現這方法不 sacle,你會疲於管理多種部署環境的排列組合 (i.e. staging, ga, joes-staging)。所以不要這樣做
  • 其實只要環境變數切得夠細、不彼此依賴,讓負責部署的人根據該環境需求,管理要如何給定參數即可。

    Image Not Showing Possible Reasons
    • The image file may be corrupted
    • The server hosting the image is unavailable
    • The image path is incorrect
    • The image format is not supported
    Learn More →
    那我們目前「部署的人」是如何管理環境變數的差異?
    Image Not Showing Possible Reasons
    • The image file may be corrupted
    • The server hosting the image is unavailable
    • The image path is incorrect
    • The image format is not supported
    Learn More →
    sa/manifests

IV. Backing services

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →

  • 所謂的 backing service 是指那些需要透過 network 溝通取得資源後,才能讓你的 app 有 normal operation 表現的 services。並將這些 services 視為一種資源 (resources)
  • 這些 service 理論上都是透過給定 URL 來連接、存取,並使用 III. Config 提到的方式來儲存
  • e.g. 利用 config 來儲存,你可以很輕易地讓 app 連向 local 環境的 resource 或其他第三方的 resource

VI. Processes

  • 在有了 IV. Backing services 這樣的原則為前提,一個 12-factor app 會進一步實踐 stateless and share-nothing 的架構
  • 另外,app 可能依賴於 sticky sessions 的設計,我們要知道它其實是違反 12-factor 精神的 (文中建議是使用 Redis/Memcached 等方式來嘗試解耦)

VIII. Concurrency

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →

  • 若服務吞吐量不足,優先考慮 Scale out via the process model
  • 對我們來說,就是 app 得做好 stateless 的準備,然後使用 K8S 的 Horizontal Pod Autoscaler 自動做 scale out
  • 當然,也會迫使我們在設計服務時,就先想清楚對 DB 做出併發請求是否會產生「業務邏輯上的 race conditions」 (e.g. read phenomena)

X. Dev/prod parity

開發/產品等價

  • 大部分的人,在有越多的開發經驗後皆會感同身受:
    1. app 在 development, staging, production 環境之間有差異的時間越久,在 production 的環境上越容易出問題
    2. 開發與維運的人員差異,容易造成部署後出問題
    3. 本地開發環境與線上環境使用的 tech stacks 不同 (e.g. SQLite vs. MySQL),造成問題
  • 而 12-factor 的精神會希望一個 app:
    1. 採用 Continuous Deployment,儘可能縮小 development 與 production 的差異
    2. 盡可能開發與維運合一 (i.e. 我開發、我維運的主人翁精神)
    3. 盡可能本地開發與線上環境使用相同的 tech stacks
      Image Not Showing Possible Reasons
      • The image file may be corrupted
      • The server hosting the image is unavailable
      • The image path is incorrect
      • The image format is not supported
      Learn More →

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →
實務上,針對這部分,我都使用:

  1. Docker 直接運行與線上環境相同的 teck stack
  2. 運用 Makefile 模擬 app 運行的環境。事先定義好環境變數讓 app 讀取並運行 (Makefile Tutorial By Example)