End-to-End Testing for Kubernetes (Part II) - Conformance Testing

此系列文為 E2E Testing for Kubernetes 的介紹,如尚未看過前一篇文章,可以參考底下連結:

Conformance Testing

在前一篇文章裡,我們介紹到如何使用 kubetest 執行 Kubernetes E2E Test , kubetest 會使用 Kubernetes Binary 開啟新的乾淨 Cluster 去做測試。在這一篇文章裡我們會介紹如何對自己部署的 Cluster 做 E2E Test。

Conformance Testing ,一致性測試,這個測試是 E2E Testing 底下的一個子集合,其主要是驗證 Kubernetes 核心的功能或是 GA 版本的 API ,也就是不管任何版本的 Cluster 都應該要能使用的基本功能。這個測試也可以解讀成: 「不管任何版本或平台的 Cluster 在經過 Conformance Test 之後的結果都要是一致的」。由於 Conformance Test 比較不限定於 Cluster 版本或是平台,因此可以用來測試自己部署的 Cluster 是否是正常的。另外 Conformance Test 也是非破壞性的測試,不會包含 [Disruptive] 的測項,因此並不會影響到 Cluster 上面運行的其他服務。

在前一篇文章有提到 Kind of Test ,其中一個 Label 是 [Conformance] ,這個就是代表 Conformance Test 的測項。

Conformance Test Requirements

Kubernetes 有列出 Conformance Test 需要滿足的條件,有非常多項,其中包含只測試 GA 版本的 API 、必須可以使用在任何 Provider 上、不需要連接到 Public Network 、不需要 Privileged 權限或是不能包含具有關於 Node 或是平台相依性的測試,如硬體規格限制等等。不過這份文件也有提到如果將來有足夠的測項能測試 Cluster 之後,會慢慢的放寬這些條件,加入更多的測項進來。

  • it tests only GA, non-optional features or APIs (e.g., no alpha or beta endpoints, no feature flags required, no deprecated features)
  • it does not require direct access to kubelet’s API to pass (nor does it require indirect access via the API server node proxy endpoint); it MAY use the kubelet API for debugging purposes upon failure
  • it works for all providers (e.g., no SkipIfProviderIs/SkipUnlessProviderIs calls)
  • it is non-privileged (e.g., does not require root on nodes, access to raw network interfaces, or Cluster admin permissions)
  • it works without access to the public internet (short of whatever is required to pre-pull images for conformance tests)

如果想了解更細部的需求條件可以參考 Conformance Test Requirements

Exexcution

我們同樣可以使用 kubetest 來執行 Conformance Test ,執行步驟非常簡單,只需要限定只執行 [Conformance] Label 的測項即可。

  1. 前置作業

    # Checking your kubernetes server version
    $ kubectl get version

    Server Version: version.Info{Major:"1", Minor:"15", GitVersion:"v1.15.3", GitCommit:"2d3c76f9091b6bec110a5e63777c332469e0cba2", GitTreeState:"clean", BuildDate:"2019-08-19T11:05:50Z", GoVersion:"go1.12.9", Compiler:"gc", Platform:"linux/amd64"}

    # Change Kubernetes repository to the specific version
    $ cd $GOPATH/src/k8s.io/kubernetes
    $ git checkout v1.15.3

    # Build e2e.test, ginkgo and kubectl
    # 這邊也可以直接使用 kubetest --build ,只是 Conformance Testing 不需要
    # build 這麼多東西。
    $ make WHAT="test/e2e/e2e.test vendor/github.com/onsi/ginkgo/ginkgo cmd/kubectl"

    這邊需要注意的是: kubetest 會直接抓 Kubernetes 目錄 Build 出來的 kubectl 當作 Client 去做測試, 如果 kubectl 的版本 ( GitVersion ) 與 Server 版本不一致, kubetest 會報錯,因此最好先將 Kubernetes 切換到對應版本的 branch/tag ,再 build e2e.test 跟 kubectl 比較好。

    如果真的想要用不同版本的 Client (kubectl) 做測試,可以在 kubetest 後面加上 --check-version-skew=false flag,但是不建議這樣做,因為可能會影響測試的準確度。

  2. 執行測試

    # Setup for conformance tests
    $ export KUBECONFIG=/path/to/kubeconfig
    $ export KUBERNETES_CONFORMANCE_TEST=y

    # Run testing
    $ kubetest --provider=skeleton --test --test_args="--ginkgo.focus=\[Conformance\]"

    # Run testing with different version of client
    $ kubetest --provider=skeleton --test --test_args="--ginkgo.focus=\[Conformance\]" --check-version-skew=false

    當設定 KUBERNETES_CONFORMANCE_TEST=y 時, kubernetes/hack/ginkgo-e2e.sh 就會從 KUBECONFIG 來取得 Master 位置,因此不再需要使用 --deployment flag 去告訴 kubetest (Ginkgo) Cluster 資訊。

    --provider=skeleton: 這邊的 skeleton 筆者也不確定如何解釋,類似於只有骨架,表示你的 Cluster 只有提供 API 介面(直接提供kubeconfig就可以存取到 Cluster ),而看不到整個整體的 Cluster ,這邊如果讀者有更好的解釋的話,再麻煩幫我修正一下,謝謝。

    筆者實際執行 Conformance Test 大概花了 3~4 小時左右,不過同樣可能跟筆者 Homelab 硬體資源有關,實際上應該不需要這多時間。

