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

如何基於 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 構建完整的 DevOps 流水線


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

  • Master 主要負責集群的狀態維護,也給集群提供一個對外訪問的入口;
  • Node 負責運行容器,為容器提供一些必要的環境,比如存儲、網絡等。

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

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

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


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

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

2. 基於 Kubernetes 的 DevOps

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

如何基於 Kubernetes 構建完整的 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 的監控過程。

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


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 數量時,它才能夠正常的運行。但是這會造成一定的資源浪費。

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


ACI 是一種無服務器化的容器解決方案,用戶無需管理底層服務器,只需要調用它的 API 把一個容器運行起來即可。另外如果運行的程序還有一些數據要存儲,如果要訪問數據庫,就需要用 cosmosDB 等服務,而它們已經跟 AKS、Kubernetes 有了很好的集成,這些服務可以很方便地在 Azure 上使用。

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

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

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

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

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


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 構建完整的 DevOps 流水線


經驗之談

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


分享到:


相關文章: