歡迎光臨
每天分享高質量文章

如何基於 Kubernetes 構建完整的 DevOps 流水線

前言

關於 DevOps 是一個很大的話題,它可能既涉及到公司的技術文化構建,也包括開發者技術能力的支援,這次技術乾貨分享主要是側重於技術方面,就是如何用 Kubernetes 來服務好 DevOps 的流水線。本文從 4 個方面介紹:

  1. 什麼是 Kubernetes?為什麼 Kubernetes 比較適合用來構建 DevOps 的流水線?
  2. 如何基於 Kubernetes 來構建 DevOps 流水線?
  3. 如何在 Azure 上面利用 AKS 去構建 DevOps 流水線?
  4. DevOps 中常見的一些挑戰。

1. 什麼是 Kubernetes?為什麼 Kubernetes 比較適合用來構建 DevOps 的流水線?

Kubernetes 是目前最為廣泛且流行的容器編排排程系統,它也是現在用來構建雲原生應用編排的最佳平臺。目前所有雲原生應用基本上都會基於 Kubernetes  API 去構建

Kubernetes 給開發者帶來了很多實用的特性,比如一致性、可擴充套件性、自我修複的功能。一致性是指在 Kubernetes 上構建的應用可以無縫的遷移到任何環境裡,不論公有雲、私有雲還是跨雲。可擴充套件性是指把 Kubernetes 的外掛機制運用到任何環境裡,透過 Kubernetes 這些外掛都可以實現自定義化。Kubernetes 的自我修複功能,包括健康檢查、故障的自動恢復、自動擴充套件等機制,這些對於系統執行至關重要。

Kubernetes 的架構比較簡單,分為 Master 和 Node 兩部分。

  • Master 主要負責叢集的狀態維護,也給叢集提供一個對外訪問的入口;

  • Node 負責執行容器,為容器提供一些必要的環境,比如儲存、網路等。

Kubernetes 在 Master 上必備的元件只有四個,在 Node 上必備的元件,除了 Kubelet、Kube-proxy,還有 Docker 等。而其他所有的一切都是透過擴充套件的方式部署到集群裡,比如在部署一個叢集時,DNS 是一個必需的功能,但這個功能是以一個容器的方式部署到集群裡。

由於 Kubernetes 架構非常簡單。因此它有一些特別的好處,就是可以運用到 DevOps 流水線裡面來。以持續整合為例,在版本升級測試新的特性時,在 Kubernetes 之前可能要透過 IPM 包管理這些軟體,當升級 IPM 包時,有可能產生衝突。而在 Kubernetes 中,透過把 IPM 包放到每一個容器裡,避免軟體包的衝突問題。如果把每個應用程式所依賴的東西都放到了容器裡面,應用程式在不同環境裡就可以很容易保持一致。

在 DevOps 裡監控系統很關鍵,而在 Kubernetes 中,透過一個 Pod 的方式執行容器,應用程式可以部署在 Pod 的一個容器裡,其他的容器可以用在監控裡。

在 DevOps 中經常需要頻繁地釋出、變更系統,發現問題時需要回滾,而在頻繁的釋出和回滾時,需要有一個系統去管理這些釋出的歷史生命週期,在發現問題時才可以回滾回來。對於系統來說,要求它釋出的過程中不能影響應用程式對外正常訪問。在 Kubernetes 中已經有了原生的機制,比如用 Service 和 Deployment 來完成這個功能,Service 可以提供一個對外訪問的入口,自動做好負載均衡;Deployment 負責管理好這些副本。如果需要升級,透過滾動升級的方式去部署。

2. 基於 Kubernetes 的 DevOps

DevOps 是把人員流程、產品進行結合,給使用者提供持續價格的一個過程,這個過程既涉及到人員、過程,也涉及到產品。DevOps 最終目的是給客戶提供持續交付的價值,流程包括:產品的規劃跟蹤、軟體開發、構建測試、產品部署、運維、監控和最佳化,並透過一個流水線的方式串聯起來。因此通常把 DevOps 這些流程合併起來稱為一個 DevOps 的流水線。這個流水線的核心標的,就是持續給使用者交付有價值的產品。

