如何在生產環境執行容器

貓飯先生發表於2017-10-11
本文講的是如何在生產環境執行容器【編者的話】Vivek Juneja是一名工作首爾的雲服務工程師。他從2008年就開始接觸雲服務,是最早的AWS和Eucalyptus的使用者。本文中總結了在生產環境中使用容器的幾個方面,特別是對虛擬機器與容器的混合部署的觀點很值得推薦給大家。

如果只是把容器限制在開發測試環境中,那麼您並沒有享受到面向容器研發和釋出工作的全部紅利。對在生產環境中使用容器的牴觸情緒來源於對安全與隔離性的擔憂,同時也包括對管理容器的運維經驗的缺乏。

在不同程度上使用容器的組織中,遷移這些容器到生產環境的決定是需要非常大的決心的。而為全新的系統和應用採用容器技術就會輕鬆許多,這些系統是完美的容器原生系統。

容器原生是什麼概念?一個容器原生的應用被設計和構建在容器的生命週期內,並將容器視為第一等公民。對於那些為了適應容器而被改造的應用,遷移到生產環境的決定通常是很難下的。這裡是指那些遺留應用,這類應用如果要選擇容器化的開發與釋出模式,更是需要大範圍的改造。

理解在生產環境執行容器對現有工作流程的影響是非常有必要的。下面列舉了一些可能受容器影響的工作流程:
  • 將改進或新功能從開發環境釋出到生產環境
  • 允許終端使用者訪問生產環境中的改進或新功能
  • 在生產環境中定位問題
  • 監控生產環境中的應用
  • 升級生產環境中的應用
  • 資料備份
  • 容災和業務延續
  • 生產環境容量規劃
  • 主機設定,特別是網路和安全設定


容量規劃

在容器選型的組織中不使用容器運營生產環境是比較常見的。在這樣的組織中,虛擬機器作為釋出單元,承擔了應用隔離和管理的職能。極有可能的,這些獨立的應用分佈在一組虛擬機器中,這些虛擬機器為了高可用有多個副本分佈在許多主機中。如果同一個生產環境被不同應用所共享,那麼虛擬機器就是做系統隔離的一把利器。

運維團隊負責虛擬的整個生命週期,應用程式碼通常使用自動或人工工作流程拷貝到虛擬機器中。虛擬機器很少因為新的釋出而被銷燬,相反虛擬機器只是用新版本的程式碼來進行釋出。這些虛擬機器偶爾的發生變化,變化是通過使用新版本的經典映象來重建虛擬機器。

