基於 Kubernetes 的微服務項目設計與實現

語言: CN / TW / HK

來源:http://dwz.date/eFPd

隨着互聯網的發展,後端服務和容器編排技術的日益成熟,微服務成為了後端服務的首選,Kubernetes 也已經成為目前容器編排的事實標準, 微服務擁抱容器時代已經來臨。

筆者結合自己的經驗,寫了這篇微服務+ Kubernetes 入門寶典,希望能夠拋磚引玉。能讓大家瞭解 微服務和 Kubernetes 如何配合。

上卷主要描述 微服務設計,項目實現,kubernetes 部署,微服務的部署 高可用和監控 這幾個部分。

下卷計劃討論服務化網格和數據持久化, 有狀態服務,operator 這幾部分。

本文由我獨立完成([email protected])如有任何錯誤,是我個人原因,請直接和我聯繫,謝謝!您可以在http://github.com/xiaojiaqi/deploy-microservices-to-a-Kubernetes-cluster 找到本文的全文和相關資料。

本文會從設計開始,設計一個簡單的前後端分離的項目,並將它部署在 kubernetes 集羣上,期間我們將關注微服務和 kubernetes 配合的各個方面,並且從 系統的可用性,可靠性、強壯性、可擴展進行討論,最終設計一個可以真正實用的系統。

整體上我們從4個章節描述這個目標,分別是:

第一章:微服務項目的設計

第二章:微服務項目的具體實現

第三章:kubernetes的部署

第四章:微服務高可用部署及驗證

微服務是一種設計思想,它並不侷限於任何開發語言,在本例中我們選擇java的spring boot 框架來實現微服務。 微服務之間的 RPC 方案也很多,我們這裏選擇RESTFUL 這種最常見的方案。 為了項目的簡潔,項目也沒有涉及數據庫和緩存,配置中心相關的內容。 我們主要注重項目的設計思想實踐和項目改進。

第一章:微服務項目的設計

1.1 微服務設計的思想

首先我們簡單地回顧一下微服務,微服務的定義當來自 Martin flowerlerhttp://martinfowler.com/articles/microservices.html 一文,借用大佬的一張圖 描述了微服務最本質的東西。

微服務把各個功能拆開了,每個模塊的功能更加獨立,也更加單一。每個模塊都獨立發展,可以説做到了功能的高內聚,低偶合。

再借一張,這樣數據庫也被徹底拆分開了。一個巨大複製的單體數據庫也按照功能拆成了小的獨立數據庫。

微服務就是這麼簡單嗎?當然不是,裏面有很多細節需要考慮,紙上得來終覺淺,絕知此事要躬行。這次讓我們開始從0開始真正的設計整套系統。

1.2 實踐設計和改進

現在我們要設計一個最簡單的微服務架構。為了更貼近真實的業務。我們假設這個系統是這樣的。

整個系統的前端是一個有着前後端分離站點,用户訪問了www.demo.com 這個前端站點,通過前端頁面發起請求,www.demo.com 服務器將請求發往a.demo.com.  然後a.demo.com 再請求b.demo.com ,b.demo.com 再請求 c.demo.com。c.demo.com 將結果返回後,不斷返回,最終顯示在前端站點,完成微服務的全套調用流程。[ 一般業務系統 在前端和微服務直接還存在一個網關部分,網關一般用於鑑權,請求分類,監控等功能, 這裏因為比較簡單,所以省略了這個部分]

最終我們將這套架構將部署在kubernetes 上,開始真正的服務用户。

1.3 改進項目

從圖一我們可以看到這是一個非常簡單而單薄的架構,存在很多問題,我們需要不斷地解決它們。下面我們開始改進項目。

首先,我們要解決節點的可靠性。在圖一所有的節點都只有一個實例,任何節點的崩潰都將造成項目無法運行,在真正的項目中這是不可接受的。怎麼解決呢?當然是多個實例

1.3.1 加入多實例及註冊中心

我們將各個模塊的實例數目增加,多個實例才能保證整個系統的可靠性。如果一個實例有問題,我們還是可以其他相同的實例進行服務。

