企業級應用Service Management Automation X(SMAX)的微服務之路

相比於瞬息萬變的互聯網應用,企業級應用如何做到快速的兌現客戶承諾,及時的響應用戶和市場需求?技術轉型是必然趨勢,不破不立,微服務理念的崛起恰好給了企業技術轉型的絕好機會。但微服務的改造之路並不是一帆風順的,這裏不僅涉及到技術層面的改造,還有管理模式,工作方式的改變。本次分享淺談一些個人看法和Mico Focus公司的實踐經驗。
正文開始之前,讓我先簡單的介紹一下我們的產品,Service Management Automation X(SMAX)來自於全球領先的純軟件公司Micro Focus,基於ITIL(Information Technology Infrastructure Library)實現,ITIL是全球公認的一系列IT服務管理最佳實踐。ITIL的基本架構可參見下圖:

2976efa1e9af634711d7b0c86904b7ef.jpeg


困局?

28a36f4995867f5212f6d5f4645419ca.png


2017年的時候,我們整個項目組還在使用瀑布模型的方式開發、發佈產品。每次產品的迭代發佈週期是一年。相比於瞬息萬變的互聯網應用,可能每個月都有一次版本更新,我們的產品版本更新太慢。爲何要如此頻繁的更新產品呢?頻繁的發佈更新可以快速的兌現客戶承諾,及時的響應用戶和市場需求,最大化的實現商業價值,小步快跑的方式搶佔市場。對於企業級應用來說,也是一樣的,我們需要快速的兌現商業價值,讓客戶儘早的用上新功能。因此從公司的戰略層面,決定將版本更新的頻率提升4倍,發佈週期從原來的1年,縮短爲3個月。
要實現這個戰略目標,對現有的組織架構、技術架構等都是非常大的挑戰。我們需要一種新型戰術來滿足我們的業務需求。微服務正好可以解決產品快速迭代的問題,並且具有以下優點:
  • 提升開發交流,每個服務足夠內聚,足夠小,代碼容易理解;

  • 服務獨立測試、部署、升級、發佈;

  • 容易擴大開發團隊,可以針對每個服務組建開發團隊;

  • 提高容錯性,一個服務的內存泄露不會導致整個系統癱瘓。


最終我們選擇了微服務,幫助我們快速的迭代產品,快速的實現商業價值。同時在開發流程上我們開始使用敏捷開發,並倡導DevOps文化,希望各個小團隊可以達到團隊自治,對市場做到快速響應。


破局?

28a36f4995867f5212f6d5f4645419ca.png


當確定了戰略目標後,就是怎麼做了?可以從兩個角度來討論。
  • 管理層面

  • 技術層面


管理層面
微服務的轉型之路,這個決定必然是由上而下的,從管理層到具體的每個開發人員,我們必須在觀念上達成一致,不破不立,敢於嘗試新技術,但也不可盲目採用新技術,爲了技術而技術,前期適當的小規模驗證過程是很有必要的。對於一些腐朽的舊思想也要能做到果斷的拋棄。
我們整個開發團隊的人數達到了數百人,對於如何管理一個數百人的敏捷團隊,也缺乏業界的最佳實踐,我們也只能摸着石頭過河。對於如何做好敏捷開發,我們依然在不斷探索中,找到最適合我們的方式。對於大型企業,現在業界有一套完整的敏捷開發解決方案SAFe,我們也在嘗試中。
技術層面
回到技術層面,我將從以下幾個方面來講我們的轉型之路:
  • 技術選型

  • 服務拆分

  • 安全

    • 容器安全

    • 敏感信息保護


  • 企業級可用(Enterprise Ready)

    • 健康檢查

    • 零停機升級


  • DevOps

    • Pipeline

    • 性能測試

    • 監控

    • GitOps


技術選型

28a36f4995867f5212f6d5f4645419ca.png