Kubernetes 如何服務好 DevOps 流水線?Kubernetes 的好處就是可以把不同的產品、工具串聯起來。以 CI/CD 裡最常用的 Jenkins 為例:現在有一個 Jenkins-x 專案,實現了與 Kubernetes 的整合,利用 Kubernetes 的 CI/CD 實現了自定義的兌現,有了這些資源兌現,就可以透過 Kubernetes 的 API 來定義 CI/CD 的過程。

另外如果使用 Kubernetes 構建整個流水線,在監控的時候就可以同樣選擇 Kubernetes 生態之中的專案,比如可以直接從 Prometheus 裡獲得很多指標,去構建想要的監控告警,以及後續的對整個產品的最佳化依據。基於這些工具,就可以構建一個 DevOps 的流水線。

一個比較典型的 DevOps 的流水線過程是:專案開始開發時,用 VS  Code 開發程式碼,然後把程式碼推送到 GitLab 裡儲存,透過 GitLab 的 hook 使 Jenkins 執行一些 CI 的過程,比如做一些單元測試,構建 Docker  image,再把這個 Docker  image 呼叫 helm 部署到開發環境或測試環境中。在測試環境裡透過 Jenkins 觸發一個整合測試的功能,完成後就可以把它部署到生產環境裡,透過 Kubernetes addon 的方式,把 Prometheus、Grafana 等監控元件部署到集群裡,就實現了一整套從 CI 到 CD 的監控過程。

3. 基於 AKS 的 Devops

AKS 是 Azure 提供的一個託管的 Kubernetes 服務,因為很多人在接觸 Kubernetes 時發現它最大的痛點是 Kubernetes 的安裝部署和維護太麻煩。Kubernetes 釋出特別快,在升級的過程中很容易出現各種問題,而 AKS 的出現可以解決這些問題。

需要註意的是,AKS 只是提供了一個託管的 Kubernetes 服務,也就是它只提供了一個 K8s 的叢集,而為了執行這個叢集,還需要其他東西,比如要考慮 Docker  image 要存在哪裡的問題。ACI 提供了跨地域自動複製的功能,因此 Docker  image 只要存到 ACI 裡,就可以在不同的 Image 裡使用。

另外在 DevOps 的流水線裡執行任務時,這些任務都類似 Kubernetes 的一個 Job,比如在持續整合裡做一個單元測試,這個單元測試可能執行很短時間就結束了,但如果用 AKS,或者透過其他產品的 Kubernetes 叢集來管理這套 DevOps 流程,要優先保證最大的 Job 數量時,它才能夠正常的執行。但是這會造成一定的資源浪費。

ACI 是一種無伺服器化的容器解決方案,使用者無需管理底層伺服器,只需要呼叫它的 API 把一個容器執行起來即可。另外如果執行的程式還有一些資料要儲存,如果要訪問資料庫,就需要用 cosmosDB 等服務,而它們已經跟 AKS、Kubernetes 有了很好的整合,這些服務可以很方便地在 Azure 上使用。

如何構建一套比較完善的 DevOps 流水線呢?

首先要建立專案,選擇最合適的產品來管理進度,用 Azure  DevOps 把產品後面的程式碼開發、單元測試和整合測試、持續部署等串聯起來。Azure  DevOps 提供了 Backlog 等工具來管理應用程式。

開發專案時,需要一套 Git 儲存倉庫,Azure  DevOps 也提供了這個功能。而專案開發完成之後,需要的本地測試可以使用 Draft,它的好處就是可以把進項打包,再透過 Helm 部署到開發環境裡,並且可以自動設定好應用程式的遠端除錯。也就是讓應用程式以容器的方式執行在一個 Kubernetes 的環境中,但是可以透過 VS Code 線上除錯程式。