但是多個實例又帶來一個問題,各個組件之間如何定位呢?如果有10個b.demo.com 實例,它的上下游又該如何找到它們呢?解決方案之一是註冊中心。註冊中心解決的是應用之間的尋址問題。有了它,上下游之間的應用可以相互尋址,並且獲知那些實例是可用的,應用挑選可用的實例進行工作。註冊中心的方案很多,有eureka,zookeeper, console, Nacos 等等,關於討論各種註冊中心是AP、CP的區別,優劣的文章很多,這篇文章不是一篇微服務的開發教程,我們選擇比較常見的eureka為演示的註冊中心。

注:在kubernetes 中部署微服務,對註冊中心是沒有任何限制的。所以不要被某些文章誤導,按照這篇文章做,你完全可以做到代碼零修改,直接在kubernetes 上運行。

1.3.2 監控系統 Metrics

在完成了註冊中心的功能後,雖然整個系統可以運行了,我們會發現沒有應用監控的情況下,我們對系統運轉狀態是完全摸黑的,這樣相當於盲人騎馬,非常危險。我們需要知道所有微服務運行的狀態,必須將各個微服務的狀態監控起來,只有這樣才能做到 運籌帷幄,決勝千里。

在這裏,我們選擇使用Prometheus和Grafana這套監控組合。Prometheus + Grafana是一個比較常見的組合, 基本是現在容器監控的標準配置。

在kubernetes 上,我們需要每個微服務的實例裏開啟監控數據到導出功能。同時利用Prometheus 的自動發現功能, 這樣Prometheus 可以將數據收集存儲起來。這裏的數據包括每個應用的各項指標比如內存大小,200錯誤數目,500錯誤數目, JVM裏線程數量,GC時間大小。配合granfana的聚合顯示能力,我們可以直觀地對整個系統有完整把控。在應用開發過程中,我們只需要在代碼里加入一個類庫就可以實現信息的導出,不需要專門寫代碼。

1.3.3 日誌系統 logging

目前已經有了監控,日誌還有存在的必要嗎?當然 下面這個圖就反應監控的3個維度。

這3個維度分別是Mertics Tracing 和logging

Metrics  主要就是指剛才説的監控,它主要反應的就是一個聚合的數據,比如今天200錯誤是多少,QPS是多少?它指的是一段時間內的數據聚合。

Logging 就是我們現在討論的日誌。的它描述一些離散的(不連續的)事件。比如各個系統裏的錯誤,告警。所以我們需要將日誌收集起來。

Tracing 則關注單次請求中信息。我們關注請求的質量和服務可行性,是我們優化系統,排查問題的工具。

説到了日誌,在一個分佈式系統,日誌是非常重要的一環。因為微服務和容器的緣故,導致日誌收集不是這麼簡單了。因為在kubernetes 裏 容器的銷燬和重啟都是經常可能出現的,我們需要第一時間就把日誌收集起來。

日誌收集的方案有很多,有些方案是在本地啟動一個收集進程,將落地的日誌轉發到kakfa組件再轉發日誌中心,也有的方案是直接寫到kafka組件直接進入日誌中心。兩者各有優劣。

在這裏,我們的方案選擇了後者。我們簡單地利用一個組件將日誌直接打入kafka 組件。這種方案的好處是我們日誌不再落地,日誌IO被消除了,日誌的存儲也和容器做到了分離。我們再也不用擔心日誌IO對宿主機造成的系統壓力了。

圖片

1.3.4      追蹤系統 Tracing

剛才我們討論了監控 (Metric)和日誌(Logging),還有一個維度就是追蹤(Tracing).

隨着微服務的實例越來越多,有一個很現實的問題出現了,當大規模分佈式集羣出現了,應用構建在不同的容器集羣裏、有可能布在了幾千台容器裏,橫跨多個不同的數據中心。因此,就需要一些可以幫助理解系統行為、用於分析性能問題的工具。這該怎麼解決呢?可以看看google的論文 google dapper

