在先前的文章,已分享過使用 JMeter 和 drill 進行小規模 Load Testing,今天延續同樣的主題,這次要使用另一個新興熱門的 Load Testing 工具 K6,試一試「如何透過 GitLab CI + K6 進行小規模 Load Testing」。
操作步驟
首先,K6 在 2021 年已經被 Grafana Labs 買下來了,但目前(2022/02/03)看來,K6 官網依然還維持原貌,沒有太大的變化,只是多掛上了 Grafana Labs 的 Logo。K6 有提供 Open Source 與 K6 Cloud 兩種方案,而本文將採用的是 Open Source 方案。
準備 GitLab Runner
老樣子,第一步我們要先預備合適的 GitLab CI 環境,應該不用再多做解釋,請先準備好能夠操控 Container 的 GitLab Runner,如果你不知該如何準備 Runner,又想要快速試一下本文的內容,那最簡單的做法是註冊一個 gitlab.com 帳號,然後建立新 Project 並使用官方提供的 Shared Runners。
準備 Docker image - K6
第二步,預備一個能夠運行 K6 的 Docker image。
這次很幸運,已經有現成的 Image 可以使用 loadimpact/k6
建立 CI Pipeline
第三步,開一個全新的 GitLab Project(Repository),並撰寫 .gitlab-ci.yml
建立我們所需的 Pipeline。
# .gitlab-ci.yml
# Job name 叫做 k6
k6:
# 指定能操控 docker 的 Runner
tags:
- "docker"
image:
name: loadimpact/k6
# entrypoint 很重要,沒設定這項,會出現找不到 load-testing.js 的錯誤。
entrypoint: ['']
# 要執行的動作只有一項,就是根據 load-testing.js 去跑 Load Testing
script:
- k6 run load-testing.js
撰寫 load-testing.js
K6 接受的 load testing 測試腳本格式是 .js
,如果是熟習 JS 的人可能會感到親切,但對於只會 .yml
的 YAML 工程師可能就需要多一點學習了,好在 K6 官網的文件內容詳盡,因此要快速寫出可用的測試腳本並不困難,下面就直接做一個簡單的示範。
// 引用必要套件
import { check } from 'k6';
import http from 'k6/http';
export default function () {
// 可以定義變數供後續使用
const url = 'https://chengweichen.com';
const check_keyword = 'Cheng Wei Chen';
// 直接就對目標 url 發動測試
const result = http.get(url);
// 同時要驗證 Response 是否吻合期待,以及是否含有特定的文字
check(result, {
'http code = 200': (r) => r.status === 200,
'verify homepage text': (r) => r.body.includes(check_keyword),
});
}
// 設定要實行多大規模的 Load testing
export const options = {
//
duration: '1m', // 測試總共要跑多久時間
vus: 10, // 同時要模擬的人數
// 更進階的測試成功與失敗條件,這比較複雜,請參閱官網文件。
thresholds: {
// 這裡直接引用官方教學的範例。
// 95 percent of response times must be below 500ms
http_req_duration: ['p(95)<500'],
},
};
將 Output 儲存為 Artifacts
上面的測試腳本順利執行後,就能在 CI Job Log 看到類似下面兩張圖片的結果。
(在大大的 K6 圖案之下,開始條列各項測試結果。)
(checks
皆有成功通過,因此是 100.00%
。)
最後,我們再對 .gitlab-ci.yml
做一點微調,讓 Output 的資訊儲存進 GitLab Artifacts 中。
# .gitlab-ci.yml
k6:
tags:
- "docker"
image:
name: loadimpact/k6
entrypoint: ['']
script:
- k6 run load-testing.js --out json=result.json
artifacts:
paths:
- result.json
【補充】直接使用
--out json=result.json
會得到完整的 Output 資訊,以上面的示範為例,最終產生的 .json 容量高達 73.9MB,因此建議大家務必要詳細參閱 K6 的文件,只需保留你所需的 Output 資訊。另外就是 K6 支援將 Output 輸出至其他的第三方服務,因此實務上你可以直接將 Output 餵給你的 Prometheus、AWS 的 CloudWatch 或其他服務,並不一定要如上面的示範儲存在 GitLab Artifacts 中。
更彈性的進行 Load Testing
最後還是老樣子,我們希望能更彈性的進行 Load Testing,如果想要動態的變更 Load Testing 的目標及強度,該怎麼做呢?好在 K6 也提供了許多彈性,因此我們一樣能用老方法,運用 GitLab CI 的 Variables 加上 Run Pipeline 可動態變更 Variables 的方式處理。
修改 .gitlab-ci.yml
,調整 Run K6 的 Command,並且定義變數的預設值。
# .gitlab-ci.yml
# 定義所需的變數預設值
variables:
K6_VUS: 10
K6_DURATION: 1m
TESTING_URL: https://chengweichen.com
TESTING_KEYWORD: "Cheng Wei Chen"
k6:
tags:
- "docker"
image:
name: loadimpact/k6
entrypoint: ['']
script:
# 加上參數 --include-system-env-vars
- k6 run load-testing.js --out json=result.json --include-system-env-vars
artifacts:
paths:
- result.json
由於 K6 接受 Environment variables,因此在上面我們可以直接用 K6_VUS
與 K6_DURATION
來取代原本設置在 load-testing.js
中的 vus
與 duration
。至於要施測的網址與該檢查的字串,也同樣設置在 ENV 中,並透過 --include-system-env-vars
傳遞給 K6 使用。
修改 load-testing.js
,將變數放在正確的位置。
import { check } from 'k6';
import http from 'k6/http';
export default function () {
// 從 ENV 中取得變數值
const url = `${__ENV.TESTING_URL}`;
const check_keyword = `${__ENV.TESTING_KEYWORD}`;
const result = http.get(url);
check(result, {
'http code = 200': (r) => r.status === 200,
'verify homepage text': (r) => r.body.includes(check_keyword),
});
}
export const options = {
// duration 與 vus 改由 ENV 取得,因此將下面兩行註解
// duration: '1m',
// vus: 10,
thresholds: {
http_req_duration: ['p(95)<500'],
},
};
透過上面的修改,在沒有輸入變數的狀況下,就會用預設值來執行 K6。如果想要動態修改測試內容,就能透過 GitLab 的 Run pipeline
來進行指定的 Load Testing。
(在 Run pipeline
的介面中,輸入這一次的 Pipeline 要使用哪些 Variables。)
Pipeline 順利執行,並取得結果。
(上面我故意填寫錯誤的 TESTING_KEYWORD
,果然在 verify homepage text
這邊出現 0%
的結果。)
結語
延續前兩次運用 GitLab CI 來進行小規模 Load Testing 的文章,這次我們又換了一個工具,變成以 GitLab CI + K6 來實施測試。
這次撰寫文章,也順利試用了 K6 這項新興的 Load Testing 工具,K6 使用起來容易,可以快速上手,又具備可輕易與其他服務整合的特性,不愧是被大廠看上的新工具。
最後還是要小提醒一下,本文僅是一個簡單的 DEMO,只靠單一 GitLab Runner 我們能模擬的最大負載量是有限的,如果你需要進行的是切切實實的大流量及高負載 Load Testing,那你還需要更多的前置作業,又或者不妨考慮直接採購 K6 Cloud。
針對本文我依然有建立一個 DEMO Project,公開放在 gitlab.com,有興趣者可自行 Fork 參考,同樣的為了避免 Public Project 的 CI/CD 被人亂按,Pipeline 已關閉權限避免被人隨意誤觸。