Kubernetes 是在叢集生產環境中執行 Docker 容器的絕佳工具。然而,也存在著 Kubernetes 無法解決的問題。隨著生產的頻繁部署,我們需要一個完全自動化的藍/綠部署來避免此過程中的停機,這也需要處理外部 HTTP 請求並執行 SSL 卸載。這需要與 ha-proxy 等負載平衡器整合。另一個挑戰是在雲端環境中運行時 Kubernetes 叢集本身的半自動擴展,例如在夜間部分縮減叢集。
雖然 Kubernetes 沒有開箱即用的這些功能,但它確實提供了可用於完成這些任務的 API。在基於開源創建的 Cloud RTI 專案框架內,開發了用於自動化 Kubernetes 叢集藍/綠部署和擴充的工具。
本文是一段影片的文字記錄,展示如何設定 Kubernetes 以及其他開源元件,以獲得一個可用於生產的環境,該環境可以使用來自 git 提交的程式碼,而不會導致生產停機。

因此,一旦您可以從外部世界訪問您的應用程序,您就可以開始完全配置自動化,也就是說,將其帶到您可以執行 git commit 的階段,並確保此 git commit 最終投入生產。當然,在實施這些步驟時,在進行部署時,我們不希望遇到停機。因此,Kubernetes 中的任何自動化都從 API 開始。

Kubernetes 並不是一個可以「開箱即用」的工具。當然你可以這樣做,使用 kubectl 等等,但 API 仍然是這個平台最有趣和最有用的東西。使用 API 作為一組函數,您幾乎可以存取 Kubernetes 中想要做的任何事情。 kubectl 本身也使用 REST API。
它是 REST,因此您可以使用任何語言和工具來使用此 API,但自訂程式庫將使您的生活變得更加輕鬆。我的團隊編寫了兩個這樣的函式庫:一個用於 Java/OSGi,一個用於 Go。第二個並不常用,但無論如何,你都可以使用這些有用的東西。它們是一個部分獲得許可的開源專案。有許多針對不同語言的庫,因此您可以選擇最合適的庫。

因此,在開始自動化部署之前,您需要確保流程不會受到任何停機的影響。例如,我們的團隊在人們使用應用程式最多的中午進行生產部署,因此避免此過程中的延遲非常重要。為了避免停機,使用兩種方法:藍/綠部署或滾動更新。在後一種情況下,如果您有 2 個應用程式副本正在運行,則它們會按順序一個接一個地更新。這種方法效果很好,但如果在部署過程中同時運行不同版本的應用程序,則不太合適。在這種情況下,您可以在後端運行舊版本時更新使用者介面,應用程式將停止運作。因此,從程式設計的角度來看,在這樣的條件下工作是相當困難的。
這就是我們更喜歡使用藍綠部署來自動化部署應用程式的原因之一。使用此方法,您必須確保在給定時間內只有一個版本的應用程式處於活動狀態。
藍/綠部署機制如下圖所示。我們透過 ha-proxy 接收應用程式的流量,它將流量路由到同一版本的應用程式的正在運行的副本。
當執行新的部署時,我們使用配備了新元件的部署器並部署新版本。部署應用程式的新版本意味著會啟動一組新的副本,然後在單獨的新 pod 中啟動新版本的副本。然而,ha-proxy 對它們一無所知,並且尚未向它們發送任何工作負載。
因此,第一步是對新版本執行健康檢查,以確保副本已準備好承擔負載。

部署的所有元件都必須支援某種形式的健康檢查。這可以是一個非常簡單的 HTTP 呼叫檢查,您可以在其中獲得具有 200 狀態的程式碼,或者更深入的檢查,您可以在其中檢查副本與資料庫和其他服務的連接、動態環境連接的穩定性、一切是否啟動並正常工作。這個過程可能相當複雜。

一旦系統確定所有更新的副本都正常工作,Deployer 將更新配置並推送正確的 confd,這將重新配置 ha-proxy。

只有在此之後,流量才會被定向到具有新版本副本的 pod,而舊 pod 將會消失。