Google 的論文描述一種解決辦法,我們一般稱作APM(Application Performance Monitor). 它把一次調用加入一個獨立無二的標記,並且在各個系統裏透傳標記,從而達到追蹤整個消息處理過程的能力。市面上大多數實現都是基於這一思想,可選方案的有很多,如 cat pip, zipkin, skywalkin。它們有需要代碼注入的,有無注入的。關於他們的優劣也有很多文章評述。在這裏我們選用zipkin 。Zipkin 需要在項目中加入一個庫,並不需要寫代碼,這對業務的入侵做到了很少,非常方便。

1.3.5 流量控制

你認為這一切就完了嗎?當然不是,微服務裏還有一項非常重要的功能:流量控制,我們還沒有做。

當海量的請求來臨的時候,我們可以用增加容器數量的辦法來提高我們的服務能力,但是簡單地添加實例是很危險的,因為整個系統的服務能力是被系統短板所限制的,簡單地添加實例,並不是總能起到提高服務能力的作用。反而可能引起反作用,最終導致整個系統的崩潰。

我們對整個系統的負載容量是有一個設計的,當超出我們設計的能力時,我們需要對多餘的請求説No。相應的方案分別是熔斷、限流和降級。目前java領域的這方面的hystrix,sentinel 在這方面都做得很好。Sentinel 在阿里接受了考驗,並且使用起來也很簡單,所以我們選它。現在我們在整個系統里加上一個流量控中心。這樣一個基本完整的 可靠的 高可靠的系統就基本完成了。

(在實際開發中,其實還有最關鍵的配置中心(apollo),數據庫(db),緩存(redis) 等組件, 服務化網格, 我們可以把這些組件暫時放在kubernetes 之外,仍然是可以起到同樣的效果)

好了設計部分,先到這裏,開始實現。

第二章:微服務項目的具體實現

從 前端向後端開始實現

2.1 前端站點

前端站點的邏輯很簡單,就是顯示一個頁面,頁面中有一個按鍵。當你點擊按鍵的時候,前端頁面發起ajax請求,訪問前端站點本身的一個接口,這個接口被nginx代理,轉發到a.demo.com 微服務上,a. demo.com 微服務再將請求轉發到b. demo.com, b. demo.com 再將請求轉發到c. demo.com. 最終將結果返回給前端。前端站點再將結果顯示在頁面上。我們通過

結果顯示,就能知道 這次請求通過了那些服務器,每台服務器的服務運行時間大概是多少。

前端站點代碼 大體如下:

然後看a、b、 c 應用部分的java代碼,這就是個普通的多模塊Maven項目。

項目很簡單,分成了3個部分,一個是註冊中心,也就是利用eureka實現註冊中心服務,另一個則是基礎庫項目,大部分功能都在這裏實現,最後則是各個微服務項目,微服務項目只需要簡單調用基礎庫就能完成。

2.2 註冊中心

註冊中心的代碼非常簡單,只需要加一個簡單的聲明

這是註冊中心的配置文件,在kubernetes集羣裏運行時,我們會運行3個節點組成高可用的註冊中心集羣。這時 這個配置項需要相應的修改。

2.3 基礎庫

在基礎庫項目裏,我們將很多的依賴都放在裏面,這樣應用項目只需要簡單依賴基礎庫就可以,能夠做到統一修改。

同時我們也可以看到大部分依賴庫只需要加入就可以,並不需編寫代碼就可以工作,這讓開發工作變得輕鬆。

對於微服務的返回結果,我們做了一些美化格式。這樣可以在檢查結果時,比較容易。

簡單的定義了一些返回的結構,可以通過這些結構,微服務可以把處理時的時間戳,線程號,實例ip這些信息返回出來。

基礎模塊的日誌實現,從github 找的例子簡單地進行了修改。(簡單實現,不要用於生產)這時我們利用logback.xml 的配置,可以選擇我們是把日誌寫入本地磁盤還是直接寫入kafka.

2.4 a.demo.com b.demo.com c.demo.com 應用實現

實現很簡單,只是簡單地調用基礎庫就可以了。注意 每個應用需要實現一個探活接口 /hs. 這樣kubernetes 系統可以通過這個接口來探活,獲知你這個應用是不是準備好了,能不能接入流量。否則 你這個應用可能還在啟動過程中,但是流量已經接入了,那麼肯定會出問題。

