爲每個人提供Kubernetes端到端測試

爲每個人提供Kubernetes端到端測試

作者:Patrick Ohly(英特爾)

越來越多過去是Kubernetes組件的一部分,現在搬到在Kubernetes之外開發。例如,存儲驅動程序曾經被編譯成Kubernetes二進制文件,然後被轉移到主機上的獨立Flexvolume二進制文件中,現在作爲容器存儲接口(Container Storage Interface,CSI)驅動程序提供,這些驅動程序部署在Kubernetes集羣內部的pod中。

這對於處理此類組件的開發者來說是一個挑戰:如何在這樣的外部組件上對Kubernetes集羣進行端到端(E2E)測試?用於測試Kubernetes本身的E2E框架具有所有必要的功能。但是,嘗試在Kubernetes之外使用它很困難,只有通過仔細選擇大量依賴項的正確版本才能實現。在Kubernetes 1.13中,E2E測試變得更加簡單。

這篇博客文章總結了Kubernetes 1.13的變化。對於CSI驅動程序開發者,它將涵蓋使存儲測試可用於測試第三方CSI驅動程序。如何使用它們將基於兩個Intel CSI驅動程序顯示:

測試這些驅動程序是大多數這些增強功能的主要動機。

E2E概述

E2E測試包括幾個階段:

  • 實現測試套件。這是本篇博文的主要焦點。Kubernetes E2E框架是用Go編寫的。它依賴於Ginkgo來管理測試,而斷言(assertion)則依賴於Gomega。這些工具支持“行爲驅動開發”,它描述了“規範”中的預期行爲。在這篇博客文章中,“test”用於引用個別Ginkgo.It規範。測試使用client-go與Kubernetes集羣進行交互。
  • 啓動測試集羣。像kubetest這樣的工具可以幫忙。
  • 針對該羣集運行E2E測試套件。Ginkgo測試套件可以使用ginkgo工具運行,也可以使用go test進行正常的Go測試。沒有任何參數,Kubernetes E2E測試套件將基於環境變量(如KUBECONFIG)連接到默認集羣,與kubectl完全相同。 Kubetest還知道如何運行Kubernetes E2E套件。

Kubernetes 1.13中的E2E框架增強功能

所有以下增強都遵循相同的基本模式:它們使E2E框架在Kubernetes之外更有用和更容易使用,而不會改變原始Kubernetes e2e.test二進制文件的行爲。

拆分供應商支持

使用Kubernetes <= 1.12的E2E框架很困難的主要原因是依賴於特定於提供者的SDK,這些SDK使用了大量的軟件包。只是編譯它已經不簡單。

許多這些軟件包僅在某些測試中需要。例如,測試預配置卷的安裝必須首先通過一些非Kubernetes API,直接與特定存儲後端通信,以管理員相同的方式配置這樣的卷。

現在有嘗試從核心Kubernetes中刪除特定於雲供應商的測試。在PR#68483中採用的方法可以看作是朝着這個目標邁出的一步:不是立即剝離代碼並打破所有依賴它的測試,所有特定於雲供應商的代碼都被移動到test/e2e/framework/providers下的可選包中。然後,E2E框架通過每個供應商包單獨實現的接口訪問它。

E2E測試套件的作者決定將哪些軟件包導入測試套件。然後通過--provider命令行標誌激活供應商支持。1.13和1.14中的Kubernetes e2e.test二進制文件仍然支持與1.12中相同的供應商程序。也可以不包含任何包,這意味着只有通用供應上程序可用:

  • “skeleton”:通過Kubernetes API訪問集羣,沒有別的
  • “local”:跟“skeleton”差不多,但是另外kubernetes/kubernetes/cluster中的腳本可以在運行測試套件後通過ssh檢索日誌

外部文件

測試可能必須在運行時讀取其他文件,例如.yaml清單。但是Kubernetes e2e.test二進制文件應該是可用的並且完全獨立,因爲這簡化了發佈和運行它。Kubernetes構建系統中的解決方案是使用go-bindata將test/e2e/testing-manifests下的所有文件鏈接到二進制文件中。E2E框架過去對go-bindata的輸出有很強的依賴性,現在bindata支持是可選的。通過testfiles包訪問文件時,將從不同的源檢索文件:

  • 相對於使用--repo-root參數指定的目錄
  • 零個或多個bindata塊

測試參數