現在一提到微服務,很多人會想到容器技術,比如Docker。
那麼微服務和容器之間到底有什麼關係呢?我的回答是,微服務和容器沒有任何關係。
微服務理念出現的時間要比容器技術早很多,其理念在70年代被提出。而容器技術在2013年才被提出,它最初由一個叫做dotCloud的項目發展而來,後來改名叫做Docker。基於微服務的思想開發應用程序是完全可以不用容器技術的,例如現在流行的Spring Cloud和Dubbo都是不使用容器技術來實現微服務思想的。
那爲什麼微服務和容器技術總是被同時提起?這主要是出於以下兩個原因:
  • 按照微服務的理念,如果使用容器作爲基礎設施,能夠實現快速部署,快速迭代,獨立運行;

  • 在雲計算中,容器作爲替代虛擬機的基礎設施受到大家的關注度更高。


如果能將容器技術應用於微服務中,簡直能達到事半功倍的效果。既然是微服務,必然會產生許許多多小的服務,如何對其進行管理就成爲了我們很現實的問題。2017年時,容器編排平臺的百花齊放,我們猶豫了,到底該怎麼選擇?當時很多互聯網公司開始自研自己的容器編排平臺,雖然這能獲得極大的獨立自主性,但同時自研也需要大量的研發投入,這是我們不能承受的。然後我們把目光放到了開源社區,當時比較知名的容器編排平臺有Kubernetes和Docker Swarm。

d913cacc6f7a536ec32be3dfdfd64826.jpeg


可能出乎很多人的意料,我們一開始用的是Docker Swarm,選它的理由也很簡單,Docker Swarm上手快,學習曲線平緩。但在使用或者嘗試的過程中,我們低估了我們產品的複雜性,Docker Swarm遠不能滿足我們的需求。最終,我們又決定轉移到Kubernetes平臺,萬幸的是,我們並沒有在Docker Swarm上花太多時間,平臺轉移的決定也做的很堅定。這在微服務改造的過程中是很關鍵的,人總會有犯錯的時候,勇於承認錯誤,並不斷地做調整,不拖泥帶水優柔寡斷。一定的試錯成本是不可避免地,不要害怕試錯。
現在回過頭來看,我們當時選擇Kubernetes的決定,真的是“賭”對了。Kubernetes自身就是一個完整的分佈式系統解決方案,支持服務發現,服務註冊,擴縮容,跨主機部署,企業級就緒,自我修復,自動重啓等功能,能幫助我們省下一大筆自研的投入。
Kubernetes起源於Google內部系統Borg,經過多年的實際運行,更成熟,更穩定。更是依託於活躍的社區,以及CNCF基金會的加持,雲原生技術的不斷髮展,我們可以很容易的從社區得到幫助,以及很多非常棒的技術實現,幫助我們解決了很多問題。比如Hashicorp公司的Vault,一款出色的存儲敏感信息的軟件,還有監控軟件Prometheus。


服務拆分

28a36f4995867f5212f6d5f4645419ca.png


有了技術選型,Kubernetes和Docker,我們就可以進一步進行微服務拆分。服務拆分,如何拆分?拆到什麼程度?
談到服務拆分,不得不提的就是著名的“康威定律”,“軟件架構會反映出公司的組織架構,組織架構又反過來影響着軟件架構。”
爲獲得更大的溝通效益,微服務架構的改造必然會導致組織架構的改變。我們需要在現有技術架構,組織架構間不斷做調整,平衡兩者的關係,最終將服務拆分爲四大模塊。
  • 事件管理、問題管理、變更管理、服務資產/配置管理

  • 租戶管理

  • 智能分析

  • 通用服務


每個業務模塊有一個團隊負責開發維護,每個團隊的人數大概是3-5人,並由團隊自己做適當的繼續拆分,落地爲真正提供服務的Pod。
個人認爲,對於大型企業級應用來說,因爲本身架構、技術債務、組織架構等等原因,不急於將應用程序拆的非常細。一是拆的越細成本越高,花費的時間也會越長,短期內看不到業務價值,就很難說服業務方同意此方案。二是從未來來看,不能保證現在的拆分就是合理的,應遵循小步快走,快速試錯的原則。
每個組件必須可以獨立運行,這是業界對於微服務的公認標準。這裏對於組件的定義,個人認爲可以擴展到由多個Pod組成,共同提供功能,而不是要求每個Pod必須可以獨立的提供功能。對於現有應用程序的微服務改造,不考慮現狀,過高的標準是不合時宜的。我們可以以架構演進的方式,慢慢迭代開發,最終不斷完善我們的應用程序。
總結來說,我們的拆分原則是,先按業務功能分成大的模塊,在由各個團隊,結合業務和技術實現繼續拆分。同時針對微服務中的一些通用功能可以成立一個獨立團隊負責,常見的通用功能有路由模塊、鑑權授權模塊。

