1. 程式人生 > >Kubernetes(K8s)容器設計模式實踐案例

Kubernetes(K8s)容器設計模式實踐案例

《Kubernetes與雲原生應用》專欄是InfoQ向輕元科技首席架構師王昕約稿的系列文章。本專欄包含8篇內容,將會從介紹和分析Kubernetes系統以及雲原生應用 入手,逐步推出基於Kubernetes的容器設計模式實踐案例,希望對計劃應用Kubernetes的朋友有所幫助。本文是該專欄的第七篇。

  1. Kubernetes系統架構與設計理念
  2. 雲原生應用的設計理念與挑戰
  3. Kubernetes與雲原生應用的容器設計模式
  4. Kubernetes容器設計模式實踐案例-單節點多容器模式
  5. Kubernetes容器設計模式實踐案例-多節點選舉模式
  6. Kubernetes容器設計模式實踐案例-工作佇列模式
  7. Kubernetes容器設計模式實踐案例-分散收集模式
  8. 雲原生應用的容器設計模式綜述與展望

Kubernetes與容器設計模式

目前Kubernetes社群推出的容器設計模式主要分為三大類:

第一類,單容器管理模式;

第二類,單節點多容器模式;

第三類,多節點多容器模式;

一類比一類更復雜。根據複雜性的不同,本系列文章給出不同篇幅的實踐案例介紹。雲端計算跟分散式系統是一個事物的兩種解讀:雲端計算是面子,分散式系統是裡子。雲端計算給使用者刻畫出的是方便的、彈性的、自動化的隨時隨地可以得到的資訊處理服務;而後臺,需要雲平臺背後的研發和運維工程師建立維護好一個複雜的分散式系統。

本系列文章所推出的容器設計模式,旨在將分散式系統,特別是將分散式應用模式化,簡化分散式系統的建立和維護。本文將介紹容器設計模式的最後一種,分散收集模式。這是最複雜的一種,但也是最具通用意義的一種模式。分散收集模式先將服務扇出到多個微服務例項上做獨立處理,再將所有處理結果扇入到一個邏輯根微服例項上作合併,以此來完成對一個複雜問題的處理;這和數學和計算機演算法中的分治法非常相似。這一模式對利用k8s平臺執行分散式系統有普遍應用價值。

分散收集模式

分散收集模式利用分散式系統彈性計算能力的容器設計模式。在這一模式中,計算服務的使用者,即服務的客戶端,將初始計算請求傳送給一個“根計算節點”。根計算節點對計算任務做出分割,將任務分割成大量的小計算任務,然後將小計算任務分配給大量計算伺服器進行分散式平行計算 。每個計算伺服器都計算初始計算任務的一小塊,將計算結果返回給根計算節點。根計算節點將所有計算結果合併起來,組成一個針對初始計算任務的一個統一的結果,返回給申請計算任務的客戶端。

這一系統中的分散式伺服器非常適合用容器技術來實現,具體到K8s系統中,就是一個K8s的Pod;具體到Docker系統中,就是一個Docker容器。利用容器快速部署啟動和執行時開銷特別小的特點,任務可以被分到很多小伺服器上並行處理,這些容器形成的小伺服器跟其他任務共同使用基礎設施計算節點的能力。

一個典型的分散收集模式的分散式系統如圖Fig01所示。根節點接受到來自客戶端的服務請求,將服務請求分配給不同的業務模組分散處理,處理結果收集到根節點,經過一定的匯聚合併運算,產生一個合併的結果交付給客戶端。

Fig01 分散收集模式示意圖

Fig01 分散收集模式示意圖

本文中案例的程式碼 本文中使用的程式碼在Github倉庫:https://github.com/xwangqingyuan/metaparticle 本文中使用的程式碼主要以metapaticle專案為基礎:https://github.com/brendandburns/metaparticle 本文作者在此基礎上增加了用於演示scatter gather容器模式的案例,在https://github.com/xwangqingyuan/metaparticle/tree/master/examples目錄下。