這種機制並不是 Kubernetes 所特有的。藍綠部署的概念已經存在很長時間了,並且它一直使用負載平衡器。首先,您將所有流量引導至舊版本的應用程序,並在更新後將其完全轉移到新版本。這項原則並不是 Kubernetes 獨有的。
現在我將向大家介紹一個新的部署元件-Deployer,它可以執行健康檢查、重新設定代理程式等。它是一個與外界無關、存在於Kubernetes內部的概念。我將向您展示如何使用開源工具建立自己的部署者概念。
因此,Deployer 做的第一件事就是使用 Kubernetes API 建立複製控制器 RC。此 API 會建立用於進一步部署的 pod 和服務,即為我們的應用程式建立一個全新的叢集。一旦 RC 確定副本已啟動,它將執行健康檢查以確保它們正常運作。為此,Deployer 使用 GET /health 指令。它運行適當的檢查組件並檢查確保叢集運行的所有元素。

一旦所有 pod 都報告了其健康狀況,Deployer 就會創建一個新的配置元素——分散式 etcd 存儲,它由 Kubernetes 內部使用,包括用於存儲負載平衡器配置。我們將資料寫入 etcd,一個名為 confd 的小工具會監控 etcd 是否有新資料。
如果它偵測到原始配置的任何更改,它會產生一個新的設定檔並將其傳遞給 ha-proxy。在這種情況下,ha-proxy 重新啟動而不會丟失任何連接,並將負載定向到提供新版本應用程式的新服務。

如您所見,儘管組件豐富,但這裡並沒有什麼複雜的。您只需要多關注 API 和 etcd。我想向您介紹我們自己使用的開源部署器—Amdatu Kubernetes Deployer。

它是用於編排 Kubernetes 部署的工具,具有以下特點:
- 藍/綠部署;
- 設定外部負載平衡器;
- 管理部署描述符;
- 管理實際部署;
- 部署期間的健康檢查;
- 將環境變數注入 pod。
此部署器建立在 Kubernetes API 之上,並提供用於管理描述符和部署的 REST API,以及用於在部署過程中串流日誌的 Websocket API。
它將負載平衡器配置資料放入 etcd 中,因此您可以避免使用開箱即用的 ha-proxy 支持,並輕鬆使用您自己的負載平衡器設定檔。 Amdatu Deployer 與 Kubernetes 本身一樣,是用 Go 編寫的,並且獲得了 Apache 許可。
在我開始使用此版本的部署器之前,我使用了以下部署描述符,它指定了我需要的參數。

該程式碼的一個重要參數是包含“useHealthCheck”標誌。我們需要指定在部署過程中執行健康檢查。當您的部署使用不需要驗證的第三方容器時,此設定可能會被停用。該描述符還指定了 ha-proxy 所需的副本數量和前端的 URL。最後是podspec標誌,它呼叫Kubernetes取得連接埠配置、鏡像等信息,這是一個相當簡單的JSON格式的描述符。
開源 Amdatu 專案的另一個工具是 Deploymentctl。它具有用於配置部署的 UI,儲存部署歷史記錄,並包含用於第三方用戶和開發人員回呼的 webhook。由於 Amdatu Deployer 本身就是一個 REST API,您可能不會使用 UI,但此介面可讓您更輕鬆地進行部署,而無需涉及任何 API。 Deploymentctl 使用 Angular 2 在 OSGi/Vertx 中編寫。
我現在將使用預先錄製的錄音在螢幕上示範上述內容,這樣您就不必等待。我們將部署一個簡單的 Go 應用程式。如果您以前沒有使用過 Go,請不要擔心,這是一個非常簡單的應用程序,所以您應該能夠掌握它。

這裡我們創建一個只回應/health的HTTP伺服器,所以這個應用程式只檢查健康檢查,不做其他任何事情。如果檢查通過,則使用下面顯示的 JSON 結構。它包含部署人員將部署的應用程式的版本、您在檔案頂部看到的訊息以及布林資料類型 - 我們的應用程式是否正常運作。
我在最後一行做了一點手腳,因為我在文件頂部放了一個固定的布林值,這將幫助我稍後部署即使是「不健康」的應用程式。我們稍後會解決這個問題。
那麼,讓我們開始吧。首先,我們使用 ~ kubectl get pods 命令檢查是否有任何正在運行的 pod,並且根據缺少前端 URL 回應,我們驗證目前沒有正在進行的部署。

接下來,您將在螢幕上看到我提到的 Deploymentctl 介面,您可以在其中設定部署參數:命名空間、應用程式名稱、部署版本、副本數、前端 URL、容器名稱、映像、資源限制、健康檢查的連接埠號碼等。資源限制非常重要,因為它們允許您使用盡可能多的硬體。您也可以在此處查看部署日誌。

