不聊什麼
在開始聊operator前,先說說這篇文章裡我們不聊什麼。我們這裡不聊operator的具體實現,不聊operator的由來歷史,不聊operator的hello world。如果想了解這些,其實可以從別的很多文章中可以查詢到。這裡我們把一些常見的概念,如docker、controller、Helm、編排等,與operator進行一下對比,從這些概念的不同角度來聊聊operator,並聊聊在我眼中的operator的核心價值。
operator與docker
我們先聊一聊docker。docker有非常多的優點,比如隔離、執行效率等等。但是在我看來,docker的核心價值,或者說顛覆性的成果就是設計了映象流程,提供標準化的交付方式。就從單個的應用例項來講,標準化、一致性的環境解決了應用的runtime的問題,將應用的部署、應用的依賴進行了統一的封裝。將應用的部署方式從手工作坊的部署方式帶入了標準化的工業時代。當然這也帶來了一定的磁碟額外損耗。但是在硬體飛速發展的今天,這點磁碟損耗幾乎不成問題。而且藉助於聯合檔案系統和映象優化,磁碟的損耗問題幾乎不用考慮。
時至今日,越來越少的專案採用原始碼進行部署。以前一個開源專案往往配上一篇冗長的安裝文件,教你如何安裝、如何執行。現在,基本上活躍的開源專案都提供了基於容器的部署方式,你只需要拉下映象run一下就可以使用。docker大大提升了交付的效率,降低了使用的門檻,有效避免了部署的故障。
operator跟docker是相似的,而其主要的交付物件從單個的應用例項,擴充套件到了多例項、分散式的系統上。以往部署一個分散式系統需要啟動多個容器,然後進行復雜的配置,而現在只要建立一個CRD。operator將自動進行分散式系統中需要的各個資源的建立和部署。從這個角度上來說,operator的目標是實現分散式系統的標準化交付。
operator與編排/Helm
現在我們一般意義上的編排,也就是orchestration,還有另一種翻譯就是編配。在維基百科的定義為描述複雜計算機系統、中介軟體(middleware)和業務的自動化的安排、協調和管理。根據我個人的經驗,總結編排的典型特徵主要包括服務的版本管理、服務的生命週期管理、多個資源多種資源的管理、引數化以及模板化。
最早接觸編排概念,是通過openstack的heat專案。openstack中從計算、儲存到網路有很多的系統。而如果部署一個完整的應用虛擬機器,需要多種資源的協同參與。heat專案就是為此目標而生。其通過模板和引數對多種資源進行編排,實現了對一個完整服務的建立、部署、修改、刪除等生命週期管理。
在k8s中,也有許多編排專案,目前比較熱門的是包管理工具Helm。如果說docker是奠定的單例項的標準化交付,那麼Helm則是叢集化多例項、多資源的標準化交付。
operator的管理不僅限於容器(pod),也可以是多個資源(比如svc域名等等),從這個角度上來說,operator跟Helm一樣,也是具有編排的能力的。從編排角度來看,在初學者看來,Helm跟operator有非常多的共性,很難對兩者的作用進行區分。Helm也可以完成分散式系統的部署。那麼operator跟Helm又有什麼樣的區別呢?Helm的側重點在於多種多個的資源管理,而對生命週期的管理主要包括建立更新和刪除。Helm通過命令驅動整個的生命週期。
而operator對於資源的管理則不僅是建立和交付。由於其可以通過watch的方式獲取相關資源的變化事件,因此可以實現高可用、可擴充套件、故障恢復等運維操作。因此operator對於生命週期的管理不僅包括建立,故障恢復,高可用,升級,擴容縮容,異常處理,以及最終的清理等等。
那你說這些功能能不能用Helm來實現,其實我覺得有一部分功能應該也是可以的。但是這裡面就涉及到一個問題,就是這些功能無法在編排中直接實現,就需要通過指令碼或者程式的方式固化到映象中。大量的運維程式碼被指令碼化。會導致維護這些指令碼的複雜度提高,可讀性變差。除此之外,還有一個潛在的風險無法解決的就是,當這些容器例項全部掛掉的時候,則完全無法自動恢復了,即使有備份資料。這時候最終還會依賴於人工的介入,仍然無法達到自動化、智慧化的目標。
operator則在實現自動化的同時實現了智慧化。其主要的工作流程是根據當前的狀態,進行智慧分析判斷,並最終進行建立、恢復、升級等操作。而位於容器中的指令碼,因為缺乏很多全域性的資訊,僅靠自身是無法無法達實現這些全部的功能的。而處於第三方視角的operator,則可以解決這個問題。他可以通過側面的觀察,獲取所有的資源的狀態和資訊,並且跟預想/宣告的狀態進行比較。通過預置的分析流程進行判斷,從而進行相應的操作,並最終達到宣告狀態的一個目的。這樣所有的運維邏輯就從映象中抽取出來,集中到operator裡去。層次和邏輯也就更加清楚,容易維護,也更容易交付和傳承。
如果把Helm比作rpm,那麼operator就是systemd。rpm負責應用的安裝、刪除,而systemd則負責應用的啟動、重啟等等操作。當然二者並不是互斥的,目前operator一種比較便捷的部署方式就是通過Helm進行部署。
operator與controller
operator可以說是另外一種controller。目前的controller manager集合的主要是基礎的、通用的資源概念,比如rs/deployment,而對於特定的應用或者服務(如etcdcluster,都可以認為是一種資源),則放權給了第三方,也就是CRD。使用者可以通過自定義的資源描述,以及自研的controller/operator進行接入。因此controller和operator的關係有點類似於標準庫和第三方庫的關係。
一般來說,對於不同的應用一般來說需要不同的operator進行處理。這時我們再來想下,以replicaset controller為例。rs的主要功能是保持副本數。當有pod因某種原因掛掉/刪除,對於無狀態的應用來說,恢復的方式就是再增加對應的pod數量。那麼從這個角度來說,對於無狀態的應用來說,rs controller其實就是無狀態應用的operator。
operator的核心價值
我們原先常常講devops,就是運維和開發的結合,提升開發交付的效率和質量。這也帶來了一個趨勢,就是運維和開發一體化。比如原來開發應用的人,通過docker映象的製作,將應用的部署啟動等固化在了dockerfile/映象中,分擔了運維的許多部署工作。但是實際上運維的工作內容和範圍其實非常廣,特別是現在的分散式的系統,包括叢集化部署、高可用、故障恢復、系統升級等等工作。而這些是無法僅用dockerfile/映象進行固化的。
operator提供了一種可能,或者說是提供了一個很好的框架,就是把運維的經驗沉澱為程式碼,實現運維的程式碼化、自動化、智慧化。以往的高可用、擴充套件收縮,以及故障恢復等等運維操作,都通過operator進行沉澱下來。從長期來看,將會推進dev、ops、devops的深度一體化。將運維經驗、應用的各種方案和功能通過程式碼的方式進行固化和傳承,減少人為故障的概率,提升整個運維的效率。
operator的許多理念並不是現在才有的。在yarn中的application manager,mesos中的framework,都可以尋找到operator的一些蛛絲馬跡。而之所以說operator將可能成為docker之後的又一項重大變革,其另外一個重要的因素就是operator是站在kubernetes的巨人肩膀上。
kubernetes強化了基礎資源的封裝,並保持了靈活性和可定製性。kubernetes從傳統的資源(cpu/mem)的交付,轉為了pod/svc/pv/pvc等資源的交付,擴充套件了資源的概念,將域名、負載均衡、儲存等等必要或相關的概念也都進行了封裝。而operator這些公共的資源基礎上,將應用叢集也視為了一種資源,可以向使用者提供。並且藉助於k8s已有的工作機制和框架,從而更為便捷靈活的實現。
operator的變革雖然重大,但是由於分散式應用主要限於工業生產領域,因此對一般的開發而言可能最終使用場景有限。因此我判斷從全域性看,operator的最終影響力有限,但在許多分散式應用的垂直領域,會產生巨大的影響。
寫在最後
使用operator的前提就是可以實現容器化。即應用可以使用容器來進行應用的自動化的部署。operator化不僅僅是開發一個operator的程式,還需要結合映象的製作、交付、封裝等工作。仍然是需要大量的開發工作的。但是一旦成熟穩定,也會帶來巨大的運維收益和長期的效果。
注: 本文已在InfoQ上首發,原文連結為https://www.infoq.cn/article/SJMUvMg_0H7BS5d99euR。