021954a782e7040e4b112d3ba4b1fe91.png


安全

28a36f4995867f5212f6d5f4645419ca.png


容器安全
在以色列,我們有專門的安全團隊負責對我們的產品進行安全掃描,可以從以下幾個維度來檢查及保證容器的安全性。
惡意及脆弱鏡像,在Docker Hub市場中有成千上萬的免費鏡像,可隨時在Docker容器中使用。然而一項研究表明,在測試的2500多個Docker鏡像中發現了大量安全漏洞。選擇官方或可信的鏡像,避免引入脆弱組件,更甚者是惡意代碼。Docker Hub也提供付費計劃,可以對鏡像進行“安全掃描”,檢查鏡像中的已知漏洞。
過量資源使用,一般情況下,Docker容器沒有資源限制。因此,不受限制的Docker容器可能導致宿主機性能嚴重下降。要對內存、帶寬和磁盤使用(I/O)設置資源限制,保證整體性能的穩定。
容器突破,在 Dockerfile 中,如果我們不顯式指明用戶,進行權限處理,那麼Docker容器默認在運行時會以root身份運行,以root身份啓動 Docker容器是一件很危險的事情。儘管,Docker容器內的root與宿主host本身的root並不一定具有一樣的權限,但是在容器內部的root擁有和宿主機一樣的UID(UID 0)。如果以priviledge的方式運行container,那麼兩者將會一樣,從而產生巨大的安全隱患。應遵守最小權限原則,避免潛在的安全風險。
對Docker鏡像進行簽名及驗證,保證客戶能拿到真正由我們公司發佈的Docker鏡像,防止***對Docker鏡像的惡意篡改。
不要在Docker鏡像中存放敏感信息,現在市面上檢查容器安全的工具有很多,我們目前使用的工具有Anchore(https://anchore.com/)和Aujas(https://www.aujas.com/)。
敏感信息保護
微服務間各個Pod之間的通信需要進行安全認證,需要用到證書以及用戶名密碼。證書該如何被安全的分發到各個Pod內部呢?Pod應該如何獲取密碼?基於Kubernetes強大的生態系統,Hashicorp公司的Vault正好可以滿足我們的技術需求。有關Vault的更多使用可以訪問官網:https://www.hashicorp.com/products/vault


企業級可用(Enterprise Ready)

28a36f4995867f5212f6d5f4645419ca.png


健康檢查
作爲企業級軟件,我們的很多客戶都是跨國公司,在各個國家都有員工,跨時區,則要求我們的應用程序必須24小時穩定提供服務。那該如何保證高可用?在軟件行業,你可能經常聽見這樣一句話,“要不你重啓試試?”的確,很多問題都可以通過重啓解決,藉助於Kubernetes提供的自愈功能,我們爲所有的Pod設置了合理的Liveness探針和Readiness探針來提高整體應用的可用性。
Kubernetes使用Liveness Probe(存活探針)來確定何時重啓容器。例如,Java程序內存泄漏了,程序無法正常工作,但是JVM進程卻是一直運行的,對於這種應用本身業務出現了問題的情況,通過檢測容器響應是否正常來決定是否重啓,這是一種很好的健康檢查機制。
Kubernetes使用Readiness Probe(就緒探針)來確定容器是否已經就緒可以接受流量。只有當Pod中的容器都處於就緒狀態時Kubernetes纔會認定該Pod處於就緒狀態。該信號的作用是控制哪些Pod應該作爲Service的後端。如果Pod處於非就緒狀態,那麼它們將會從Service的Endpoint中移除。
配置有效的Liveness Probe
Liveness Probe應該檢查什麼?
一個好的Liveness Probe應該檢查應用內部所有關鍵部分是否健康,並使用一個專有的URL訪問,例如/health,當訪問/health時執行這個功能,然後返回對應結果。這裏要注意不能做鑑權,不然Probe就會一直失敗導致陷入重啓的死循環。
另外檢查只能限制在應用內部,不能檢查依賴外部的部分,例如當前web server不能連接數據庫時,這個就不能看成web server不健康。
Liveness Probe必須輕量。
Liveness Probe不能佔用過多的資源,且不能佔用過長的時間,否則所有資源都在做健康檢查,這就沒有意義了。例如Java應用,就最好用HTTP GET方式,如果用Exec方式,JVM啓動就佔用了非常多的資源。
零停機升級
產品總是在不斷迭代中的,SMAX也不會只有一個版本。在Kubernetes集羣中,如何升級應用程序,並且最小的宕機時間?
這裏不得不佩服Kubernetes的強大,已經爲我們提供了現成的解決方案,Rolling Update(滾動升級)。Kubernetes的Rolling Update提供了兩個參數maxSurge和maxUnavailable來控制滾動升級的速度,不同的速度會導致不同的現象。
創建一個額外的Pod(新),然後刪除一箇舊的Pod(maxUnavailable = 0,maxSurge = 1)
假設我們有3個Pod,此配置允許在原有Pod的數量之上添加一個額外的Pod(maxSurge = 1),而可用Pod的數量不能低於3(maxUnavailable = 0)。此種配置保證了在新的Pod還沒有正常提供服務時,依然會有舊的Pod存在,舊的Pod依然可用對外提供服務。但這種配置,在保證宕機時間的同時,也對應用程序提出了新的挑戰,新舊Pod必須保證前後兼容。還有一個缺點就是更新Pod慢。

4e3295c385fea903058965fc2285f965.png


刪除一個Pod,然後添加一個新的Pod(maxUnavailable = 1,maxSurge = 0)
此配置不允許創建額外的Pod(maxSurge = 0),但允許有一個Pod不可用(maxUnavailable = 1)。在這種配置下,Kubernetes將首先停止一個Pod,然後再創建一個新的Pod。這種配置的主要好處是,不需要額外的計算資源,畢竟多創建一個Pod就是多一份計算資源消耗。

31f1b4ca397789d18724c6b41671a933.png


儘可能快地更新Pods(maxUnavailable = 1,maxSurge = 1)
此配置允許在額外創建一個Pod(maxSurge = 1)的同時,允許有一個Pod不可用(maxUnavailable = 1)。第三種配置結合了以上兩種配置的優缺點,極大地減少了更新Pod的時間。

090521a0663b6a8853852c5682ffc1be.png


這三種配置方式在我們SMAX產品中都存在,關鍵是結合自身選擇最適合自己的配置方式。
以上就是我們產品SMAX的微服務遷移之路,想必每家公司的遷移之路都是不同的,全盤照搬是行不通的,要結合自身的行業屬性,公司組織架構,人員配置,現有技術架構,不斷地做權衡,設置優先級。完美的技術架構不可能是一步到位,需要不斷地演進迭代。
伴隨着微服務的改造,部署集羣、測試等變得異常複雜,因此需要一種新的技術理念,提高工作效率,DevOps應運而生。DevOps是一種方法,它使開發人員和運維人員能夠更緊密地協作,從而更快地交付高質量的軟件。


DevOps

28a36f4995867f5212f6d5f4645419ca.png


Pipeline
對於構建一個微服務集羣來說,這是一個龐大而複雜的集成與交付步驟,如果這些步驟依然停留在手工操作的階段,將嚴重拖慢“快速交付”的理念。通過Jenkins pipeline實現持續集成和持續交付(CI/CD)管道,完成自動化構建、測試和部署應用程序。
在開發和運維人員之間架起一座橋樑,方便開發人員快速驗證新代碼功能,保證質量。
在Pipeline方面,我們自研了很多的工具包,比如在2017年的時候,還沒有kubeadm,我們自己開發了一套程序,可以做到快速的創建Kubernetes集羣,並將整個SMAX集羣部署其上,一切只需一條指令,大大節約了開發測試人員部署環境的時間。
性能測試
目前我們使用LoadRunner對整個集羣進行壓力測試,當前我們大約有50個關鍵事務(Transactions)用於壓力測試,這50個關鍵事務基本涵蓋了SMAX的核心功能。並且我們還有150個非關鍵事務處於開發調試階段,力求對SMAX進行更完整全面的壓力測試。未來我們依然會不斷擴充我們的事務數量用於壓力測試。
我們將上一次發佈版本的測試結果作爲基準線,計算此次壓力測試的結果,性能是否有提升,還是衰退。通常如果有10%左右的性能衰退,我們就會引起警覺,花時間花人力進一步分析原因。參考LoadRunner的測試報告和其他的監控報告,幫助我們更快的定位問題。

fd5f3d77e2897d41285500deecef91b8.png


監控
當前我們從虛擬機和Kubernetes的兩個角度來監控整個集羣。虛擬機監控可以給到我們一個整體的性能報告。Kubernetes集羣監控可以更具體到各個Pod的性能報告。
虛擬機監控,我們使用了Zabbix監控整個集羣的硬件使用率,比如CPU,Memory,磁盤IO等。這些參數相對來說還是比較粗略的查看集羣的整體狀態,但可以給到我們一個比較直觀的整體性能趨勢報告。當某些性能指標出現異常(超平均的5% - 10%)時,我們能快速的發現問題,然後採取措施,進一步分析問題。是否是新代碼的引入導致了性能問題?

96db0cc177eb80cbb058ef7e266679d3.png


Kubernetes集羣監控,利用Prometheus+Grafana搭建監控系統,我們可以很直觀的看到Pod的運行狀況,何時Pod的CPU和Memory處於高負載階段,高負載的持續時間是否和LoadRunner壓力測試的時間片吻合,如果不吻合,我們需要進一步分析導致高負載的原因。如果高負載的百分比大於平均值,也同樣需要引起警覺,可能是一個性能下降的信號。

28a36f4995867f5212f6d5f4645419ca.png


GitOps
GitOps要求在版本控制軟件中(如GitHub,GitLab和Bitbucket),使用聲明性規範(比如yaml文件)存儲系統所需的狀態,這樣對整個系統的改動,都是可審計跟蹤的,每一個改動都包含了提交時間、提交者,這意味着基礎設施可以和應用程序一樣做到版本化。
在Kubernetes中,所有的Kubernetes資源都是以聲明性規範(yaml文件)的方式來創建的。對聲明性規範的修改,Kubernetes會負責將集羣的最終狀態保持和聲明性規範一致。
GitOps正是利用了Git的版本化和Kubernetes的聲明性規範來描述、創建和觀察整個系統,開發和交付基於Kubernetes的基礎設施和應用程序的模型規範。
如果從CI/CD的角度來理解GitOps,那麼每次的Pull Request被合併到主分支就是CI,CD意味着Kubernetes用Pull Request的文件改動來更新自己的Kubernetes集羣。
我們運用GitOps的理念,爲DevOps團隊提供基礎設施,如Jenkins instance,PostgreSQL數據庫、Prometheus和Grafana等。
在DevOps方面,我們還有很多需要做的,比如,自動伸縮,流量監控,日誌鏈路追蹤。我們已經在開始嘗試一些POC(Proof of Concept,驗證性測試),相信不久的將來,我們的所有嘗試都可以給客戶帶來真正的商業價值。


總結

28a36f4995867f5212f6d5f4645419ca.png


架構總是處在不斷演化的過程中,我們不會停止對新技術的探索,用更好的技術服務未來更復雜的業務需求,快速實現商業價值。
Q&A

a34058500f363c6569c1e576a6040ab7.png


Q:團隊敏捷,最重要的是什麼?團隊最成功是那一part?
A:我認爲團隊敏捷最重要的應該是團隊文化,要真正的是一個團隊,大家萬衆一心,不要搞小集體,大家目標統一了就更容易辦成一件事情。舉個例子,在我們團隊中是如何培養團隊文化的?每個人團隊中總會有1-2個樂於分享,專研技術的人,我們可以定期搞一些內部技術分享,小型的,時間也不用太長。慢慢的培養大家的極客精神,由1-2個人帶動整個團隊。以上是對某個具體團隊,我認爲最重要的事情。如果上升到整個產品部門或整個公司,我認爲管理層的百分比支持也沒關鍵,要有一條路走到黑的魄力。我們團隊最成功的部分,我認爲也就是我們團隊的文化,樂於分享,我也希望這個文化可以一直保持下去。
Q:業務升級時,Kubernetes通過滾動升級策略,保證了最大在線Pod數。那請問,單個Pod如何保證流量的平滑,比如在postStart階段會做哪些檢查?
A:這個要看你Pod的具體業務是否是有狀態,比如session信息等。新老Pod是否可以共存,同時提供服務。Pod提供的是在線服務還是離線服務。然後在決定在Pod生命週期的哪些階段做哪些事情。如果我們按最簡單的說:
  • 新老Pod可以共存,並且Pod提供的是離線服務。那麼在preStop階段可以先把老Pod的readiness置 爲false,這樣新的請求就到新的Pod上去了,然後等老Pod做完已有的離線服務就Terminate。

  • 如果說新老Pod可以共存,但不能同時提供服務,可能需要考慮藍綠部署,通過Service的label selector來切換流量。

  • 如果在複雜的情況,我需要更多的信息,具體分析。相對應的,代碼需要做的事情也會更多。我們可以羣內詳聊。


Q:服務拆分過程中需要注意的點有哪些?微服務架構的配置問題?舊服務集羣化需要注意的點有哪些?新舊服務之間的網絡是否可以互通,如果不互通如何解決?
A:個人認爲服務拆分的注意點可以從“管理”和“技術”來說:
  • 管理層面,服務拆分後和現有組織架構的衝突問題如何解決,這裏管理層必須要有打破舊有格局的決心,但適時的妥協不可避免。

  • 技術層面,還是根據業務來拆分,同一業務或相似業務儘量拆分在同一團隊,這樣業務知識至少不用跨團隊。先做一個大的拆分,不是那麼細的拆分,嘗試一下,然後在根據業務,由團隊決定繼續拆分,可能會有一個大的團隊變成兩個小的團隊。


在Kubernetes中可以使用ConfigMap和Secrets做配置,但如果是複雜應用,也可以使用開源的一些配置中心。舊服務集羣化的注意點,這個問題有點大,基本今天分享的所有內容都是注意點,到時會整理成文章發佈,可以關注一下。Kubernetes是可以和外部系統互通的,比如使用externalService。如果不互通,是否可以嘗試使用Proxy等技術使其互通。
Q:使用Kubernetes來管理微服務會帶來一些好處當然也會帶來一些複雜度,比如容器平臺本身維護的複雜度,你們是從哪些方面來權衡最終使用Kubernetes來管理微服務?
A:一個是自身業務的複雜度,如果業務簡單,完全沒必要使用Kubernetes。如果自身業務複雜,必然需要一個功能全面的容器編排平臺,比如Kubernetes。甚至一些更復雜的業務,都會基於Kubernetes做二次開發。二是CNCF,雲原生技術的推廣,這些技術都是圍繞Kubernetes的,社區的幫助也很重要,減少了自研的投入。
Q:你們的基礎設施是自己公司的私有云還是用的公有云?在基礎設施選擇上你們會用公有云去簡化基礎設施的投入,而把注意力都放在軟件研發上嗎?
A:我們有線下機房,同時也支持部署在雲端,比如Amzon EKS,Auzre AKS,GCP,阿里雲。最近在嘗試部署到OpenShift。其實我們是企業級應用,屬於賣軟件產品,最終部署在哪裏?on-premise,私有云還是公有云是由客戶自己決定的。所以每個平臺我們都需要支持。但我們也有自己的SaaS服務是部署在AWS上,簡化了基礎設施的投入和維護成本。

































































































發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章