另一方面,一些組織實踐在釋出更新時作廢老虛擬機器,再重新生成新的虛擬機器。Netflix的Aminator(https://github.com/Netflix/aminator) 和圍繞它周圍的實踐已經成為如何用虛擬機器管理生產環境並實踐不變性的一股潮流。

容器的支持者們持續的宣傳使用裸機來執行容器化應用。這可以避免從主機與作業系統連線層產生的效能和上下文切換的代價。這個建議在我們執行不與其他非信任系統共享資源的單體應用時會顯得更加有必要。

一般組織在早期做容器選型時會使用混合策略來處理這種情況:組合執行在虛擬機器和裸機中的容器化應用。這種組合可以通過分析管理和效能指標後進行調優。當運維容器的成熟度達到一定階段後,這些組織會採用在裸機上執行他們的應用。

在共享的生產設施中執行多個應用時,在裸機中執行容器的決定需要依靠先前的經驗。一個較為安全的選項是將不同的租戶用虛擬機器包裝起來,讓容器在這些虛擬機器的內部作為你的服務的執行時環境。每個部署容器的虛擬機器屬於相同的租戶,這樣就在不同的租戶之間提供了隔離性。

Chart_Transition-of-Infrastructure-from-Low-to-High-Maturity-1024x683.png


圖一:在成熟度低的時候,租戶之間不會共享生產環境。可以使用虛擬機器或者物理機進行隔離。在成熟度高的時候,每個租戶的應用元件被擴散到共享的設施中。作為容器來說,高成熟度代表著每個租戶的應用元件被擴散到共享的虛擬機器或者裸機的設施中。

在生產環境中釋出應用

容器的臨時天性使得升級應用時應該使用全新的容器釋出程式變更,而不是去更新已經存在的例項。當一個特定的修改被標記為需要釋出到生產環境時,一組使用新版本的映象被建立出來,新的容器被新的標籤標記。新標籤最後是使用持續整合工具建立的。生成出來的映象和標籤被儲存到容器映象註冊中心內,那裡可被生產環境訪問。

相比於容器註冊中心在所有環境中被共享-包括開發,測試和生產環境-在某些情況下,為生產環境使用單獨的容器映象註冊中心是合理的。單獨的生產環境容器映象註冊中心不會與其他環境共享。在這種情況下,需要一個較好的工作流程將開發和測試環境中的候選的容器映象遷移到生產環境中。一箇中間系統將會從開發/測試註冊中心拉取候選的映象,然後重新標記而後推送到生產環境的註冊中心內。使用這個方法,將會在其他環境和生產環境之間的容器映象產生清晰的隔離。

容器的臨時特性極大的限制了原有的運維經驗,那就是使用靜態埠繫結和IP地址來發布主機中的應用。這種靜態手段對於配置網路防火牆和交換機是有幫助的。在生產環境中釋出更新的最佳實踐是去選用滾動更新。這就要求在生產環境中部署額外的設施去修改已經存在的負載均衡器和代理的配置,當一組新的容器例項啟動現有版本。

為了在釋出容器的時候保持一定的可恢復性,非常明智的做法是使用編排工具來管理容器執行環境。如果不使用任何編排工具,那麼執行時配置策略,比如”–restart”,就是非常必要的。推薦的重啟策略是在”on-failure”和”unless-stopped”之間切換,或者根據你的環境從中選擇一個。

在生產環境中為容器設定主機環境

在你為容器準備生產設施時一個重要的考慮關鍵點是瞭解容器映象的“密封”特性。容器映象需要一套標準化的設施用以保障在開發,測試和生產環境的配置是相同的。這套標準化設施可以嚴格保障在生產環境中得到符合預期的行為。以下是需要考慮的要點:

  • 核心的選擇
  • 容器執行時版本的選擇
  • 網路訪問與防火牆配置
  • 安全加固方案的選擇
  • 系統訪問許可權


雖然背離以上要素的一部分是很有誘惑性的,但是任何改變都會帶來意想不到的結果,所以需要認真衡量這些改變。解決這個問題最簡單的方法是從開發,測試到生產的所有環境都保持相同。一開始這點是很難做到的,但是考慮你選擇容器的終極目標是什麼後,你會說服自己的。所有的環境使用相同的Linux核心;它們使用相同的主機配置,檔案系統拓撲,網路配置和使用者角色。標準化所有的元素幫助你去保證容器映象在被構建和測試後一直到生產環境均保持相同。

容器執行時的某些方面的行為是會有些不同的,比如訪問其他依賴應有的URL或者日誌級別。這些執行時配置可以通過一些手段傳遞給容器。其中一種是通過環境變數將執行時配置注入到容器例項中。這些環境變數指向服務註冊中心,那些註冊中心包含了正確的依賴服務。諸如ZooKeeperConsul這樣的工具對於實現這種操作是有幫助的。

如果主機已經使用了配置管理工具,比如ChefPuppetAnsible,那麼最好是在所有環境中儘可能使用單一的配置。對於可擴充套件的設施來說,考慮到可用性和效能的要求,在所有環境中不同的配置應該只是例項的數量。

主機需要偶爾的升級到最新的核心分支或容器版本等。這些升級不能被封裝在容器映象中。這些對主機配置的修改應該遵循滾動升級的原則,那就是進行階段性升級,而不是做一次全量升級。

最後,像主機一樣,支援設施的配置也應該保持相似,比如日誌聚合系統,監控,度量,服務路由和發現系統。這其實是要求與容器映象有關的系統,不僅僅是主機,而且包括在環境中所有參與的系統,都需要有一定層次的一致性。

在生產環境中的容器服務發現

對於容器化應用來說標準化服務發現機制是一個重要的考量點。執行容器化應用的方式與執行虛擬機器內應用的方式很少是一致的:那是因為在一臺主機內會執行超過一個的容器。在這個極其罕見的情況下,如果你使用橋接網路模式,你可以為你的每個容器使用靜態埠。這意味著你對主機中的容器預先選擇了需要暴露的埠,並使用這些埠去配置負載均衡器和代理。

重配負載均衡和代理可能是不需要的,如果對在主機中增加容器僅僅是有限的需求。但是在大多數情況下,容器的增減是基於對穩定部署的負載或者擴充套件實踐的思考,並且那是服務發現系統發揮作用的地方。

生產環境支援:日誌蒐集和監控

在生產環境中容器對於支援服務的需要與非容器環境是一樣的。這包括瞭如何從容器例項中捕獲日誌並將它們傳輸到集中化日誌管理系統中。內建的日誌後端已經在Docker守護程式中得到了支援,並且現在有一些個性化的解決方案也可以使用。

目前有許多管理Docker容器產生日誌的手段。Docker的預設設定是將日誌非壓縮的寫入到磁碟中,並且可以選擇刪除策略去限制日誌佔用的磁碟空間。在生產環境中,有許多日誌驅動與Docker引擎協同工作並提供給產生日誌的應用許多靈活方案去透明化管理日誌。如果你已經使用了一種集中化日誌管理解決方案,那麼你可以選擇一種Dokcer日誌驅動來向它填充日誌資料。日誌驅動支援許多種協議,比如Syslog,它可以被用在許多內嵌系統中或者雲化的SaaS方案中。

容器的臨時狀態在容器的日誌和監控領域是需要被強調的一個關鍵特性。在生產環境做釋出時,新容器會替換掉老的。這對於傳統概念中假設有狀態和長時間執行的計算單元是一種破壞。滾動容器特性對於傳統日誌和監控理念帶來了新的問題。與讓計算例項執行長達數天甚至數月不同,容器可能在以小時為視窗的時間內就發生變化。

如果你實踐持續化整合,這個視窗可能更小。一個以主機維度構建的日誌和監控解決方案不能適應容器的靈活性。由於容器短暫的生命週期,幾乎不能有一個預先說明的方式去監控它們。並且最後是將它們作為一個群組去監控,而不是監控每個容器。

將容器歸為一組的一種方法是使用合理的後設資料,比如標籤。一個標籤指的是“映象標籤”,它可以在生產環境中被執行。不要使用令人困惑的“最新”標籤。

舉例,假如你釋出了一個叫做“product-api”的應用,並使用映象標籤“25”,環境變數設定位“production”。這意味著這是被構建系統第25個標記的映象,並且容器執行在生產環境中。你可能在給定的時間上在容器設施中執行了很多這種例項。標籤在新的釋出時會被改變,但是環境變數配置將會保持為“production”

監控系統將會監控環境變數被設定為“production”的容器映象,就好像監控一個長時間執行的生產服務一樣,這樣就避免了釋出新版本帶來的持續更新的問題。如果你使用編排工具,你應該使用更有表達力的標籤來編組你得容器例項。

容器生產環境中較為合理的監控和日誌策略是使用非侵入解決方案,這樣就與執行時容器進行了隔離。容器監控工具需要容器感知,甚至容器平臺感知。這種感知能力將會幫助監控工具在報告錯誤時避免錯亂,例如當容器在一臺主機中停止的時候並被容器平臺遷移到另外一臺主機。容器的足跡導致一些而外的資料需要被監控和被日誌系統蒐集,因此產生了額外的資料需要管理。

容器監控是一個飛速發展的領域,我們會在今年晚些時候釋出第五部電子書中詳細介紹這部分內容。目前有一些SaaS服務和本地化工具來幫助你應對該領域中的問題。

管理容器資料的方法

目前被廣發接受的管理容器資料的方案是在生產環境中使用無狀態的容器,這些容器不會在其內部儲存任何資料,也就是完全事務性的容器。無狀態容器在外部儲存處理過的資料,超過容器範圍的資料,更可取的方法是使用合適的儲存服務作為可靠並可用的持久化後端。安全性在儲存服務中是被更加重視的,比如資料庫,佇列和快取服務。對於這些有狀態容器,可接受的模式是使用資料容器。有狀態服務的執行時引擎在執行態時與資料容器連結。在實踐中,這意味著資料庫引擎執行在一個容器中,但是“資料容器”被掛在為卷軸來儲存狀態。

如果你使用編排平臺來執行一組主機環境,那麼使用分散式儲存方案是非常有必要的,比如Cluster和Ceph,他們提供了共享掛載點。如果容器例項基於可用性原則在叢集中來回移動,這些方案是非常有用的。

容器安全與金鑰管理

安全是經常讓你擔心的,尤其當不同租戶的多個容器例項執行在共享的機器中時。這種擔心來源於對容器技術能否提供良好的隔離性的信心的缺失,這種期待來源於虛擬機器技術的實現。但是,把容器作為虛擬機器的替代者並不能改善這種擔心。容器的實現,例如Docker,對應用提供安全包裝。容器執行態抽象了在不同名稱空間配置細粒度許可權的複雜性,比如使用者,網路和程式。

如果考慮到在共享設施中一個容器的多租戶釋出過程,使用虛擬機器來隔離不同的租戶,並且使用容器來隔離一個租戶的不同應用元件。當社群中容器釋出持續增長時,那麼就需要去掉虛擬機器的隔離,讓所有使用者共享相同的設施。

執行一個不變容器例項需要考慮的另外一個要點是避免將需要保證安全的金鑰和證書暴露出去。現在有很多方法來解決方這個問題,從將密碼通過環境變數設定,到掛載加密資料容器為卷軸來保護它們。但是,在這些技術中還是又很大隱患,並且從容器執行提供者那裡沒有可用的標準方案。

生產環境容器化展望

成功將容器應用於生產環境的一個重要的條件是建立良好的社群。工具和實踐持續釋出,直到在大多陣列織中執行容器變成一個常規的選項。在此之前,這種適應容器的戰爭在組織內部不會完結。使所有的利益相關者,特別是運維和安全團隊,深刻的認識到他們對於容器的要求是需要很多工作才能實現的。在生產環境中使用容器和使用虛擬機器是非常不同的,並且它將優先需要的是開發經驗和運維簡化,除了資源利用率的好處外。

原文連結:HOW TO RUN CONTAINERS IN PRODUCTION ENVIRONMENTS (翻譯:高洪濤)

===========================================
譯者介紹

高洪濤,噹噹網架構師,開源資料庫分庫分表中介軟體Sharding-JDBC作者。目前從事Docker相關研究工作。

原文釋出時間為:2016-08-14

本文作者:高洪濤

本文來自雲棲社群合作伙伴Dockerone.io,瞭解相關資訊可以關注Dockerone.io。

原文標題:如何在生產環境執行容器


相關文章