如果應用程式在本地測試透過了,就需要推送到程式碼倉庫裡持續整合,然後需要部署到測試環境裡做相應的測試,最終再把它部署到生產環境裡。當這一切做完了以後,應用程式就已經線上上跑了,但這個時候 DevOps 流程並沒有結束,因為還需要運維和監控這個應用程式。這個時候就可以 Azure monitor 監控這個程式的狀態。

4. DevOps 的挑戰

DevOps 的挑戰,首先就是自動化的測試不足。DevOps 流水線由於測試的投入不足,新釋出的功能沒有測試到,這個時候釋出到生產環境就容易出現各種各樣的問題。比如應用程式部署之後,可用性降低了,資源使用率突然升的很高等。對於這個問題實際上可以透過一定的組織文化建設去解決。一個比較簡便的方式就是對這些過程提供適當的測試改寫率的要求。例如一個新的產品釋出時,要求測試改寫率不能降低了,但是測試改寫率是比較難以控制的,可能要從組織文化上來解決。

第二個問題就是DevOps 的工具鏈缺少連結,沒有連結就沒有辦法做到高度的自動化。比較推薦的做法是選用 Kubernetes 生態中的這些工具鏈,利用 Kubernetes  API 把應用程式更好地串聯起來,形成完整的 DevOps 的流水線。

第三個問題就是很難量化成果,以及很難協調團隊之間的合作。比如使用者抱怨網站訪問速度慢了,由於當下並不知道慢的問題在哪裡,所以要到各個產品裡去檢查。如果沒有一套完善的監控系統,就很難定位這個產品到底是該由誰去負責。針對這個問題可以使用 Kubernetes,在不改變應用程式的情況下,跟蹤整個應用程式的呼叫鏈,比如可以使用 ServiceMesh 監控這些應用程式,這樣可以減少發現問題之後沒法具體定位產品的瓶頸。

最後一個問題就是在 DevOps 之中,雖然使用了 Kubernetes 的生態鏈工具,如果沒有遵循一些 Kubernetes/DevOps 的最佳實踐,會導致在實際操作中出現預想不到的問題。比如一個最簡單的問題,在升級的過程中可以用 Kubernetes 的 Deployment 來做滾動更新。按照正常的預期,在滾動更新的過程中,原來的副本還在正常執行著,新副本也是逐步去建立著,Service 負載均衡也是正常執行的。但問題是,Service 每次升級時總會時不時的斷一下,其可能用性在每次部署時,總會降低那麼一點。產生這個問題就是因為沒有遵循 Kubernetes 最基本的最佳實踐,沒有給應用程式部署健康檢查。對於最佳實踐的問題,實際上需要整個團隊,不只是 DevOps 流水線的構建團隊,還需要應用程式的團隊共同把這些最佳實踐運用到流水線和應用程式的管理中。比如會出現 Job 的失敗率非常高的問題,這時不僅要對應用程式進行資源的限制,另外對 DevOps 流水線裡面的這些 Job 也要進行一定的資源控制,不要把資源全部耗光。

經驗之談

在 Kubernetes 中,不建議大家直接去管理一個 Pod,你之前建立了一個 Pod,而沒有使用控制器去管理它。在 Kubernetes 中,建議每一個 Pod 都有一個控制器來管理,比如你可以用 Deployment 來管理,或者使用副本控制器來管理。所有這些控制器都是用來保證 Pod 在預期的狀態。也可以使用自己的控制器去管理這些 Pod,透過開發一個 API 去管理生命週期。這樣容器最終在執行狀態時,總是有一個控制器來管理,就不會出現一個容器在一直在執行,卻不知道是誰在管理的問題。


嘉賓簡介

倪朋飛,就職於微軟 Azure,主要關註 Kubernetes 與微服務,同時也是 Kubernetes 開源社群 SIG Azure Tech Lead。作為 Kubernetes 專案維護者,同時負責維護開源書籍《Kubernetes 指南》。

贊(0)

分享創造快樂