分散式計算模式專案Metapaticle

Metapaticle專案的目的在開發並展示一種基礎設施即程式碼的程式設計模式,力圖將基礎設施管理邏輯和功能運算邏輯以同一種語言實現在同一短小精幹的程式中。

在分散式計算系統中,不僅功能性計算的邏輯是重要的,對計算系統的邏輯拓撲結構的控制也是重要的。大家可以想象,依靠流行大資料分析框架Hadoop MapReduce,Spark,Storm和Flink等進行分散式大資料運算,程式碼中往往包含邏輯拓撲結構的邏輯。

在以往的分散式計算特別是雲端計算體系中,大多將基礎設施管理的邏輯由配置檔案和自動化運維工具來配置,而功能運算邏輯由通用的程式語言來控制。這一模式也比較符合過去基礎設施管理邏輯和功能運算邏輯的特點

在過去,基礎設施相對固定,變化較小,因此用來管理它的配置檔案和自動化運維工具不需要支援太強大的動態邏輯功能;另一方面,過去大多數程式語言的抽象度和表達能力較底層,以命令式的程式設計正規化為主;因此,功能運算邏輯和基礎設施管理邏輯相距較遠。即便如此,當開發人員開始運維自己的軟體系統時,不可避免地將同時用兩種語言分別管理基礎設施和功能運算邏輯,往往給開發人員帶來不舒服的感覺。

隨著雲端計算特別是容器技術的流行,計算機系統的基礎設施越來越動態,人們對基礎設施管理控制的邏輯控能力要求越來越大。同時,隨著計算機語言的發展,函數語言程式設計,宣告式語言越來越收到開發人員的熟悉;人們越來越傾向於使用高抽象度的、高表達力的函數語言程式設計模式甚至宣告式語言來快速地實現功能邏輯,使得很多應用功能邏輯的程式碼看上去越來越簡單得像“配置檔案”。這樣,對基礎設施管理邏輯控制能力的需求和對功能運算邏輯控制能力的需求似乎越來越接近了。

在這種背景下,metaparticle專案被設計用來探索將基礎設施管理邏輯和功能運算邏輯以同一種程式語言來實現的模式。正像我們提到的,隨著雲端計算和容器的發展,基礎設施管理邏輯和功能運算邏輯越來越融合成一個整體的分散式計算任務。Metaparticle謀求的正是用同一種語言搞定一個整體的計算任務。

目前metaparticle主要支援javascript語言,主要是利用它的簡單性和它對函數語言程式設計的支援。當然,按照metaparticle的設計思想,未來Python,Scala,Swift這些較高階的語言都可是用來實現metaparticle的模式。Metaparticle的設計思想在於用同一種語言完成同一個分散式計算任務,但是並不會謀求限制到某一種特定語言。

Metaparticle專案還很初級,主要對我們的幫助還是試驗和啟發作用。Metaparticle支援3種分散式系統的服務模式:分散收集模式(Scatter/Gather)、分片模式(Shard)和水平擴充套件模式(Spread)。其中分散收集模式是更具通用性的一種模式,正好也是本系列文章中準備介紹的最後一種容器設計模式,也是最複雜的一種設計模式。本文中針對分散收集模式的演示案例,以metaparticle為基礎,先要通過nodejs的包管理工具安裝metaparticle模組,然後通過node來試驗本文中的案例。

安裝Metaparticle

本文中的演示案例以Metaparticle的Scatter/Gather模式為基礎,要安裝可參照檔案https://github.com/xwangqingyuan/metaparticle/blob/master/README.md和https://github.com/xwangqingyuan/metaparticle/blob/master/examples/server1.md 要通過NPM安裝Metaparticle,可以直接執行: $ npm install metaparticle 也可以下載程式碼後,通過原生代碼安裝: $ git clone https://github.com/xwangqingyuan/metaparticle.git$ npm install ./metaparticle/ 在安裝過程中如果碰到缺少的nodejs module,直接用npm install即可。

