蓋環境很難?是這樣的嗎?QA 需要自己蓋環境?
上一次的分享 之後,開始有 QA 的朋友找我聊很多他正在面對的問題。其中一個問題是:
Backend 開發人員說建立環境很難?是這樣嗎?
本文針對這個問題,整理背後可能的問題,以及實際可行的方法。全文整理自 09/18 在 FB 寫的草稿。
Backend 開發人員說建立環境很難?是這樣嗎?
標題簡化了一些訊息,重現原本的提問:
我是一個 QA,我曾經找 Backend 開發人員問,我想自己建環境測試,他們說很難,Config 很雜亂、DB Schema 很複雜、Infra 很複雜,真的是這樣?
重新整理提問,整個問題是從 蓋環境 (專有名詞 Provisioning) 出發,對於測試人員來看,背後 動機
與 目的
有以下:
- 因為執行測試過程會被自動觸發的 CI 部署打斷,希望不被干擾執行
- 想要透過了解環境,更確立問題的正確性
- 想要透過 Log 找問題,目前環境無法看到 Log
- 測試過程,想進去 DB 增加資料,查問題
從開發人員的回覆,可以看出背後有以下問題:
- Config 很雜亂
- DB Schema 很複雜
- Infra 很複雜
1. 現象:Config 很雜亂
Config 指的是應用程式在啟動階段透過外界指定的配置資訊,應該在 系統設計 (System Design)
過程就要確立的結構,這屬於 Application Interface
的範疇,也是 System Design 階段要確立的東西。
Application Interface
是我自己定義的名詞,用來描述一個應用程式的外顯介面。只要是使用者會接觸到的資訊,都屬於外顯介面,像是 Config / Environment Variables / Secret / API / Documentation … etc.
常見的 Config 大概可以分成以下幾個部分:
- 系統依賴:
- 會有 connection string 的,包含 ip / host、protocol、id / password 、parameters 等。
- 服務自己的基礎設施,像是對 Database / Cacche / Queue .. 等依賴
- 公司內部與第三方系統的依賴:
- 公司內部:像是依賴於內部的 簡訊服務、另一個服務的 API … 等。
- 第三方服務:像是依賴於 Google SSO、AWS S3 服務、Twillo 的簡訊服務、Paypal 的金流服務 … 等。
- 業務邏輯功能的初始與預設參數:
- 通常是 Feature Toggle 以及其參數
- 每頁商品數量的預設數量
- 其他 … etc
- 非功能的參數:
- Logging: Rotation 的規則、擋名規則、輸出模式 (File or Stdout) ..
- DI 框架的參數,像是 Autowire 掃描的規則
- 框架的設定
這些依照實際案例,會有所差異,不過我個人大概是這樣分。
Config 需要有經驗的人、經過有設計的過程,持續精煉與重構。因為沒有這個循環,隨著時間的推進 (通常是 >2y),會越來越複雜,隨之而來的是管理複雜度。如果再加上多環境部署 (不管 Test or Prod),管理問題就會浮上檯面。
Config 的設計概念參閱 Designing Configuration Loading Strategies
問題背後的問題 (QBQ)
開發過程沒有設計與管理
:在新需求開發過程中,Config 很常會因為新需求而增加,這時候沒有適度的設計與管理,時間久了,一定開花。- 不管用 K/V 結構 (.properies) 或者 object (XML / JSON / YAML),只要沒有配套的
技術管理機制
,最後就是整串葡萄串大亂鬥 - 機制:透過統一個 ConfigLoader 限制,包含命名規則、資料結構驗證等
- 規範:要有設計與 Review 流程
- 不管用 K/V 結構 (.properies) 或者 object (XML / JSON / YAML),只要沒有配套的
沒有持續收斂設計
:如果沒有適度的技術管理機制持續收斂,時間越久越亂是正常的- 各種亂象出現在 Config 裡,像是在一個 JSON element 裡面塞入一個 XML string
- 在一個 XML 的 attribute 裡塞入整個 JSON payload
部署管理機制不踏實
:- 不管有沒設計或收斂,都需要面對管理問題,因為只要有部署的需求,部署的環境越多,就要有管理流程。
- 實際上 APP 的部署第一關應該是 QA 要把關,這概念在 “DevOps 8 字環的誤區:左環問題“ 有深入說明。
理想 Config 實踐流程有以下的循環:
設計優先 (Design First)
: 系統設計的時候,#TechLead 必須把關規格持續迭代 (Continuous Iteration)
: 每次更版都要做適度的調整與迭代管理政策 (Management Policy)
: 也就是每次的更版要遵守的規範,例如 Key 的 增刪改 各自需要應對的措施- 這些規範背後需要技術支撐,像是 Config Migration 機制與流程
2. 現象:DB Schema 很複雜
DB Schema 很複雜 (或者很亂),其實背後本質是跟 Config 一樣的問題。
DB Schema (這裡指的是 Ralation DB, 不是 NoSQL) 一樣是要經過設計與收斂,透過迭代 去蕪存菁
、精煉
。資料結構的設計難的是在初期 判斷
與 預測
判斷資料溫度在未來的變化性,因為很難一次到位,所以通常都要透過以下方法:
- 設計階段 Tech Leader 需要把關 DDL 的設計
- 持續小部分的迭代與改進,調整資料溫度的配置,例如:
- 原本判定是
熱資料
,後期變成冷資料,那應該就要設計 Archive 機制,轉入OLAP
- 原本是以為是
冷資料
,變成溫資料,那就要透過快取緩存改善 - 原本是以為是
熱資料
,上線後發現根本沒有存取,所以要改成冷資料,或者一次快取。
- 原本判定是
- 規劃每次更版 DDL / DML Migration 機制與流程
這些都是透過 持續迭代
改善出來的,會越來越亂,都是因為 沒有持續迭代
、或者 經驗不足
與 能力不夠
造成的。經驗與能力我覺得找到適當的人就可以了,難的是專案管理過程中,沒有持續迭代,這也是普遍公司的問題。
看到這裡,不難發現, Config / DB Schema 的處理與管理手段是一樣的。
3. 現象:Infra 很複雜
再來談談 Infra 的部分,其實也是一樣的。
通常一個應用程式起來,都會有相應的依賴,常見的有:
- Database (RDB / NoSQL): MySQL / PostgreSQL / MongoDB / DDB … etc
- Cache: Redis / Memcached
- Queue: RabbitMQ / SQS
- Storage: File System / Object Storage (S3, GCS)
上述的排序:Structure to Non-Structure
這些東西,通常難的都不是建立 (Provisioning) 起來這件事情,因為這年代有 docker / container 這個技術,通常只要 config 講清楚,不會太難。上面列的最難的大概只有 RDB (Relation Database),因為他有 DDL 需要做 Migration,這個會稍微難一點。現在很多 ORM 都有對應的方法與策略,概念從 RoR (Ruby on Rails, 2008) 年代就有了,基本概念就是可以做到持續更迭 DDL。所以最難的沒了。
其他不管是 NoSQL / Cache / Queue / Storage …. 都談不上難。
- NoSQL 本身就是沒有 DDL Migration 的問題,因為這東西本身就是 Non-Schema 的。
- Cache 通常就是一些 Key / Value 的操作,所以只要知道 Key 的定義與結構即可
- Queue 是通道的概念,大部分只要把通道規則弄好就好,一次性的。
- Storage 目錄結構,不管是 Object Storage or Block Storage,搞懂目錄結構即可。
很多人想問,像那些 Replication / HA / Cluster 不是很難嗎?
這時候我會先分清楚目的性:Functional Test
or NonFunctional Test
如果前者,基本上,不用考慮這些是。如果是測後者,才需要考慮這些事情,看你自己的 R&R。後者通常跟 架構
很有關係,因為 前述的 (HA, Cluster … ) 很多都跟 Reliability 有關係,可靠度本質就是工程 / 架構 要面對的問題,這才是真正的難。
相關概念參閱以下的文章:
除了這些,可能還有其他像是 Networking, Platform (K8s) 的依賴。
問題背後的問題 (Problem Behind Question, PBQ)
很雜亂?很難?
上述的東西,都很雜,談不上難,但是時間只要越來越久,就會由雜變成難。更多參閱: “問題的難與雜“
只要有遵循前述的設計原則,持續迭代,給一台 Linux,足夠的 CPU / Memory / Disk,應該沒什麼做不到的。
去看看外面 Open Source ,我沒看過有哪個說一定要 K8s / AWS / GCP 才能安裝的?
我把問題歸類為:
- 設計問題
- 能力問題
- 執行力
對於 QA 而言,我自己親身經驗,裝軟體這件事情,只要上述條件具備,剩下的都是指日可待的問題。所以這問題,最後我的回答都是一樣的:
如果你覺得很複雜,那表示不夠熟悉;如果覺得很難,那代表基本功不夠紮實;如果覺得很亂,那大多都是管理問題。
團隊的問題
而蓋環境背後也可以看出整個開發團隊的問題:
- Backend 開發人員都覺得蓋環境難,表示不了解整體架構與對外依賴配置
- 有很多依賴問題:
- 例如強依賴於 Cloud Services,像是 AWS S3 / Secret Management,卻沒有做適度的設計。
- 像是用了 EKS 的 IRSA,或者 AWS IAM Role,就以為一定要 AWS 應用程式才能跑,其實這些都是不了解運作原理,以及沒有適度設 Config 造成的。
- 時間久了,導致連開發人員自己都蓋不起來,就連一些 Sr. Engineer 都搞不定。
- 沒有適度切割顆粒度,導致 Config 隨時間增長,複雜度過高。
- 切割顆粒度背後代表著要重構,一個 Method 有一千行,通常就要拆分職責。
- 有很多依賴問題:
- 太過依賴於所謂的
自動化
,而自動化的程式本身的品質堪憂,導致部署難度越來越高。- 只有寫自動化的人大概知道整個架構是怎麼一回事
- Config 的資訊只有開發人員知道,其他 (QA / Ops) 都不知道
- 蓋環境這件事情,在團隊裡是一個天方夜譚的 #能力
所以,得到結論:
蓋環境這件事情不可能
需要動用很多團隊
上述問題,在越有歷史、越有規模,但不注重軟體工程的公司,越容易發生。
翻譯:很多 (九成九) 公司都有這樣的問題。
怎麼解?
做好該做的基本功,只要想省略、或者用自動化掩蓋的念頭,時間越久會越雜。 OOP 之所以會出現,是因為 早期程式發展到複雜度而產生,而 OOP 背後的本質就是持續的分類與重構。
問題提到的 Config / DB Schema / Infra 其實都是要持續設計與改善的。不是只有自動化就天下太平,自動化只會粉飾太平。
公司已經 Run 一段時間 (>3y) 了,怎麼辦?這時候只能請 扁鵲 出場開刀了,不用懷疑,任何想要走捷徑的方法,最後一定死路一條。該開刀,就要開刀,沒有特效藥。
QA 需要自己蓋環境嗎?
QA 的職責之一是發現問題。
發現問題這個過程,背後代表要能證明 症狀 (Symptom)
真的是一個 問題 (Problem)
。如果已經是問題了,那麼一定能夠提供完整的重現步驟 (Reproducable),有相關的證據,像是 Log、Config、Data …. 等。這個過程本身是非常講究科學方法的,
當掌握環境建置的時候,上述的過程才能夠有效地掌握,也才能找出有意義的 Defect。
對我來講,蓋環境,是 QA 的第一個條件,這段在 “Software QA 的職能條件“ 的技能段落排第一位。
延伸閱讀
- 演講:從理想、到現實的距離,開啟品味軟體測試之路
- 聊聊寫 Blog 的想法
- Designing Configuration Loading Strategies
- 問題的難與雜
- DevOps 8 字環的誤區:左環問題
- Resource Provisioning and DevOps
- 如何有效的回報問題 (How to Report Problems Effectively)
- 怎樣的 CI/CD 才夠 Quality?
- 可靠性工程 (Reliability Engineering)
- Software QA 的職能條件