標籤:

為什麼 Kubernetes 很酷

在我剛開始學習 Kubernetes(大約是一年半以前吧?)時,我真的不明白為什麼應該去關注它。

在我使用 Kubernetes 全職工作了三個多月後,我才逐漸明白了為什麼我應該使用它。(我距離成為一個 Kubernetes 專家還很遠!)希望這篇文章對你理解 Kubernetes 能做什麼會有幫助!

我將嘗試去解釋我對 Kubernetes 感興趣的一些原因,而不去使用 「原生雲(cloud native)」、「編排系統(orchestration)」、「容器(container)」,或者任何 Kubernetes 專用的術語 :)。我去解釋的這些觀點主要來自一位 Kubernetes 操作者/基礎設施工程師,因為,我現在的工作就是去配置 Kubernetes 和讓它工作的更好。

我不會去嘗試解決一些如 「你應該在你的生產系統中使用 Kubernetes 嗎?」這樣的問題。那是非常複雜的問題。(不僅是因為「生產系統」根據你的用途而總是有不同的要求)

Kubernetes 可以讓你無需設置一台新的伺服器即可在生產系統中運行代碼

我首次被說教使用 Kubernetes 是與我的夥伴 Kamal 的下面的談話:

大致是這樣的:

  • Kamal: 使用 Kubernetes 你可以通過一條命令就能設置一台新的伺服器。
  • Julia: 我覺得不太可能吧。
  • Kamal: 像這樣,你寫一個配置文件,然後應用它,這時候,你就在生產系統中運行了一個 HTTP 服務。
  • Julia: 但是,現在我需要去創建一個新的 AWS 實例,明確地寫一個 Puppet 清單,設置服務發現,配置負載均衡,配置我們的部署軟體,並且確保 DNS 正常工作,如果沒有什麼問題的話,至少在 4 小時後才能投入使用。
  • Kamal: 是的,使用 Kubernetes 你不需要做那麼多事情,你可以在 5 分鐘內設置一台新的 HTTP 服務,並且它將自動運行。只要你的集群中有空閑的資源它就能正常工作!
  • Julia: 這兒一定是一個「坑」。

這裡有一種陷阱,設置一個生產用 Kubernetes 集群(在我的經險中)確實並不容易。(查看 Kubernetes 艱難之旅 中去開始使用時有哪些複雜的東西)但是,我們現在並不深入討論它。

因此,Kubernetes 第一個很酷的事情是,它可能使那些想在生產系統中部署新開發的軟體的方式變得更容易。那是很酷的事,而且它真的是這樣,因此,一旦你使用一個運作中的 Kubernetes 集群,你真的可以僅使用一個配置文件就在生產系統中設置一台 HTTP 服務(在 5 分鐘內運行這個應用程序,設置一個負載均衡,給它一個 DNS 名字,等等)。看起來真的很有趣。

對於運行在生產系統中的代碼,Kubernetes 可以提供更好的可見性和可管理性

在我看來,在理解 etcd 之前,你可能不會理解 Kubernetes 的。因此,讓我們先討論 etcd!

想像一下,如果現在我這樣問你,「告訴我你運行在生產系統中的每個應用程序,它運行在哪台主機上?它是否狀態很好?是否為它分配了一個 DNS 名字?」我並不知道這些,但是,我可能需要到很多不同的地方去查詢來回答這些問題,並且,我需要花很長的時間才能搞定。我現在可以很確定地說不需要查詢,僅一個 API 就可以搞定它們。

在 Kubernetes 中,你的集群的所有狀態 – 運行中的應用程序 (「pod」)、節點、DNS 名字、 cron 任務、 等等 —— 都保存在一個單一的資料庫中(etcd)。每個 Kubernetes 組件是無狀態的,並且基本是通過下列方式工作的:

  • 從 etcd 中讀取狀態(比如,「分配給節點 1 的 pod 列表」)
  • 產生變化(比如,「在節點 1 上運行 pod A」)
  • 更新 etcd 中的狀態(比如,「設置 pod A 的狀態為 『running』」)

這意味著,如果你想去回答諸如 「在那個可用區中有多少台運行著 nginx 的 pod?」 這樣的問題時,你可以通過查詢一個統一的 API(Kubernetes API)去回答它。並且,你可以在每個其它 Kubernetes 組件上運行那個 API 去進行同樣的訪問。

這也意味著,你可以很容易地去管理每個運行在 Kubernetes 中的任何東西。比如說,如果你想要:

  • 部署實現一個複雜的定製的部署策略(部署一個東西,等待 2 分鐘,部署 5 個以上,等待 3.7 分鐘,等等)
  • 每當推送到 github 上一個分支,自動化 啟動一個新的 web 伺服器
  • 監視所有你的運行的應用程序,確保它們有一個合理的內存使用限制。

這些你只需要寫一個程序與 Kubernetes API(「controller」)通訊就可以了。

另一個關於 Kubernetes API 的令人激動的事情是,你不會局限於 Kubernetes 所提供的現有功能!如果對於你要部署/創建/監視的軟體有你自己的方案,那麼,你可以使用 Kubernetes API 去寫一些代碼去達到你的目的!它可以讓你做到你想做的任何事情。

即便每個 Kubernetes 組件都「掛了」,你的代碼將仍然保持運行

關於 Kubernetes 我(在各種博客文章中 :))承諾的一件事情是,「如果 Kubernetes API 服務和其它組件『掛了』也沒事,你的代碼將一直保持運行狀態」。我認為理論上這聽起來很酷,但是我不確定它是否真是這樣的。

到目前為止,這似乎是真的!