如果現在重複指令~kubectl get pods,你會看到系統「凍結」20秒,在此期間ha-proxy被重新配置。此後,pod 啟動,並且可以在部署日誌中看到我們的副本。

我從影片中剪掉了 20 秒的等待時間,現在您可以在螢幕上看到應用程式的第一個版本已經部署。所有這些都僅使用 UI 完成。

現在讓我們試試第二個版本。為此,我將應用程式的消息從“Hello, Kubernetes!”更改為到“Hello, Deployer!”,系統會建立這個映像並將其放置在Docker註冊表中,之後我們只需再次單擊Deploymentctl視窗中的“Deploy”按鈕即可。這將以與部署應用程式第一個版本時相同的方式自動啟動部署日誌。

~kubectl get pods 命令顯示目前有 2 個版本的應用程式正在運行,但是前端顯示我們仍在運行版本 1。

負載平衡器等待健康檢查完成後再將流量重新導向到新版本。 20 秒後,我們切換到 curl 並看到我們現在已經部署了應用程式的版本 2,並且第一個版本已被刪除。

這是一個健康的應用程式部署。讓我們看看如果我將應用程式新版本中的 Healthy 參數值從 true 更改為 false 會發生什麼情況,即嘗試部署未通過健康檢查的不健康應用程式。如果應用程式在開發過程中出現一些配置錯誤並以這種形式發送到生產環境,就會發生這種情況。
如您所見,部署經歷了上面顯示的所有步驟,並且~kubectl get pods 顯示兩個 pod 都在運行。但與先前的部署不同,日誌顯示逾時狀態。即由於健康檢查失敗,導致無法部署新版本的應用程式。結果,您會看到系統已恢復使用舊版本的應用程序,而新版本已被刪除。

這樣做的好處是,即使有大量並發請求進入您的應用程序,他們甚至不會注意到部署過程運行時的停機時間。如果您使用 Gatling 框架測試此應用程序,該框架會向其發送盡可能多的請求,那麼這些請求都不會被丟棄。這意味著我們的用戶甚至不會注意到即時版本更新。如果失敗,將繼續在舊版本上工作;如果成功,使用者就會轉向新版本。
只有一種情況會導致失敗——如果健康檢查通過,但應用程式一暴露於工作負載就會崩潰,即崩潰只會在部署完成後才會發生。在這種情況下,您必須手動回滾到舊版本。因此,我們研究如何使用專為 Kubernetes 設計的開源工具。如果您將這些工具整合到您的建置/部署管道中,您的部署流程將會變得更加容易。在這種情況下,您可以使用使用者介面來啟動部署,或完全自動化此流程,例如透過使用提交至 master。

我們的建置伺服器將建立一個 Docker 映像並將其推送到 Docker Hub 或您使用的任何其他註冊表。 Docker hub 支援 webhook,所以我們可以像上圖一樣透過 Deployer 觸發遠端部署。這樣,您就可以完全自動化地將應用程式部署到潛在生產中。
讓我們進入下一個主題——擴展 Kubernetes 叢集。請注意,kubectl 指令是一個縮放指令。有了這個幫助,我們可以輕鬆增加現有集群中的副本數量。然而,在實踐中,我們通常希望增加節點的數量,而不是 pod 的數量。

同時,在工作時間您可能需要增加亞馬遜服務的成本,而在晚上則需要減少應用程式的執行實例數量。這並不意味著僅擴展 pod 的數量就足夠了,因為即使其中一個節點處於空閒狀態,您仍然需要向亞馬遜支付費用。這意味著除了擴展 pod 之外,您還需要擴展所使用的機器數量。
這可能很棘手,因為無論我們使用亞馬遜還是其他雲端服務,Kubernetes 都不知道正在使用的機器數量。它缺少在節點層級擴展系統的工具。