在每個應用的配置裏,我們都預置了各個配置的項目,在本地運行的時候,我們可以填注入本地的配置,在kubernetes 裏 以容器形式進行運行,我們可以利用yaml來動態地修改它們,做到2種情況下完全兼容。

第三章:kubernetes的部署

在完成應用的編寫後,我們需要安裝kubernetes系統了,如果已經有kubernetes 集羣的,就可以直接跳過這個部分了,請看下一章。除了kubernetes 集羣以外,你還需要Prometheus and Grafana這樣的監控組件。所以這裏我推薦一個牛逼的安裝工具,和所有現有的Kubernetes 安裝工具比,它是最好的,沒有之一。

它的名字是 K8seasy, 它的優點在於

  1. 可以一鍵安裝整體kubernetes 系統,無需瞭解任何背景知識
  2. 所有的鏡像都已經內置,不會因為下載鏡像失敗而導致失敗
  3. 安裝支持各種不同版本kubernetes版本
  4. 安裝的服務是二進制版本的,非容器版本, 穩定高效
  5. 支持安裝3節點 高可用的生產環境集羣

3.1 安裝過程

下載K8seasy,官方主頁 http://github.com/xiaojiaqi/K8seasy_release_page

安裝下載頁:http://dl.K8seasy.com/

將3個安裝文件都下載下來, 其中 pack.2020.10.02.bin 和installer 都是安裝文件, kubernetes-server-linux-amd64.tar.gz 是kubernetes 的官方軟件包,你可以自己選擇一個最新的版本。

如果要選擇一個其他版本的kubernetes

安裝的過程很簡單,2條命令即可,這裏我們假設 需要安裝Kubernetes的網絡為 192.168.2.0, master 主機為192.168.2.50

1 創建密鑰

sudo ./installer --genkey -hostlist=192.168.2.1

2 創建集羣

sudo ./installer -kubernetestarfile kubernetes-server-linux-amd64v1.18.2.tar.gz -masterip 192.168.2.50

稍等一會兒 就能看到類似如下輸出

就這麼簡單,一個Kubernetes已經裝好了。此時相關的所有監控已經被完全安裝好了。

3. 各項監控

以master 節點為 192.168.2.50 為例子

http://192.168.2.50:10000 可以直接打開dashboard, 對整個集羣有一個全面瞭解

打開 http://192.168.2.50:8080  可以直接訪問alertmanager

打開 http://192.168.2.50:8081 你可以直接使用 Grafana (用户 admin, 密碼admin)

打開 http://192.168.2.50:8082 你可以訪問 Prometheus.

4. 多套環境監控

這一切就完了嗎?當然不是,為了支持多集羣管理,再推薦一個工具。剛才我們説到直接使用 http://192.168.2.50:1000 這個頁面可以直接管理整個集羣,但是在公司裏如果有多個集羣,該如何管理呢? 別擔心,K8seasy 已經有對應的解決方案

仔細看剛才的安裝好的日誌,裏面提示你 專門生產了一個 lens.kubeconfig 的配置文件, 並且有一個 域名和 ip 的對應表。這時候,你只需要 首先在本地Host 文件里加入這個對應

然後去 http://Kuberneteslens.dev/

下載一個lens的安裝包。安裝lens以後,你只需要將 lens.kubeconfig 導入到lens裏

導入完成後,你就可以遠程管理這個集羣了。這樣有多個集羣,你也可以只用一套lens 進行管理了。

Lens的界面優美,使用方便,快試試吧。

好了 Kubernetes 的安裝完成了。當然了K8seasy 的功能是非常強大的,你可以用 sudo ./installer -h 查看幫助, 也可以使用 sudo ./installer -demo 查看各種場景的安裝幫助。

第四章:微服務高可用部署及驗證