Test Lists

由於 Conformance Testing 是 E2E Testing 的子集合,因此其測項一樣位於 kubernetes/test/e2e/ 裡,不過 Kubernetes 有特別將 Conformance Testing 的測試項目清單記錄在 conformance.txt 底下,如果要細看每一個測項內容的話也可以參考 Kubernetes Conformance Test Suite - v1.9

kubernetes/test/conformance/testdata/conformance.txt

查看其中一個 spec ,會發現 Conformance Test 是使用 framework.ConformanceIt() ,而不是像 E2E Test 使用 Ginkgo.It()

kubernetes/test/e2e/common/pods.go

...
/*
Release : v1.9
Testname: Pods, assigned hostip
Description: Create a Pod. Pod status MUST return successfully and contains a valid IP address.
*/
framework.ConformanceIt("should get a host IP [NodeConformance]", func() {
name := "pod-hostip-" + string(uuid.NewUUID())
testHostIP(podClient, &v1.Pod{
ObjectMeta: metav1.ObjectMeta{
Name: name,
},
Spec: v1.PodSpec{
Containers: []v1.Container{
{
Name: "test",
Image: imageutils.GetPauseImageName(),
},
},
},
})
})
...

實際去看 framework.ConformanceIt() 內容 (位於 kubernetes/test/e2e/framework/framework.go) ,會發現 ConformanceIt() 的功能為貼 [Conformance] Label ,至於為什麼要特別額外用一個 function 來貼 Label ,這邊官方註解是方便靜態分析用,不過筆者認為這樣也可以方便之後針對 Conformance Test 作修改,例如對所有的 Conformance Test 加上額外的 Label 或是增加什麼內容,直接透過 ConformanceIt() 就可以統一修改了。

kubernetes/test/e2e/framework/framework.go

...
// ConformanceIt is wrapper function for ginkgo It. Adds "[Conformance]" tag and makes static analysis easier.
func ConformanceIt(text string, body interface{}, timeout ...float64) bool {
return ginkgo.It(text+" [Conformance]", body, timeout...)
}
...

Write Your Own Test

接下來介紹如何撰寫自己的測項 ,基本上都跟 E2E Test 差不多,不過不確定是不是因為一般使用者比較常使用到 Conformance Test , 這部分文件比 E2E Test 完整許多。

