1. 程式人生 > >谷歌大神為你解釋Kubernetes, 微服務和容器化

谷歌大神為你解釋Kubernetes, 微服務和容器化

來自谷歌雲平臺(Google Cloud Platform)的開發者佈道師 Ray Tsang 和 Bret McGowen 在 SpringOne2GX 大會上分享了谷歌的 Kubernetes 的實踐,來看看都有哪些內容吧!

?wx_fmt=png&wxfrom=5&wx_lazy=1

微服務解決的痛點

?wx_fmt=png&wxfrom=5&wx_lazy=1?wx_fmt=png&wxfrom=5&wx_lazy=1


1. 包的大小和部署的難度成正比
傳統 Java 開發將應用打成一個巨無霸的 Ear 或者 War 檔案(Fat Jar),包的大小越大,部署的複雜度就越高。

在傳統架構中,通常開發人員需要給測試人員一個部署文件,而這個文件通常是一個很長的 Wiki 或者 Doc。開發將部署的每一步都描述在這個文件裡,如果漏掉了其中任何一步,測試就可能部署不成功,所以包越大,你花在部署的時間就越長,這種做法對兩者都是一種傷害。

微服務架構,每個 jar 包獨立部署,且非常小,導致部署簡單,依賴清晰。通過宣告的方式將環境用程式碼來描述(Infra as Code),自動化搭建環境,而不是依賴文件。

2. 包越大,啟動速度越慢
這個很好理解,包越大,需要載入的內容就越多,有的專案啟動時間甚至需要半個小時。

使用微服務架構,服務啟動速度快,並且能夠實現0宕機滾動升級。

?wx_fmt=png

微服務的搭建

?wx_fmt=png?wx_fmt=png

對於 Java 開發者,搭建微服務時建議使用 Spring Initializr (start.spring.io) 自動生成標準 Spring Boot 的框架程式碼,框架程式碼會宣告所需要的依賴,例如 Mysql,Redis,Eureka,Zuul,Cloud messaging 等等,這樣能夠讓開發者快速搭建一個微服務的專案,並且以此專案為規範,複製到其他專案,使得每個微服務的程式碼組織更規範,可讀性更好。

如果不是 Spring 的開發者,也可以使用 Jboss Wildfly等其他微服務框架。

?wx_fmt=png

開始容器化

?wx_fmt=png

理論上來講部署一個微服務,只需要執行 Java -jar 即可執行。但實際並沒有人這麼做,為什麼?每個服務需要配置 JDBC 連線池,配置埠,做服務發現,服務隔離,如果人為的去維護每個微服務,那也將會是一場災難。

容器和容器平臺的誕生天生就能夠解決這些問題。

1. 用程式碼描述環境 - DockerFile

?wx_fmt=png

DockerFile 解決的是用程式碼描述環境的問題。對這個 DockerFile 執行 Docker build 命令,可以構建出一個不變的映象,這個映象可以跑在任意的 Docker 環境裡。這樣就解決了基礎設施即程式碼(Infra as Code)的問題。

2. 多容器應用的管理工具 - Compose

應用通常包含多個容器,Docker Compose 解決了應用裡的多容器定義,執行的問題。 Compose 使用 YML 檔案定義每個服務的依賴服務,自身暴露的埠等等。你只需要為你的微服務寫好 YML 檔案,然後執行 "docker-compose up", 那麼你需要的所有容器都會啟動起來,並且按照配置的方式去執行。


?wx_fmt=png

谷歌雲平臺的架構

?wx_fmt=png?wx_fmt=png


在谷歌,所有的服務都跑在容器裡,每週谷歌啟動20億次容器。

?wx_fmt=png

從谷歌開發者的視角來看容器平臺,當開發者需要部署一個應用時,他只需要宣告這個應用執行的叢集,叢集中機器的配置,以及服務的拷貝數量。

?wx_fmt=png

谷歌雲平臺 Kubernetes 架構圖:

1. 容器映象儲存在私有 Docker 映象註冊中心(目前使用的是 Artifactory)。
2. 寫好 Config 檔案,讓 Kubernetes Master 執行部署任務。
3. Scheduler 定時從 Master 取出任務,並且找到終端(Kubelet,通常是虛擬機器)實際執行這個任務。
4. 當找到Kubelet 之後,從 Artifactory 拉取映象,啟動容器。

?wx_fmt=png

Kubernetes 的特性

?wx_fmt=png

如何實現類似谷歌的微服務架構?光靠 Compose 肯定不夠,因為 Compose 僅僅解決了應用的描述,執行的問題,但應用的編排,服務註冊,服務發現,服務監控,故障恢復,DNS,負載均衡等等功能如何實現? Docker 的作用是計算資源和環境的描述和排程,Kubernetes 的作用是以應用為中心的生命週期的管理。

 Pods

Pods 的定義:Pods 包含一組容器,容器之間共享 namespace,共享儲存,共享 IP 地址。