Kubernetes 裝好了,現在開始將微服務部署上去了。我們剛才的代碼只是Java 源碼,我們還需要將它們編譯成Jar包,然後再打成docker 鏡像才能部署,這部分比較簡單,所以我不演示如何完成了,我將相關的Dockerfile 和 最終Yaml 都放在Github 裏了,在開始開發時,我提到將日誌寫入Kafka, 所以有2套配置,一套使用了Kafak 一套沒有使用Kafka。請注意區別,有因為沒有Kafka 比較容易實施,我這裏就演示沒有Kafak的版本。這樣所有隻要有一台Linux 就可以保證將整個流程實施成功。

4.1  服務部署上去

依次運行每條部署Yaml的命令即可,不需要做其他的操作。

注意,鏡像在Docker-Hub, 可能需要一定時間能下載。

運行後在 Dashboard 查看,你可以看到類似的信息,所有的服務都已經成功運行。

查看Dashboard

此時修改你本地的Hosts

這樣的話,因為我們的Kubernetes 是支持 nginx-ingress的,所以你可以直接訪問Master的物理IP來訪問這些服務,不需要做任何轉換。

首先我們可以打開dashboard 從中查到eureka.服務器的具體ip, 然後訪問eurka 服務。

查看註冊中心

在頁面中你可以發現,在Kubernetes集羣裏,我們啟動了3個eureka服務,它們相互註冊,組成了一個高可用集羣。

其次,我們在Grafana 中導入 jvm 的監控項目

這樣Grafana可以幫助我們把 各個Java服務的具體狀態做一個收集,完成我們需要的監控。

前端驗證

此時 我們打開 http://www.demo.com 的網頁。

我們可以點擊頁面上的 get 請求按鍵,模擬發出請求,隨後我們就會發現頁面裏顯示出的信息在不斷變化。

在頁面顯示的內容裏,我們可以清楚地發現,我們的消息在不同實例裏處理,如果有一個實例出現了故障是不會影響我們現在的業務的。

好了開始驗證整個系統。

模擬驗證

使用一個簡單的腳本 模擬每3秒從前端訪問一次後端。

調用關係驗證

首先打開zipkin  zipkin.demo.com

點擊具體的請求,可以查看到每次請求在內部的細節。

限流熔斷驗證

其次 打開 sentinel 站點,這個站點可以監控,也可以對微服務進行限流,限速,熔斷等操作。(密碼口令都是 sentinel)

進入控制枱後,我們可以發現所有的服務已經自動被發現,並存在於左邊的菜單。

分別點開 a b c 3個服務,可以看到規律的週期訪問,和我們的腳本的測試速度是一致的。

Sentinel 裏面內含強大的監控,流控 降級等功能,具體的使用,可以慢慢學習,相信你一定會受益良多。

應用狀態驗證

打開Grafana的監控頁,你可以查看所有應用的狀態,包括heap 大小,啟動時間,錯誤數目 等等。

通過這張圖你可以瞭解每個應用本身的狀態,使用了多少內存,響應的代碼是多少,jvm 使用情況。相信此時 你已經對各個組件的情況,監控都有了一個全面瞭解。一個基於 Kubernetes 的微服務架構已經開始工作了。

最後送一張常用的系統架構圖,希望大家能通過本文對高可用微服務如何架設 Kubernetes 上有一個基本的瞭解,將本文討論的東西用於實踐。謝謝!


如果此文對你有所幫助,希望能隨手點個轉發!



End




乾貨分享



這裏為大家準備了一份小小的禮物,關注公眾號,輸入如下代碼,即可獲得百度網盤地址,無套路領取!

001:《程序員必讀書籍》
002:《從無到有搭建中小型互聯網公司後台服務架構與運維架構》
003:《互聯網企業高併發解決方案》
004:《互聯網架構教學視頻》
006:《SpringBoot實現點餐系統》
007:《SpringSecurity實戰視頻》
008:《Hadoop實戰教學視頻》
009:《騰訊2019Techo開發者大會PPT》

010: 微信交流羣


我就知道你“在看”






本文分享自微信公眾號 - JAVA日知錄(javadaily)。
如有侵權,請聯繫 [email protected] 刪除。
本文參與“OSC源創計劃”,歡迎正在閲讀的你也加入,一起分享。