我已經斷開了一些正在運行的 etcd,發生了這些情況:

  1. 所有的代碼繼續保持運行狀態
  2. 不能做 新的 事情(你不能部署新的代碼或者生成變更,cron 作業將停止工作)
  3. 當它恢復時,集群將趕上這期間它錯過的內容

這樣做意味著如果 etcd 宕掉,並且你的應用程序的其中之一崩潰或者發生其它事情,在 etcd 恢復之前,它不能夠恢復。

Kubernetes 的設計對 bug 很有彈性

與任何軟體一樣,Kubernetes 也會有 bug。例如,到目前為止,我們的集群控制管理器有內存泄漏,並且,調度器經常崩潰。bug 當然不好,但是,我發現 Kubernetes 的設計可以幫助減輕它的許多核心組件中的錯誤的影響。

如果你重啟動任何組件,將會發生:

  • 從 etcd 中讀取所有的與它相關的狀態
  • 基於那些狀態(調度 pod、回收完成的 pod、調度 cron 作業、按需部署等等),它會去做那些它認為必須要做的事情

因為,所有的組件並不會在內存中保持狀態,你在任何時候都可以重啟它們,這可以幫助你減輕各種 bug 的影響。

例如,如果在你的控制管理器中有內存泄露。因為,控制管理器是無狀態的,你可以每小時定期去重啟它,或者,在感覺到可能導致任何不一致的問題發生時重啟它。又或者,在調度器中遇到了一個 bug,它有時忘記了某個 pod,從來不去調度它們。你可以每隔 10 分鐘來重啟調度器來緩減這種情況。(我們並不會這麼做,而是去修復這個 bug,但是,你可以這樣做 :))

因此,我覺得即使在它的核心組件中有 bug,我仍然可以信任 Kubernetes 的設計可以讓我確保集群狀態的一致性。並且,總在來說,隨著時間的推移軟體質量會提高。唯一你必須去操作的有狀態的東西就是 etcd。

不用過多地討論「狀態」這個東西 —— 而我認為在 Kubernetes 中很酷的一件事情是,唯一需要去做備份/恢復計劃的東西是 etcd (除非為你的 pod 使用了持久化存儲的卷)。我認為這樣可以使 Kubernetes 運維比你想的更容易一些。

在 Kubernetes 之上實現新的分散式系統是非常容易的

假設你想去實現一個分散式 cron 作業調度系統!從零開始做工作量非常大。但是,在 Kubernetes 裡面實現一個分散式 cron 作業調度系統是非常容易的!(仍然沒那麼簡單,畢竟它是一個分散式系統)

我第一次讀到 Kubernetes 的 cron 作業控制器的代碼時,我對它是如此的簡單感到由衷高興。去讀讀看,其主要的邏輯大約是 400 行的 Go 代碼。去讀它吧! => cronjob_controller.go <=

cron 作業控制器基本上做的是:

  • 每 10 秒鐘:
    • 列出所有已存在的 cron 作業
    • 檢查是否有需要現在去運行的任務
    • 如果有,創建一個新的作業對象去調度,並通過其它的 Kubernetes 控制器實際運行它
    • 清理已完成的作業
    • 重複以上工作

Kubernetes 模型是很受限制的(它有定義在 etcd 中的資源模式,控制器讀取這個資源並更新 etcd),我認為這種相關的固有的/受限制的模型,可以使它更容易地在 Kubernetes 框架中開發你自己的分散式系統。

Kamal 給我說的是 「Kubernetes 是一個寫你自己的分散式系統的很好的平台」 ,而不是「 Kubernetes 是一個你可以使用的分散式系統」,並且,我覺得它真的很有意思。他做了一個 為你推送到 GitHub 的每個分支運行一個 HTTP 服務的系統 的原型。這花了他一個周末的時間,大約 800 行 Go 代碼,我認為它真不可思議!

Kubernetes 可以使你做一些非常神奇的事情(但並不容易)

我一開始就說 「kubernetes 可以讓你做一些很神奇的事情,你可以用一個配置文件來做這麼多的基礎設施,它太神奇了」。這是真的!

為什麼說 「Kubernetes 並不容易」呢?是因為 Kubernetes 有很多部分,學習怎麼去成功地運營一個高可用的 Kubernetes 集群要做很多的工作。就像我發現它給我了許多抽象的東西,我需要去理解這些抽象的東西才能調試問題和正確地配置它們。我喜歡學習新東西,因此,它並不會使我發狂或者生氣,但是我認為了解這一點很重要 :)

對於 「我不能僅依靠抽象概念」 的一個具體的例子是,我努力學習了許多 Linux 上網路是如何工作的,才讓我對設置 Kubernetes 網路稍有信心,這比我以前學過的關於網路的知識要多很多。這種方式很有意思但是非常費時間。在以後的某個時間,我或許寫更多的關於設置 Kubernetes 網路的困難/有趣的事情。

或者,為了成功設置我的 Kubernetes CA,我寫了一篇 2000 字的博客文章,述及了我不得不學習 Kubernetes 不同方式的 CA 的各種細節。

我覺得,像 GKE (Google 的 Kubernetes 產品) 這樣的一些監管的 Kubernetes 的系統可能更簡單,因為,他們為你做了許多的決定,但是,我沒有嘗試過它們。


via: jvns.ca/blog/2017/10/05

作者:Julia Evans 譯者:qhwdw 校對:wxy

本文由 LCTT 原創編譯,Linux中國 榮譽推出


推薦閱讀:

Kubernetes 是什麼?
數人云|微軟Azure Container Service的容器化應用
如何在 Windows 上運行 Linux 容器

TAG:Kubernetes | 容器 |