為什么從第一天起就應該在 Kubernetes 上構建應用
如果你正在從頭開發一個新的項目,諸如一個新的 APP,服務或者網站,你主要的關注點通常不是如何在高可用的網絡中大規模的運行它。相反,你可能會專注于為你的目標客戶打造合適的產品或尋找適合市場的產品。如果你正在為一家初創公司創建一個 MVP,你需要在大規模擴展(scaling)之前完成這個最小可用產品,否則,你在為誰擴展?如果你是企業的開發人員,你希望確保的是當前做的業務滿足期望和需求。規?;\營充其量只是明天的事情。
因此,在選擇正確的技術集時,Kubernetes(通常與大型分布式系統相關)現在可能不在你的關注范圍內。畢竟,它帶來了很大一部分工作量:設置和操作集群、容器化你的應用程序、定義服務、部署、負載平衡器等等。這在早期看起來可能有點矯枉過正,你可能認為你的時間最好花在其他任務上,例如編寫實際應用程序的前幾次迭代。
當我們在 2008 年開始構建 Stack Overflow 時,我們沒得選擇。沒有 Docker(2013 年),也沒有 Kubernetes(2014 年)。云計算還處于起步階段:Azure 剛剛推出(2008 年),而 Amazon Web Services 大約成立兩年。我們構建的東西是為特定硬件設計的,并對其做了很多假設?,F在我們正在對我們的代碼庫進行現代化改造并遷移到云端,我們必須投入大量工作才能使 Kubernetes 和容器正常工作。
經歷了這個過程,我們獲得一個全新的視角。如果你今天正在構建一個新應用程序,那么仔細研究一下使其成為云原生并從一開始就使用 Kubernetes 可能是值得的。設置 Kubernetes 的工作量比你想象的要少。同時,它也比以后重構你的應用程序來支持容器化所需的工作量少。
以下有三個原因說明為什么從一開始就在 Kubernetes 上構建你的應用程序不一定是一個壞主意。
托管的 Kubernetes 完成了繁重的工作
幾年前,當我們在 Stack Overflow 建立我們的第一個內部 Kubernetes 集群時,我們花了將近一周的時間才能啟動并運行所有內容:配置虛擬機、安裝、配置、配置、配置。 一旦集群啟動,后面就是持續的維護工作。這個過程對我們最大的觸動是 Kubernetes 對我們來說太棒了——但我們希望其他人也能來使用它。
如今,Amazon 的 Elastic Kubernetes Service(EKS)、Microsoft 的 Azure Kubernetes Service(AKS)或 Google 的 Google Kubernetes Engine(GKE)等托管 Kubernetes 服務允許你在幾分鐘內設置自己的集群。例如,在 AKS 中,你只需單擊門戶中的幾個按鈕并填寫幾個表單:
這很方便,但你可能不想在工作流結束時創建集群這種快捷方式。先完成這個向導(wizard),但不要點擊最后那個藍色的“創建”按鈕!相反,將你剛剛創建的配置下載為 ARM 模板并將其納入到你的源代碼控制系統?,F在你擁有兩全其美的優勢——易用性和基礎設施即代碼(IaC)!
一旦你在此處完成設置,那么對于規模化你的應用程序,剩下的就沒有什么可做的了,除了向你的云提供商提供更多的寫檢查(write bigger checks)。任何額外的資源分配都很容易。規模化帶來的問題——容錯、負載平衡、流量整形(traffic shaping)——已經得到處理。 在任何時候,都不會出現你被成功淹沒的那一刻;你無需付出太多額外工作就可以使你的應用程序面向未來。
你可以保持云無關(cloud agnostic)
如果你的項目成功了,那么在早期階段做出的技術決策很可能在未來數月或數年仍會產生影響。例如,Stack Overflow 最初是用 C# 編寫的。13 年后,它仍然是用 C# 編寫的,但它曾經也是。偶爾有人建議我們用 Node.js 重寫它。但直到現在也沒有發生。
對云服務的依賴也是如此。你可以在基礎設施即服務(IaaS)產品(如 Amazon 的 EC2)之上構建你的新應用程序。或者,你可能開始依賴平臺即服務(PaaS)產品,例如 Microsoft 的 Azure SQL。但是,你是否愿意在現階段對其背后的云提供商做出長期承諾?如果你還不知道你的旅程會帶你去哪里,也許你更愿意保持云無關狀態一段時間。
讓我們回到基礎設施即代碼:將諸如 Terraform 之類的工具投入其中將幫助你在某種程度上保持與云無關。它提供了統一的工具包和配置語言(HCL)來跨不同的云和基礎架構提供商管理你的資源。你的應用程序不太可能真正與云無關,但是在這種情況下,你可以像切換家中的互聯網或電力供應商一樣輕松地切換云提供商。
HashiCorp 論壇中有一個關于這個主題的很好的討論:Terraform 真的與云無關嗎?正如其中一位評論者指出的那樣:
“Kubernetes 集群是對計算資源進行抽象的一個很好的例子:它在不同平臺上有許多托管和自我管理的實現,所有這些實現都提供了一個通用的 API 和一組通用的功能。”
這總結得很好!它仍然不是一個完美的抽象。例如,每個云提供商可能都有自己的自定義方式來實現公共負載均衡器和 Kubernetes 中的持久卷等內容。公平地說,如果你在 Kubernetes 上構建應用,你將在一定程度上保持云無關。
你可以輕松地啟動新環境 - 隨心所欲!
Kubernetes 通常被視為管理生產基礎設施的一種方式。但是在 Stack Overflow,我們一直在使用它來動態管理我們的測試環境。我們使用 Kubernetes 來托管我們所謂的 PR 環境。只需按一下按鈕,每個拉取請求都可以在隔離的測試環境中運行:
當我們說“隔離環境”時,我們指的是一切:應用程序本身(包含 PR 分支中更改的代碼)及其自己的 SQL Server、Redis、Elasticsearch 和額外的服務實例。所有這些都會在幾分鐘內從頭開始啟動,并在專用命名空間中的少數容器中運行,同時只為你和任何對你的 PR 感興趣的人服務。
這不是我們發明的;其他組織一直在使用這個概念。這個想法是每個代碼更改都會通過拉取請求進入像 Git 這樣的版本控制系統。其他開發人員會審查代碼,但代碼不能說明一切。你希望看到代碼的運行情況。通常,你必須在本地下載所有代碼,編譯并運行它。這可能很簡單,但是如果你正在運行一個需要從多個倉庫中提取代碼的大型應用程序,或者微服務架構,那么你可能會需要幾個小時的調試。
讓我們更理想一點說,假設你已將一項新功能的所有提交(commits)壓縮為一個,并將其作為單個 PR 提交。將這個 PR 環境作為一個鏈接發送到銷售或營銷部門那里,以便他們可以預覽實際運行的功能。如果你的銷售團隊想要演示具有特定功能或自定義構建的應用程序,那么直接給他們發送 PR 環境鏈接。你不必花時間指導技術水平較低的同事完成構建過程。
達到這一點需要大量的基礎工作。首先,在 Windows Containers 中運行經典的 .NET Framework 并不是我們真正想要追求的途徑。理論上這是可能的——從 v1.19 開始,Kubernetes 就已經提供了 Windows 支持——但 Docker/Kubernetes 生態系統實際上更以 Linux 為中心。幸運的是,我們向 .NET Core 的遷移已經在進行中,所以我們決定押注 Linux 容器。
當然,這也帶來了一系列挑戰。當處理一個已有 10 多年歷史的代碼庫時,你可能會發現關于它運行的基礎架構的假設:硬編碼文件路徑(包括我們最喜歡的:正斜杠與反斜杠)、服務 URL、配置等。但我們最終完成了這個工作,現在我們可以在自動擴展的 Kubernetes 集群上啟動任意數量的 Stack Overflow、Stack Exchange 網絡和 Teams 產品的測試實例。
回顧 Stack Overflow 的早期,擁有這種工具可能就會是另一種局面。在構建產品的早期階段,你通常希望盡可能快的構建、衡量和學習相關知識。使用容器和 Kubernetes 將允許你為此構建這樣的工具,并在你需要擴展時為你提供面向未來的支持。
那么,你應該從一開始就使用 Kubernetes 嗎?可能是!當然,這仍然取決于你的特定項目、需求和優先事項。
但是你是否一直在說“我們不需要 Kubernetes,因為我們還沒有產品市場契合度”?仔細想想,也許你會發現自己在說“我們需要 Kubernetes,因為我們還沒有適合市場的產品。”