敝社從 2016 年就開始 Kubernetes,應該能算是相當早期的使用者了,也因此我們累積了一堆的 Kubernetes YAML 設定檔,從某個時間開始 staging 和 production 環境的設定檔更開始分裂,自此以來一直無法合併。因此這次的目標就是:
一開始我先從 awesome-kubernetes 尋找現有的設定管理工具,以下列出一些我覺得還不錯的工具以及它們的優缺點。
因為現有工具對我來說都有些不足的地方,所以我最後決定根據 ksonnet 的概念,並稍微調整一些部份讓我用起來更順手一些:
相較於 ksonnet 來說砍了很多功能,所以實際上實作並沒有花太多時間,麻煩的是把現有的上百個 YAML 檔轉換成 JavaScript、整合 staging 和 production 環境並實際在 Kubernetes 上測試,大約花了 5 週才完成所有工作,最後的結果非常可觀。
npm install kosko -g
kosko init examplecd examplenpm install
# 輸出到 consolekosko generate# Apply 到 Kubernetes cluster 上kosko generate | kubectl apply -f -
其實在執行 kosko generate
時也會順帶驗證,這個指令只是用來方便在 CI 上跑測試時不會把設定輸出到 log。
kosko validate
# 單一檔案kosko migrate -f nginx-deployment.yml# 資料夾kosko migrate -f nginx
預設的資料夾結構參考 ksonnet,components
資料夾用來放 manifests,environments
則是各環境的參數。
.├── components│ ├── nginx.js│ └── postgres.js├── environments│ ├── staging│ │ ├── index.js│ │ ├── nginx.js│ │ └── postgres.js│ └── production│ ├── index.js│ ├── nginx.js│ └── postgres.js├── kosko.toml└── templates
但實際使用時發現這種結構在 components 過多時使用起來必須要在 components
和 environments
兩個資料夾來回,不太方便,所以最後加上了自訂路徑的功能。
[paths.environment]component = "components/#{component}/#{environment}"
上述的設定改變了 component environments 的檔案路徑,變成了下列的結構:
.├── components│ ├── nginx│ │ ├── index.js│ │ ├── staging.js│ │ └── production.js│ └── postgres│ ├── index.js│ ├── staging.js│ └── production.js├── environments│ ├── staging.js│ └── production.js├── kosko.toml└── templates
為了能夠驗證設定是否符合 schema,我根據 Kubernetes 的 OpenAPI specification 產生了相對應的 TypeScript。不僅能夠在編譯時找出一些基本的型別錯誤,即使沒有使用 TypeScript 也能透過 JSON schema 驗證設定。
下面列出一些開發時遇到的問題:
JSON 實際上是沒有 undefined
型別的,雖然 JSON.stringify
會直接忽略,但是 js-yaml 卻不會,所以我必須在 toJSON()
函數裡刪除所有 undefined
的欄位。
在 Kubernetes 裡有一種特殊型別叫做 int-or-string
,雖然在 JSON schema 是 string
,但在 TypeScript 必須轉為 string | number
,不然編譯器常會報錯。舉例來說,Service
中的 targetPort
就是常見的情況,它同時可以是 port number (int) 或 named port (string)。
new Service({ spec: { ports: [{ port: 80, targetPort: 80 }] }});
最後炫耀一下,在支援 TypeScript 的編輯器裡寫設定有多爽 😎
一開始其實是打算用 ksonnet 的,但是必須要另外學 jsonnet 很麻煩。開始造輪子大約一個月後發現 ksonnet 竟然停止維護了,不禁感嘆幸好當初選擇了自己造輪子?
其他使用 Kubernetes 的大大們可能也會遇到設定管理的問題,不知道各位是怎麼解決的?是使用官方的 kustomize?還是也自己開發工具?又是如何管理 secrets 呢?如果可以的話,希望能互相交流。