我們將撰寫測試分成三個步驟:

  1. 撰寫測試。
  2. 確保你的測試有符合 [Conformance Test Requirements](#Conformance-Test-Requirements)。
  3. 發送 PR

細部流程可參考 Promoting Tests to Conformance

1. 撰寫測試
在撰寫 Conformance Test 時必須遵守兩個的格式,一個是一定要使用 framework.ConformanceIt() ,不要使用 Ginkgo.It 。 另一個是一定要撰寫 metadata ,格式如下:

/*
Release : v1.15.3
Testname: Kubelet: log output
Description: By default the stdout and stderr from the process being
executed in a pod MUST be sent to the pod's logs.
*/
framework.ConformanceIt("it should print the output to logs", func() {
...
})

測試放置位置以及 Import 位置都與我們之前撰寫的 E2E Test 相同,因此這邊只簡單列出流程,細節部分可以參考前一篇文章。

1. 在 kubernets/test/e2e 建立資料夾來放置你的測試檔。
2. 在 kubernets/test/e2e/e2e_test.go 以及 kubernets/test/e2e/BUILD import 你的測試。
3. 在 kubernets/test/e2e/<yourfolder>/ 下新增你的 BUILD 檔。
4. 更新 conformance.txt
5. 使用 kubetest --build 重新 build e2e.test

比較需要注意是第四步必須執行以下指令來更新 conformance.txt :

$ go run test/conformance/walk.go test/e2e > test/conformance/testdata/conformance.txt

請記得在撰寫自己的測試時一定要加上對應 Label ,如 [Slow][Serial][Disruptive] 等等,這樣可以讓測試人員更加了解你的測項的特性,如果不確定要加上哪些 Label 可以在 slack 或是 發佈 Issue / PR 時,標註 #kinds-of-tests 來詢問。

2. 確保你的測試有符合 [Conformance Test Requirements]
這部分可以參考 Conformance Test Requirements

3. 發送 PR

1. PR Title:  "Promote xxx e2e test to Conformance"
2. 撰寫測項的資訊以及 metadata,並加上 PR Label 以及標註負責的 SIG。
- /area conformance
- @kubernetes/sig-architecture-pr-reviews @kubernetes/sig-xxx-pr-reviews
@kubernetes/cncf-conformance-wg
- Any necessary information (e.g. 例如解釋為什麼測項無法在 Windows 執行)
3. 將 PR 加到 SIG Architecture's Conformance Test Review board 的 To Triage 欄位。
4. 使用 /test pull-kubernetes-e2e-aks-engine-azure-windows 來測試項目能否正常跑在 Windows Node 上

Conformance Test Review board

For Windows

Comforance Testing 並沒有強制要求測項一定要支援 Windows Node ,但是既然 Kubernetes 有支援 Windows ,那還是必須要能夠對 Windows Node 做 Conformance Test 。在現有的測項中,大部分的測項都是可以在 Windows Node 執行的,只有少部分貼上 [LinuxOnly] 的測項是不能跑在 Windows 上的。

在撰寫自己的測試時,如果不確定 Linux Node 和 Windows Node 在測試執行上的差異或是不確定你寫的測項是否可以運行在 Windows 的話,可以參考 Windows & Linux Considerations

如果撰寫的測試不支援 Windows ,一定要標註 [LinuxOnly] Label,且在送PR時寫清楚為何不能跑在 Windows Node 上,讓 Reviewer 知道。

VMware Tanzu (Heptio) Sonobuoy

另外一個常見的 Kubernetes Conformance Testing Tool 是由 VMware Tanzu (Heptio) 開發的 Sonobuoy 。 Sonobuoy 提供比 kubetest 更方便的介面來做 Conformance Test ,只需要簡單幾行指令就可以執行測試,測試項目也與 kubetest 使用的 ( kubernetes/test/e2e/... ) 是完全一樣的,差別在於 Sonobuoy 是預先將測項全部放到 Docker Image 裡面,因此不需要像 kubetest 需要特別 Build e2e.test,不過需要注意的是 Sonobuoy 只支援前三新的 Kubernetes 版本。

Sonobuoy Website

Certified Kubernetes

Sonobuoy 同時也是 CNCF 官方用來認證 Kubernetes Cluster 的 Conformance Testing Tool,企業可以使用 Sonobuoy 來驗證自己開發的 Kubernetes 部署工具佈出來的 Cluster ,如果通過測試可以將結果提交到 GitHub ,該部署工具就可以獲得 CNCF 的認證標章,並顯示在 CNCF 官網上,詳細驗證流程可以參考 Certified Kubernetes

Execution

Sonobuoy 執行方式也很簡單,只需要設定 KUBECONFIG 然後執行 sonobuoy run 就可以跑 Conformance Test 了。

$ export KUBECONFIG=/path/to/kubeconfig
$ go get -u -v github.com/heptio/sonobuoy

# Start testing and wait until they are finished run:
$ sonobuoy run --wait

# Get the result
$ results=$(sonobuoy retrieve)
$ sonobuoy e2e $results

# Delete the objects deployed by sonobuoy
$ sonobuoy delete

Result

Sonobuoy 執行結果報告大致架構如下( Sonobuoy Snapshot Layout ):

servergroups.json: 紀錄 Kubernetes API 資訊
serverversion.json: 紀錄 Kubernetes Cluster 版本資訊

hosts
放置每個 Node 的 Configuration ( configz.json )跟健康狀態 ( healthz.json )

meta

  • config.json: 放置 Sonobuoy 的設定檔。
  • query-time.json: Sonobuoy 在處理各種 Resource 的反應時間,類似 Performenace Testing 。
  • run.log: Sonobuoy執行的 log ,注意這不是 Kubernetes Log。

plugins
放置 Plugins 的詳細資訊。

podlogs
放置 Pod 的 Log ,注意這裡預設只會有 Sonobuoy 產生的 Pod 的 Log。

resources
放置 Kubernetes Cluster 的 Resource 資訊。

Cluster: 放所有不屬於任何 Namespaces 的 Resources,如 RoleBinding 、 Namespaces 等等。
ns: 放各個不同 Namespaces 的 Resources。

這邊是依照 Resource 種類去作分類,一個種類就是一個 JSON 檔,例如 pohsien namespace 裡面有100個 Pod , Sonobuoy 就會在 resources/ns/pohsien/pods.json 放100個 Pod 資訊,並不會有100個 JSON 檔。

Sonobuoy vs kubetest

Sonobuoy 提供了比 kubetest 更加簡單的方式執行 Conformance Test,其不需要 Build Kubernetes Binary ,也不需要比較麻煩的步驟執行測試。輸出結果部分,Sonobuoy 也提供很完善的 Output 機制,方便測試人員去查看測試結果。因為上述的優點,所以 Sonobuoy 成為了目前主流的 Kubernetes Conformance Testing Tool 。

但是由於 Sonobuoy 畢竟是第三方的工具,它會從 Kubernetes 官方目錄取得測項以及需要的資料並放置在 Sonobuoy Docker Image ,這提升了使用上方便性,但也導致其可能會沒辦法取得最新的測試項目。主要因為 Kubernetes 更新速度非常快,在每一次的更新之後, Sonobuoy 都會需要去更新 Image,而在等待 Sonobuoy 更新這段時間測項就會出現落差。不過筆者認為如果沒有要測試最新版本的 Cluster ,就比較不需要擔心這個問題,或著是可以設定排程一段時間更新 Sonobuoy ,然後再次做測試。

Summary

在這系列文我們介紹了 Kubernets End to End Testing ,包括怎使用 kubetest 執行 E2E Test 以及 Conformance Test ,也簡單介紹了如何撰寫自己的測項,最後也介紹如何使用 CNCF 官方的 Comformance Testing Tool - Sonobuoy 。

E2E Testing 是在企業導入 Kubernetes 流程中是相當重要的一步,無論是使用什麼工具部署,建議都使用 E2E Testing 來驗證 Cluster 是否正常,這樣當發生任何問題時,比較可以排除掉 Cluster 本身的問題,減少問題定位的成本。

另外也可以定期的執行 E2E Testing / Conformance Testing 或是直接將測試整合進 CI/CD 流程裡,不過最好根據自己的環境狀況來評估,雖然 Conformance Testing 是無破壞性的測試,但是直接對於 Production 環境去做測試其實還是會有一些風險 (例如影響效能或是非預期內錯誤等等) ,因此還是需要特別注意,或著是也可以在測試前,先將重要服務轉移出去,待測試完成後再轉移回來,也是一個方法,實際執行方式可以根據自己的環境去做評估。

References

  1. Conformance Testing in Kubernetes
  2. Kubernetes Conformance Test Suite - v1.9
  3. Conformance.txt
  4. Sonobuoy
  5. CNCF - Certified Kubernetes

文章內容的轉載、重製、發佈,請註明出處: https://pohsienshih.github.io