開發如何考慮維運

CI 講了這麼久,大家也許會覺得跟維運人員好像沒什麼太大關係,因為幾乎都環繞在測試上。今天來聊聊 DevOps 的其中一半:開發如何考慮維運

測試是測上線的過程

先破題,不管是哪種測試,都是在假設上線的狀況下執行不是嗎?所以測試本身就是站在維運的角度看程式了。範圍比較小的單元測試也許比較無感,但擴大到跟其他元件的整合測試時,其實就會發現某些測試會需要維運人員協助,如手動測試前,必須先把所有依賴服務與測試機器都先準備好,接著把程式部署上去才能開始測。

所以開發要如何考慮維運呢?其實「概念上」非常地簡單,只要要求開發人員每次測試都親自做就行了!

這是要逼死誰?

或許會有開發人員抗議,明明部署測試機器是維運的事,為何要開發自己來?還記得 Day 02 提到的 Hello World 嗎?開發人員測程式,本來就該知道測試的環境要如何部署了,這沒有抗議的道理。但環境部署通常有固定的模式,而這正是維運人員拿手好戲,所以可以由維運人員撰寫腳本,讓開發容易地在任何地方建立起基礎環境。

而開發人員每次測試都需要部署程式,部署方法很多,但概念上都是把可執行的程式丟到基礎環境上,另外同時也把環境的設定初始化,最後就是資料遷移,都完成後才開始測。以測試 3A 的角度來看,這是 Arrange 的過程。這個過程應該是開發人員最熟悉的,畢竟是寫程式的人,應該會非常清楚如何部署。

所以前面基礎環境可以由維運人員寫腳本變成一行指令建機器,後面開發人員只要讓部署變得簡單快速,那對維運人員就太完美了。

如何簡化部署流程?

上面有提到部署的過程,其實不外乎三個重點。

  • 更新程式
  • 更新設定檔
  • 資料遷移

更新程式,通常 compile 跟可執行檔都有固定對應的上傳路徑,這部分是可以自動執行的。資料遷移也有固定的方法,也可以執行。部署常出現一個好像需要人為介入的部分,叫設定。好像也沒錯,帳密設定是由人手動加入的,但沒人會想在原始碼裡放帳密。因此有一個常見的解法,稱為環境變數。環境變數正如其名,它是變數,不過是因環境而變。幾乎所有系統都有環境變數的實作,也幾乎所有語言都可以取得目前環境的變數值。

因環境變數是定義在系統上,不同的環境,就應當要有不同的環境變數。定義在系統裡的好處是,程式的更新會跟環境無關。這樣的做法,在部署的時候就不會把設定值取代掉,而繼續沿用之前的設定。程式在取得不同的環境變數後就可以做不一樣的行為,如開發者可以開啟 debug 模式,而正式上線不開啟。

聽起來好像很厲害,那該如何寫呢?比方說上例的 debug 模式可以這樣寫:

<?php

$debug = getenv('DEBUG');

於是 $debug 的變數就會取得環境變數 DEBUG 的值,再去做後續的處理。

開發做這有什麼好處嗎?

嚴格說起來,是不一定!但如果需要管理多個環境時,絕對會認為這是神器。比方說像我開發需要管理的環境有三種

  • Notebook
  • Docker
  • CI Server

開發通常會有支援檔案整合環境變數的套件,通常查 dotenv 都會有相關的資訊,這部分就跳過。Docker 如果用 Docker Compose 可以這樣定義:

server:
image: php:7.0-apache
environment:
DEBUG: 1

上例就是打開 debug 模式。CI 也有類似的做法,如 CircleCI 是這樣定義的:

machine:
php:
version: 7.0.7
environment:
DEBUG: 0

CI 我不想開 debug 模式,那這樣設定即可。

是的,不需要寫腳本去做字串 replace,也不需要擔心機敏資料被別人發現,它只要在存在機器裡就能繼續被使用。理想上,部署只要整包程式丟上去,設定不需要調整就能直接 work 了。

今日回顧

雖然是說「要求開發人員」,但實際上是大家共同寫出一個自動化系統,讓開發人員方便測試並快速取得結果。最終目的還是為了 CI 精神!