通過分散收集計算正態分佈(高斯分佈)的統計特性

在本演示案例中,利用分散收集模式模擬展示一個正態分佈的統計直方圖。 計算高斯分佈的示例程式碼檔案scatter-gather-gaussian.js清單。

// Import the main library var mp = require(‘metaparticle’);   // A simple function for calculating a Gaussian distributed value // from a uniform random value var gaussian = function (sigma, mean) {     var u1 = 2 * Math.PI * Math.random();     var u2 = -2 * Math.log(Math.random());     var n = Math.sqrt(u2) * Math.cos(u1);     return n * sigma + mean; };

// This function is executed on each leaf var leafFunction = function (data) {     var result = { ‘n’: [] };     for (var i = 0; i < 100; i++) {         result.n.push(gaussian(25, 100));     }     return result; };

// This function is executed on each root var mergeFunction = function (responses) {     var histogram = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0];       for (var i = 0; i < responses.length; i++) {         for (var j = 0; j < responses[i].n.length; j++) {             if (responses[i].n < 0 || responses[i].n > 200) {                 continue             }             var ix = Math.floor(responses[i].n[j] / 20);             histogram[ix]++;         }     }     return histogram; };

var svc = mp.service(     // name of the service     “histogram-service”,     // library function that creates a scatter/gather service     mp.scatter(10, leafFunction, mergeFunction));   // Expose the root service to the world svc.subservices.gather.expose = true;   // And serve mp.serve();

在本例中,根伺服器將計算任務分配給10個葉子伺服器計算。方法mp.scatter用來排程整體的分散式計算。方法mp.scatter的第一個引數是分片的個數,第2個引數是葉子伺服器的計算函式leafFunction,第3個引數是根伺服器合併的計算函式mergeFunction。

在本例中,每個葉子節點都模擬一個方差為25,均值為100的正態分佈隨機變數。計算函式leafFunction用來產生100個隨機變數,計算函式mergeFunction用來合併所有子節點的隨機變數,統計這些隨機變數的樣本值處在不同區間的個數。

啟動分散收集模式計算高斯分佈的伺服器端容器服務。 [email protected]:/gitws/github.com/xwangqingyuan/metaparticle/examples$ node scatter-gather-gaussian.jsbuilding image (this may take a bit)building image done.deploying

執行客戶端程式傳送請求計算統計結果。 [email protected]:/gitws/github.com/xwangqingyuan/metaparticle/examples$ node client.js histogram-service[0,4,55,139,296,284,160,53,9,0] 通過計算結果可以看到,正如一般正態分佈所預期的一樣,正態分佈的主要樣本個數集中在直方圖中間的部分296和284,越向兩邊樣本個數越少。

停止並刪除分散收集模式的伺服器端容器服務。 [email protected]:/gitws/github.com/xwangqingyuan/metaparticle/examples$ node scatter-gather-gaussian.js delete

通過分散收集計算均勻分佈的統計特性

在本例中,每個葉子節點都模擬一個處於0到200之間的均勻分佈的隨機變數。計算函式leafFunction用來產生100個隨機變數,計算函式mergeFunction用來合併所有子節點的隨機變數,統計這些隨機變數的樣本值處在不同區間的個數。 計算均勻分佈的示例程式碼檔案scatter-gather-uniform.js清單。

// Import the main library var mp = require(‘metaparticle’);   // A simple function to caculate a uniform integer var uniform = function (lower, upper) {     return Math.round(lower + (upper-lower)*Math.random()); };   // This function is executed on each leaf var leafFunction = function (data) {     var result = { ‘n’: [] };     for (var i = 0; i < 100; i++) {         result.n.push(uniform(0, 200));     }     return result; };   // This function is executed on each root var mergeFunction = function (responses) {     var histogram = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0];       for (var i = 0; i < responses.length; i++) {         for (var j = 0; j < 10; j++) {             histogram[j] += responses[i].n[j];         }     }     return histogram; };

var svc = mp.service(     // name of the service     “histogram-service”,     // library function that creates a scatter/gather service     mp.scatter(10, leafFunction, mergeFunction));   // Expose the root service to the world svc.subservices.gather.expose = true;   // And serve mp.serve();

啟動分散收集模式計算均勻分佈的伺服器端容器服務。 [email protected]:/gitws/github.com/xwangqingyuan/metaparticle/examples$ node scatter-gather-uniform.js.jsbuilding image (this may take a bit)building image done.deploying

執行客戶端程式傳送請求計算統計結果。 [email protected]:/gitws/github.com/xwangqingyuan/metaparticle/examples$ node client.js histogram-service[1244,980,1066,961,679,1097,825,1021,719,911] 通過計算結果可以看到,正如一般均勻分佈所預期的一樣,均勻分佈的主要樣本個數在10個收集得到的樣本區間分佈比較均勻,圍繞平均數1000上下波動。

停止並刪除分散收集模式的伺服器端容器服務。 [email protected]:/gitws/github.com/xwangqingyuan/metaparticle/examples$ node scatter-gather-uniform.js delete

通過分散收集計算整數中的數字出現頻率

在本例中,利用分散收集模式,模擬統計一系列整數的10進位制佔位數字的統計特性。 在本例中,每個葉子節點都計算100個處於0到100之間的均勻分佈的整數的所有佔位數字的出現次數,例如56這個整數,有5和6兩個數字,會給5和6這兩個數字的次數分別增加1。計算函式leafFunction用來產生100個隨機變數,並統計這100個隨機變數的數字(0-9)出現次數,計算函式mergeFunction用來合併所有子節點的計算的出現次數,計算出總的出現次數。

計算整數中的數字出現頻率的示例程式碼檔案scatter-gather-count-digit.js清單。

// Import the main library var mp = require(‘metaparticle’);   // A simple function to caculate a uniform integer var uniform = function (lower, upper) {     return Math.round(lower + (upper-lower)*Math.random()); };   // This function is executed on each leaf var leafFunction = function (data) {     var result = {‘n’: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]};     for (var i = 0; i < 100; i++) {         var num = uniform(0, 100);         var str = “” + num;         for (var j = 0; j < str.length; j++) {           var digit = parseInt(str.charAt(j));           result.n[digit]++;         }     }     return result; };   // This function is executed on each root var mergeFunction = function (responses) {     var histogram = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0];       for (var i = 0; i < responses.length; i++) {         for (var j = 0; j < 10; j++) {             histogram[j] += responses[i].n[j];         }     }     return histogram; };

var svc = mp.service(     // name of the service     “histogram-service”,     // library function that creates a scatter/gather service     mp.scatter(10, leafFunction, mergeFunction));   // Expose the root service to the world svc.subservices.gather.expose = true;   // And serve mp.serve();

啟動分散收集模式計算高斯分佈的伺服器端容器服務。 [email protected]:/gitws/github.com/xwangqingyuan/metaparticle/examples$ node scatter-gather-count-digit.jsbuilding image (this may take a bit)building image done.deploying

執行客戶端程式傳送請求計算統計結果。 [email protected]:/gitws/github.com/xwangqingyuan/metaparticle/examples$ node client.js histogram-service[83,184,178,196,207,202,204,231,205,196] 通過計算結果可以看到,在所有數字中,1-9的數字出現頻率是比較接近的,大概在200左右,而0作為數字出現頻率是較低的,大概少100個左右,這是因為0不會作為首位數字出現。

停止並刪除分散收集模式的伺服器端容器服務。 [email protected]:/gitws/github.com/xwangqingyuan/metaparticle/examples$ node scatter-gather-count-digit.js delete

通過分散收集計算整數末尾數字的出現頻率

在本例中,利用分散收集模式,模擬統計一系列整數的10進位制末尾數字的出現。 在本例中,每個葉子節點都計算100個處於0到100之間的5的倍數的末尾數字的出現頻率。計算函式leafFunction用來產生100個隨機變數,並統計這100個隨機變數的數字(0-9)出現次數,計算函式mergeFunction用來合併所有子節點的計算的出現次數,計算出總的出現次數。

計算高斯分佈的示例程式碼檔案scatter-gather-count-last-digit.js清單。

// Import the main library var mp = require(‘metaparticle’);   // A simple function to caculate a uniform integer var uniform = function (lower, upper) {     return Math.round(lower + (upper-lower)*Math.random()); };   // This function is executed on each leaf var leafFunction = function (data) {     var result = {‘n’: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]};     for (var i = 0; i < 100; i++) {         var num = uniform(0, 20)*5;         var str = “” + num;         var digit = parseInt(str.charAt(str.length-1));         result.n[digit]++;     }     return result; };   // This function is executed on each root var mergeFunction = function (responses) {     var histogram = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0];       for (var i = 0; i < responses.length; i++) {         for (var j = 0; j < 10; j++) {             histogram[j] += responses[i].n[j];         }     }     return histogram; };

var svc = mp.service(     // name of the service     “histogram-service”,     // library function that creates a scatter/gather service     mp.scatter(10, leafFunction, mergeFunction));   // Expose the root service to the world svc.subservices.gather.expose = true;   // And serve mp.serve();

啟動分散收集模式計算高斯分佈的伺服器端容器服務。 [email protected]:/gitws/github.com/xwangqingyuan/metaparticle/examples$ node scatter-gather-count-last-digit.jsbuilding image (this may take a bit)building image done.Deploying

執行客戶端程式傳送請求計算統計結果。 [email protected]:/gitws/github.com/xwangqingyuan/metaparticle/examples$ node client.js histogram-service[495,0,0,0,0,505,0,0,0,0] 通過計算結果可以看到,在所有數字中,0和5的作為末尾數字佔據了所有出現次數,各佔出現頻率的一半,而其他數字不會作為末尾數字出現;這很顯然,因為這裡統計的所有整數都是5的倍數。

停止並刪除分散收集模式的伺服器端容器服務。 [email protected]:/gitws/github.com/xwangqingyuan/metaparticle/examples$ node scatter-gather-count-last-digit.js delete

總結

本文主要介紹了K8s叢集中,多節點容器模式中的分散收集模式。分散收集模式利用分散式系統彈性計算能力的容器設計模式。在這一模式中,計算服務的使用者,即服務的客戶端,將初始計算請求傳送給一個“根計算節點”。根計算節點對計算任務做出分割,將任務分割成大量的小計算任務,然後將小計算任務分配給大量計算伺服器進行分散式平行計算 。每個計算伺服器都計算初始計算任務的一小塊,將計算結果返回給根計算節點。根計算節點將所有計算結果合併起來,組成一個針對初始計算任務的一個統一的結果,返回給申請計算任務的客戶端。分散收集模式是本系列容器設計模式的最後一種,也是最複雜的和最有普遍應用價值的一種模式。

本文同時介紹了分散式計算模式專案Metapaticle,該專案的目的在開發並展示一種基礎設施即程式碼的程式設計模式,力圖將基礎設施管理邏輯和功能運算邏輯以同一種語言實現在同一短小精幹的程式中。依靠K8s叢集強大的基礎設施編排引擎和控制工具,以容器為基礎實施的分散式應用可以獲得強大的動態管理基礎設施的能力,DevOps理念從流程管理上連通開發和運維,而Metapaticle則考慮從程式設計正規化和程式語言上打通開發和運維,成為一種新的DevOps自動化工具。