為什麼會有 Pods?Pods 設計的目標是為了支援需要緊耦合容器的應用,讓一個 Pods 裡的多個容器變成對外服務的原子結構。例如 LAMP應用,這個應用依賴於多個不同的容器才能執行。

Pods 主要的目的,是為了解決一些輔助程式,例如內容管理系統,本地快取管理,日誌,備份,代理和更新等等,目的是讓這幾個整合的容器有統一的生命週期,降低獨立維護容器的複雜度,所以 Pods 的初衷並不是運行同一個容器的多個副本。

Replication Controller

Replication Controller 會將叢集保持在一個期望的狀態。


傳統的部署,需要一步一步部署好所有需要的東西,在 Kubernetes 裡,你只需要描述你要部署生什麼樣,例如我要將某個服務部署6個例項。

?wx_fmt=png

此時的環境裡有6個例項,突然,Node2節點發生了故障,導致叢集裡有2個節點掛掉。在傳統專案裡,我需要監控這個事件,並且手動去重啟節點。

?wx_fmt=png


Replication Controller 會自動監控到這個事故,並且在可以的節點裡尋找可用資源,部署這兩個例項,直到最終叢集裡有6個例項。

?wx_fmt=png

Service

Service 是一組 Pods 的邏輯集合。在 Service 內部,Kubernetes 會建立負載均衡來將流量代理到可用的 Pods 上。Service 有一個固定的虛擬 IP( VIP)對外提供服務。

Service 的應用場景在於:假設後端有3個容器例項在執行,並且這3個例項是隨時有可能壞掉的(Design for failure),前端的例項無需關注這三個例項各自的狀態,而只需要宣告它依賴的是後端某一個 Service 即可,讓 Replication Controller 自動保證這個後端 Service 的可用性。

Labels

和名字和 UID 不同,Labels 不提供唯一性,通常,我們期望多個物件使用相同的 Label(s)。通過 Label 的設定和消費,可以輕鬆的過濾出需要找到的物件,例如:

?wx_fmt=png


這個命令能夠從叢集中所有的 Pods 裡找出環境屬於"Production",tier 等於"frontend"的 Pods。在前端服務的依賴聲明裡,和執行 Deploy 命令時,都可以用到 Labels 這個特性,實現服務或 Pods 的過濾。

?wx_fmt=png

金絲雀(Canary)部署

?wx_fmt=png?wx_fmt=png

金絲雀最早是礦工進煤礦時,會帶一隻金絲雀進去,如果金絲雀發生異常反應,則說明存在瓦斯洩露,如果金絲雀反應正常,則說明安全。

上圖說明的是通過 Replication Controller,Labels 和 Service 實現金絲雀部署,通過 Label(Role=FE)找到 FE 服務的兩個版本,V1和 V2,用 Service 來遮蔽版本的差異,並且將流量分發給 V1 和 V2 的 Pods。

谷歌內部的金絲雀釋出的策略是將新的版本部署叢集1%的機器,並且監控使用者行為,如果使用者對於新功能有更多的點選次數,則說明改功能可以部署更多例項,達到5-10%的比例,再根據監控結果決定是否部署到100%的機器。

?wx_fmt=png

服務發現

?wx_fmt=png

Kubernetes 裡服務發現有多種方式:

1. 通過環境變數注入發現服務。
當 Pods 在叢集的 Node 中執行時,Kubernetes 會為它增加一些列的環境變數。以 Redis 的服務發現為例:

?wx_fmt=png

上圖的"redis-master"暴露了6379埠,以及在叢集裡的 IP 地址,如果你的容器聲明瞭對"redis-master"服務的依賴,在你的 Pods 裡就能夠訪問到這些環境變數。

2. 通過 Kubernetes DNS 伺服器。
Kubernetes DNS 伺服器會訂閱 Kubernetes API建立 Service 的事件,並且為每個 Service 記錄一個 DNS 的記錄。這樣做的好處是:只要 DNS 服務在叢集裡有訪問許可權,那麼所有的 Pods 都能訪問新註冊的 Service。

舉例:如果你有一個 Service 在 Kubernetes Namespace "my-ns"下 ,名字叫做叫 "my-service",那麼一條叫做"my-service.my-ns"的記錄就會被建立。所有在"my-ns" Namespace 裡的 Pods 都能通過 DNS 查詢到"my-service"。

?wx_fmt=png

總結

?wx_fmt=png?wx_fmt=png

Pod: 一組緊耦合的容器。

Replication Controller:持續的將當前的狀態變成期望的狀態。

Service:一組 Pod 的邏輯組合。

Labels:將 Pods 打上標籤,進行多緯度的分組。

通過 Kubernetes 的這些特性,您可以輕鬆實現服務的服務註冊,服務發現,高可用性,故障自動回滾,金絲雀釋出等需求,實現微服務的落地。

本文轉載自公眾號【JFrog傑蛙DevOps】

推薦閱讀

點選 “閱讀原文” 搜搜本號內容