e2e.test二進制文件採用控制測試執行的附加參數。2016年,開始嘗試用Viper配置文件替換所有E2E命令行參數。但是這種努力停滯不前,這使得開發者沒有明確指導他們應該如何處理特定於測試的參數。

v1.12中的方法是將所有標誌添加到中央test/e2e/framework/test_context.go,這對於獨立於框架開發的測試不行。自PR#69105以來,建議使用普通標誌包在其自己的源代碼中定義其參數。標記名稱必須是分層的,點分隔不同的級別,例如my.test.parameter,並且必須是唯一的。標誌包強制執行唯一性,第二次註冊標誌時會發生混亂。新的配置包簡化了多個選項的定義,這些選項存儲在單個結構中。

總而言之,這就是現在如何處理參數:

  • 測試包中的init代碼定義了測試和參數。實際參數值尚不可用,因此測試定義不能使用它們。
  • 測試套件的init代碼解析參數和配置文件(可選)。
  • 測試運行並可以使用參數值。

但是,最近有人指出,比較可取且有可能不將測試設置公開爲命令行標誌,只能通過配置文件設置它們。關於這個有一個開放的bug和一個待定的PR。

Viper支持得到了增強。與供應商支持一樣,它是完全可選的。它通過導入viperconfig包被拉入e2e.test二進制文件,並在解析正常的命令行標誌後調用它。這已經實現,以便當標誌出現在Viper配置文件中時,也可以設置所有可以通過命令行標誌設置的變量。例如,Kubernetes v1.13 e2e.test二進制文件接受--viper-config=/tmp/my-config.yaml,該文件將my.test.parameter設置爲具有此內容的值:my: test: parameter: value

在較舊的Kubernetes版本中,該選項只能從當前目錄加載文件,後綴必須省略,實際上只能通過這種方式設置幾個參數。請注意Viper的一個限制仍然存在:它通過匹配已知標誌的配置文件條目,而不會發出有關未知配置文件條目的警告,從而不會檢測到錯別字。Kubernetes的更好的配置文件解析器仍在開發中。

從.yaml創建項目清單

在Kubernetes 1.12中,有一些支持從.yaml文件加載單個項目,但是然後創建該項目必須通過手寫代碼完成。現在,框架提供新方法加載具有多個項目的.yaml文件、修補這些項目(例如,設置爲當前測試創建的命名空間)以及創建它們。這目前用於爲每個測試重新部署CSI驅動程序,這些驅動程序來自完全相同的.yaml文件,這些文件也用於通過kubectl進行部署。如果CSI驅動程序支持以不同的名稱運行,則測試完全獨立並且可以並行運行。

但是,重新部署驅動程序會降低測試執行速度,並且不會涵蓋針對驅動程序的併發操作。更現實的測試場景是在啓動測試集羣時部署驅動程序一次,然後針對該部署運行所有測試。最終,Kubernetes E2E測試將轉移到該模型,一旦更清楚如何擴展測試集羣的啓動,包括安裝CSI驅動程序等其他實體。

Kubernetes 1.14推出的增強功能

重用存儲測試

能夠使用Kubernetes之外的框架可以構建自定義測試套件。但是沒有測試的測試套件仍然沒用。一些現有的測試,特別是用於存儲的測試,可以應用於樹外組件。感謝Masaki Kimura所做的工作,Kubernetes 1.13中的存儲測試被定義爲可以針對不同的驅動程序多次實例化它們。

但歷史有重複的習慣。與供應商程序一樣,定義這些測試的程序包也提取了所有樹內存儲後端的驅動程序定義,這反過來又拉取了比所需更多的附加程序包。這在Kubernetes 1.14進行了修復。

跳過不支持的測試

某些存儲測試依賴於羣集的功能(如在支持XFS的主機上運行)或驅動程序(如支持塊卷)。在測試運行時檢查這些條件,導致在不滿意時跳過測試。好的是這記錄解釋了爲什麼測試沒有運行。

開始測試很慢,特別是當它必須首先部署CSI驅動程序時,在其他情況下也差不多。在快速集羣上測量爲測試創建命名空間的時間爲5秒,並且會產生大量噪聲測試輸出。本來可以解決這個問題,通過跳過不支持的測試的定義,然後報告爲什麼測試甚至不是測試套件的一部分變得棘手。這種方法已不被考慮,而是採用重新組織存儲測試套件的方式,以便在進行更昂貴的測試設置步驟之前首先檢查條件。

更易讀的測試定義