所以我們必須同時照顧節點和 pod。我們可以使用 AWS API 和 Scaling 群組機器輕鬆擴充新節點的啟動,以配置 Kubernetes 工作節點的數量。您也可以使用 cloud-init 或類似的腳本在 Kubernetes 叢集中註冊節點。
新的機器在Scaling群組中啟動,將自己初始化為節點,在主註冊表中註冊自己並開始工作。此後,您可以增加結果節點上使用的副本數量。縮小規模需要付出更多努力,因為您需要確保這樣的舉措不會導致在關閉「不必要的」機器時破壞已經運行的應用程式。為了防止這種情況,您需要將節點設定為「不可調度」狀態。這意味著預設調度程序在調度 DaemonSet pod 時將忽略這些節點。調度程序不會從這些伺服器中刪除任何內容,但也不會在那裡啟動任何新容器。下一步是驅逐排水節點,即將正在運行的 pod 從該節點移至另一台機器或其他具有足夠容量的節點。一旦您確認這些節點上沒有更多容器,您就可以將它們從 Kubernetes 中刪除。此後,對於 Kubernetes 來說,它們將不復存在。接下來,您需要使用 AWS API 關閉不必要的節點或機器。
您可以使用 Amdatu Scalerd,另一個類似 AWS API 的開源擴充工具。它提供了一個 CLI 來新增或刪除叢集中的節點。它的有趣功能是能夠使用以下 json 檔案自訂調度程序。

所示程式碼在夜間將叢集容量減少了一半。它配置現有副本的數量和 Amazon 叢集的所需容量。使用此排程器將在夜間自動減少節點數量並在早晨增加節點數量,從而節省您在亞馬遜等雲端服務上使用節點的成本。此功能未內建於 Kubernetes 中,但使用 Scaledr 可讓您根據需要擴充平台。
我想指出的是,很多人告訴我,「這一切都很好,但是我的資料庫通常處於靜態,該怎麼辦?」如何在像 Kubernetes 這樣的動態環境中運行這樣的事情?在我看來,你不應該這樣做,你不應該嘗試在 Kubernetes 中運行資料倉儲。從技術上來說這是可能的,並且互聯網上也有關於這個主題的指南,但是它會嚴重地使你的生活複雜化。
是的,Kubernetes 具有持久存儲的概念,您可以嘗試運行像 Mongo 或 MySQL 這樣的資料存儲,但這是一項相當耗費人力的任務。這是因為資料倉儲不完全支援與動態環境的互動。大多數資料庫都需要大量配置,包括手動叢集配置,並且不喜歡自動擴展和其他類似的東西。
因此,不要嘗試在 Kubernetes 中運行資料倉儲,以免讓生活變得更加艱難。使用熟悉的服務以傳統方式組織他們的工作,並簡單地為 Kubernetes 提供使用它們的能力。

最後,我想向大家介紹我的團隊正在開發的基於 Kubernetes 的 Cloud RTI 平台。它提供集中式日誌記錄、應用程式和叢集監控以及許多其他有用的功能。它使用Grafana等各種開源工具來顯示監控。


有人問為什麼在 Kubernetes 中使用 ha-proxy 負載平衡器。好問題,因為目前有 2 個等級的負載平衡。 Kubernetes 服務仍位於虛擬 IP 位址上。您不能將它們用於外部主機端口,因為如果 Amazon 的雲端主機超載,位址就會變更。這就是我們將 ha-proxy 放在服務前面的原因——為流量創建一個更靜態的結構,以便與 Kubernetes 無縫互動。
另一個好問題是,在進行藍/綠部署時如何處理資料庫模式的變更?關鍵是,無論您是否使用 Kubernetes,更改資料庫模式都是一項艱鉅的任務。您需要確保新舊模式相容,之後您可以升級資料庫,然後升級應用程式本身。您可以熱交換資料庫,然後升級應用程式。我知道有人用新的模式加載了一個全新的資料庫集群,如果你有一個像 Mongo 這樣的無模式資料庫,這是一個選擇,但無論如何這都不是一項簡單的任務。如果沒有其他問題,謝謝大家的關注!

一些廣告🙂
感謝您與我們在一起。 你喜歡我們的文章嗎? 想看更多有趣的內容? 通過下訂單或推薦給朋友來支持我們, , 我們為您發明的入門級服務器的獨特模擬: (適用於 RAID1 和 RAID10,最多 24 個內核和最多 40GB DDR4)。
Dell R730xd 在阿姆斯特丹的 Equinix Tier IV 數據中心便宜 2 倍? 只有這裡 在荷蘭! Dell R420 - 2x E5-2430 2.2Ghz 6C 128GB DDR3 2x960GB SSD 1Gbps 100TB - 99 美元起! 閱讀
來源: www.habr.com