同樣的PR還將測試重寫,接近傳統的Ginkgo測試,測試用例及其局部變量在一個函數中。

測試外部驅動程序

構建自定義E2E測試套件仍然是相當多的工作。將在Kubernetes 1.14測試檔案中分發的e2e.test二進制文件將能夠測試已安裝的存儲驅動程序,而無需重建測試套件。有關詳細說明,請參閱本自述文件。

E2E測試套件HOWTO

測試套件初始化

第一步是設置定義測試套件的必要樣板代碼。在Kubernetes E2E中,這是在e2e.go和e2e_test.go文件中完成的。它也可以在e2e_test.go文件中完成。Kubernetes在e2e_test.go中導入所有各種供應商程序、樹內測試、Viper配置支持和bindata文件。e2e.go控制實際執行,包括一些集羣準備和指標收集。

一個更簡單的起點是來自PMEM-CSI的e2e_[test].go文件。它不使用任何供應商程序,沒有Viper,沒有bindata,只導入存儲測試。

與PMEM-CSI一樣,OIM會丟棄所有額外功能,但有點複雜,因爲它將自定義集羣啓動直接集成到測試套件中,在這種情況下非常有用,因爲一些額外的組件必須在主機端運行。通過直接在E2E二進制文件中運行它們,使用dlv進行交互式調試變得更加容易。

這兩個CSI驅動程序都遵循Kubernetes示例,並使用test/e2e目錄作爲其測試套件,但也可以使用任何其他目錄和其他文件名。

添加E2E存儲測試

測試由導入測試套件的包定義。E2E測試唯一特有的是,它們使用framework.NewDefaultFramework實例化一個framework.Framework指針(通常稱爲f)。此變量在每個測試的BeforeEach中重新初始化,並在AfterEach中釋放。它在運行時有一個f.ClientSet和f.Namespace(並且只在運行時!),可以由測試使用。

PMEM-CSI存儲測試導Kubernetes存儲測試套件,併爲必須已安裝在測試集羣中的PMEM-CSI驅動程序設置一個供應測試實例。存儲測試套件更改存儲類以使用不同的文件系統類型運行測試。由於此要求,存儲類是從.yaml文件創建的。

解釋框架中可用的所有各種實用方法超出了本博文的範圍。閱讀現有測試和框架的源代碼是一個很好的入門方法。

提供代碼

即使消除了許多不必要的依賴關係,提供Kubernetes代碼仍然不是一件容易的事。k8s.io/kubernetes並不意味着包含在其他項目中,也沒有以dep等工具理解的方式定義其依賴關係。其他k8s.io包應包含在內,但不遵循語義版本控制或不標記任何版本(k8s.io/kube-openapi,k8s.io/utils)。

PMEM-CSI使用dep。它的Gopkg.toml文件是一個很好的起點。它啓用了修剪(默認情況下未在dep中啓用)並將某些項目鎖定到與所使用的Kubernetes版本兼容的版本上。當dep沒有選擇兼容的版本時,檢查Kubernetes的Godeps.json有助於確定哪個版本可能是正確的版本。

編譯並運行測試套件

go test ./test/e2e -args -help是測試測試套件編譯的最快方法。

一旦編譯完成並且已經設置了集羣,go test -timeout=0 -v ./test/e2e -ginkgo.v命令將運行所有測試。要並行運行測試,請使用ginkgo -p ./test/e2e命令。

如何參與

Kubernetes E2E框架由測試SIG的testing-commons子項目所有。請參閱該頁面以獲取聯繫信息。

有各種任務,包括但不限於:

  • 將test/e2e/framework移動到staging倉庫並重組它以使其更加模塊化(#74352)。
  • 通過將更多代碼移入test/e2e/framework(#74353)來簡化e2e.go。
  • 從Kubernetes E2E測試套件中刪除特定於供應商程序的代碼(#70194)。

鳴謝

特別感謝本文的審閱者:


KubeCon + CloudNativeCon + Open Source Summit大會日期:

  • 會議日程通告日期:2019 年 4 月 10 日
  • 會議活動舉辦日期:2019 年 6 月 24 至 26 日

KubeCon + CloudNativeCon + Open Source Summit贊助方案
KubeCon + CloudNativeCon + Open Source Summit多元化獎學金現正接受申請
KubeCon + CloudNativeCon和Open Source Summit即將首次合體落地中國
KubeCon + CloudNativeCon + Open Source Summit購票窗口,立即購票!
CNCF邀請你加入最終用戶社區

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章