Advacned Puppet: Puppet Master性能調優

本文是Advanced Puppet系列的第一篇:Puppet master性能調優,談一談如何優化和提升C/S架構下master端的性能。html

故事情節每每驚人地相似:你是一名使用Puppet管理線上業務的DevOps工程師,隨着公司的業務發展,你所管理的集羣規模日益擴大。終於某一天,你忽然發現執行一次puppet agent -vt的時間長得不可接受,多臺agent併發運行時居然會有節點運行失敗,往日曆來沒有考慮過Puppet的性能竟然成爲了瓶頸……首先要恭喜你,由於Puppet Master端的性能瓶頸只有在集羣發展到必定規模時纔會遇到。前端

 

Tuning

    圖1 性能調優node

籠統地去談系統的性能調優,是一個泛泛的話題,陳皓在他的《性能調優攻略》中介紹了系統性能的定義和如何定位性能瓶頸。所以,本篇把討論範圍縮小:只關注master端的性能調優,而不涉及Puppet代碼的執行效率調優,部署邏輯的調優等等。git

咱們要對Puppet進行優化前,首先要清楚它有哪些瓶頸。對Puppet的C/S架構全部瞭解後,咱們把它歸類到Web服務: puppet agent端向puppet master發送請求,puppet master端處理請求並返回結果。web服務常見的性能度量指標是響應時間,系統吞吐量,系統資源利用率,併發用戶數等。那麼在這裏咱們主要關注兩個指標:響應時間和併發用戶數。所以,在對Puppet Master進行調優前,須要瞭解agent端和master端是如何交互的。web

image圖2 Puppet C/S架構下的處理流程圖shell

從圖2能夠看到一次完整的agent請求catalog的具體流程,Agent和Master之間的交互能夠分爲三步:數據庫

      1. agent先向master發送一個請求,但願獲取本身的catalog;apache

      2. Master端經過agent附帶的fqdn,environment等facts信息判斷節點的分類,隨後對其所屬的class,define等資源進行編譯;處理完成後把catalog以json格式返回給agent端;json

      3. Agent端拿到catalog後先作一個本地的狀態查詢,而後進行收斂達到預期的狀態,完成後發送一個本次執行概況的report給Master端後端

 

ok,那咱們來看一下實際的運行結果是如何的:以一臺RabbitMQ節點向PuppetMaster發起一次執行操做爲例,先分析Server端的訪問日誌有哪些操做:

10.0.1.45 - - [15/Aug/2014:23:31:50 -0400] "GET /production/node/server-45.1.test.ustack.in? HTTP/1.1" 200 4473 "-" "-" 0 
10.0.1.45 - - [15/Aug/2014:23:31:50 -0400] "GET /production/file_metadatas/plugins?links=manage&recurse=true&checksum_type=md5&ignore=.svn&ignore=CVS&ignore=.git HTTP/1.1" 200 149510 "-" "-" 0 
10.0.1.45 - - [15/Aug/2014:23:31:52 -0400] "POST /production/catalog/server-45.1.test.ustack.in HTTP/1.1" 200 305052 "-" "-" 7 
10.0.1.45 - - [15/Aug/2014:23:32:03 -0400] "GET /production/file_metadata/modules/rsyslog/rsyslog_default?links=manage HTTP/1.1" 200 317 "-" "-" 0 
10.0.1.45 - - [15/Aug/2014:23:32:03 -0400] "GET /production/file_metadata/modules/ssh/sshd_config?links=manage HTTP/1.1" 200 309 "-" "-" 0 
10.0.1.45 - - [15/Aug/2014:23:32:04 -0400] "GET /production/file_metadata/modules/ssh/ssh_config?links=manage HTTP/1.1" 200 308 "-" "-" 0 
10.0.1.45 - - [15/Aug/2014:23:32:04 -0400] "GET /production/file_metadatas/modules/mcollective/site_libdir?links=manage&recurse=true&checksum_type=md5 HTTP/1.1" 200 650 "-" "-" 0 
10.0.1.45 - - [15/Aug/2014:23:32:04 -0400] "GET /production/file_metadatas/modules/mcollective/plugins/actionpolicy?links=manage&recurse=true&checksum_type=md5 HTTP/1.1" 200 1740 "-" "-" 0 
10.0.1.45 - - [15/Aug/2014:23:32:07 -0400] "GET /production/file_metadata/modules/logrotate/etc/logrotate.conf?links=manage HTTP/1.1" 200 322 "-" "-" 0 
10.0.1.45 - - [15/Aug/2014:23:32:07 -0400] "GET /production/file_metadata/modules/logrotate/etc/cron.hourly/logrotate?links=manage HTTP/1.1" 200 329 "-" "-" 0 
10.0.1.45 - - [15/Aug/2014:23:32:07 -0400] "GET /production/file_metadata/modules/logrotate/etc/cron.daily/logrotate?links=manage HTTP/1.1" 200 328 "-" "-" 0 
10.0.1.45 - - [15/Aug/2014:23:32:07 -0400] "PUT /production/report/server-45.1.test.ustack.in HTTP/1.1" 200 11 "-" "-" 0

再來看agent端的輸出日誌:

time puppet agent -vt 

Info: Retrieving plugin
Info: Caching catalog for server-45.1.test.ustack.in 
Info: Applying configuration version '1408154486' 
Notice: Finished catalog run in 4.57 seconds

real    0m17.579s 

所謂catalog的編譯,實質上是生成一個資源執行的有向狀態圖,是一個消耗CPU和磁盤IO資源的計算操做。在一次沒有任何變動操做的狀況,Puppet在分類和編譯catalog上花費了整整11秒的時間,而做爲文件服務器向agent端提供文件下載只花費了4秒,那麼咱們能從哪些方面來縮短master的響應時間?首先咱們要分析慢在哪裏,有哪些可能的緣由會致使運行速度慢?

 

1. 升級軟件版本

根據個人交流發現有很多公司仍在使用2.x版本的puppet,尤爲以2.7.x居多。由於在Ubuntu/CentOS下,使用默認源安裝的puppet版本就是2.7(6).x。根據官方的3.x Release Note,3.x的性能相比2.x相比有很是顯著的提高,尤爲是與2.7.x相比有50%的提高,咱們目前使用的Puppet版本是3.3.1,實測結果是:相比2.7.14,總體的執行速度約提高了30%(與具體的部署邏輯相關)。

升級帶來另一個重要的問題:兼容性。咱們知道把一個項目從Python2.7升級到Python3.4是一個很是困難的事情,某些語法的變動,最讓人頭疼的是大量的第三方庫並不支持3.x。可是從Puppet 2.7(6).x升級到3.x你不須要太擔憂兼容性問題,由於絕大多數的puppet modules支持3.x的puppet語法規範。可能須要變更的是你本身編寫的模塊,例如模板,變量的命令空間等一些變更,而且這些兼容性問題只是以warning的形式提醒你進行修改。

 

2. 設置客戶端合理的運行間隔

經常有很多同窗喜歡把puppet agent端的運行間隔runinterval參數設置得很短,例如180s甚至60s。他們但願經過這種不停運行agent的方式,一是可以替代主動推送的需求,二是能夠作到當服務意外中止,配置文件被人爲修改後,能夠儘快地恢復。這些想法並不能知足上述需求。

首先,推和拉是兩個不一樣的操做模式,若以頻繁的被動拉取節點配置來替代主動推送帶來了幾個問題:

    1. 無心義地浪費server端的性能,從前面的數據中能夠得知編譯catalog是一個很是耗資源的操做;

    2. 線上的一切變動均屬於嚴肅的變動流程,須要主動地控制升級策略,例如兩個web服務節點的升級流程,先得把web-01從lb背後摘下,進行變動,而後再從新上線,接着對web-02作一樣的操做,拉模型明顯不符合這樣的部署需求;

    3. 服務監控屬於監控體系來管理,讓puppet來作,愛莫能助;

一個合理的runinterval值應該根據集羣的規模來進行調整,官方的推薦值是1800s。

 

3.設置Splay避免驚羣效應

舉個簡單的例子,當你往一羣鴿子中間扔一塊食物,雖然最終只有一個鴿子搶到食物,但全部鴿子都會被驚動來爭奪,沒有搶到食物的鴿子只好回去繼續睡覺, 等待下一塊食物到來。這樣,每扔一塊食物,都會驚動全部的鴿子,稱爲驚羣。對於PuppetMaster來講,多個puppetmaster進程在等待CPU和IO資源時也會產生相似的狀況。

在搭建內部開發環境的初期,我對puppet agent的運行間隔設置隨意設置了一個較短的值:300s。本覺得大功告成,可是當集羣規模增長了一倍後,我發現agent從Puppet Master獲取一次catalog的時間超過了個人預期。經過分析apache日誌我才發現,全部節點幾乎在同個時間段向這臺可憐的PuppetMaster發出了請求,瞬間把這臺運行在hypervisor上的master的CPU資源跑滿。解決這個問題的辦法就是設法錯開Agent的拉取時間點,puppet默認提供了splay參數來知足這個需求。

你須要在每臺agent節點的puppet配置文件中,添加:

splay = true

還有一個splaylimit參數,若不設置則默認會取runinterval的值。Puppet agent每次會在runinterval的基礎上,增長0~splaylimit(秒)間的隨機值後再運行,大大下降了agent同一時刻運行的機率。

 

4.棄用Webrick

不少同窗喜歡使用ruby自帶的webrick webserver來啓動puppetmaster服務,由於簡單方便。例如:

service puppetmaster start

首先,你要明白一點的是這些語言的內置webserver目的僅是爲了方便調試代碼,是根本不能放到生產環境去使用。

使用WebRick運行的Puppetmaster性能有多差?

僅9個併發請求就能把它拖垮。

我在在一臺E5 2620的服務器上試驗:只要9個puppet agent同時向運行在webrick上的puppet master發送請求,就處理不過來了,你會發現總有某臺agent會出現40x Error的錯誤。

要提升單臺Puppetmaster的性能很簡單,只要使用常見的Web Server軟件就能夠顯著地提升Puppet master的性能,例如Apache,Nginx等。這類文檔不少,這裏就再也不詳細說明配置的步驟了。

 

5.禁止使用activerecord + SQL做爲Storeconfigs Backend

當你在開啓了storeconfigs來使用Puppet的一些高級特性時,請注意不要使用activerecord + SQL的組合做爲其後端存儲。這對組合經常在2.x版本中出現得比較多,由於那時它的替代品PuppetDB尚未成熟,咱們也曾經使用了近一年的ActiveRecord + MySQL的方式來作後端存儲,它的目的就是把生成的catalog,facts等等都存到數據庫中,其性能就是慢,慢,慢。去年咱們在作私有云項目時,起初部署一臺控制節點,居然要30分鐘!慢到老大一度想要用shell腳本去取代puppet,一度讓我想把代碼中全部高級特性所有禁用。我不得不尋求其餘替代技術來改善storeconfigs的運行效率。

Puppet 3.x升級的另外一個特性就是把這些老古董標記爲棄用,當時社區推出了PuppetDB + PostgreSQL的新組合,其目的就是爲了替代它們的。在執行存儲和查詢操做時,性能上提高不止快了一倍,最終交付給用戶的時候,部署時間降低到了18分鐘。不過,我已經忘記把測試對比數據丟哪了,多是隨ActiveRecord + MySQL一塊兒丟了 :D。

 

6. 橫向擴展Puppet集羣

通過上述的優化後,你經過觀察CPU負載發現單臺Puppet已沒法管理當前的集羣規模時,能夠對Puppet進行橫向擴展。web服務的性能擴展較爲容易,經過簡單地增長puppet master節點的數量就能輕鬆地提升處理能力。在前端放置七層負載均衡,用於處理SSL認證和轉發請求。如何搭建Puppet集羣,如何在前端設置七層負載均衡的配置過程,我以前已寫過相關的文章,也能夠經過網上找到相應的資料。

 

 

image

圖3 Puppet集羣的典型架構圖

 

7. 縱向擴展與橫向擴展PuppetDB服務

當你選擇使用PuppetDB做爲storeconfigs的組件時,那麼PuppetDB將是Puppet部署中的重要組件,若是PuppetDB掛了,那麼agent節點將沒法獲得catalog。PuppetDB節點是屬於典型的耗CPU,耗內存,耗磁盤IO的資源使用大戶。下面咱們來看看實際使用中可能會遇到的瓶頸以及解決辦法。

image 圖4 PuppetDB性能監控面板

7.1 數據庫的性能瓶頸

PuppetDB主要做用是存儲和查詢catalog,facts和reports,其主要瓶頸主要在於後端PostgreSQL的讀寫性能,咱們不可能花費精力去作PG的性能調優,須要找一種廉價的方式來提升性能。個人老大經常教育我,若是錢能解決的問題,那都不是事兒。所以若經過縱向擴展就能解決問題,實際上是一種很是經濟的手段:D。所以在生產環境中,推薦使用企業級的SSD盤去替代SATA盤,不然隨着集羣規模的增長,大量的隨機讀寫操做會讓PostgreSQL慢如蝸牛。

 

7.2 Java Heap大小的瓶頸

在使用PostgreSQL的狀況下,分配128MB內存做爲基礎,而後根據集羣的規模來增長額外的內存配置,原則是爲每一臺puppet node分配1M內存。而後經過觀察PuppetDB的性能檢測面板再進行適當地調整。修改方式是編輯puppetdb的啓動腳本,修改JAVA_ARGS參數,爲其分配2G內存:

JAVA_ARGS="-Xmx2g"

 

7.3 PuppetDB worker進程數的瓶頸

PuppetDB能夠有效利用多核來處理其隊列中的請求,每一個核能夠運行一個worker進程,PuppetDB默認只會運行該臺機器一半核數的worker。所以,當你發現PuppetDB的性能監控面板上queue depth值長時間不爲0時,你就須要配置更多的worker數。

                  圖5 Command Queue 監控圖

那若是單臺PuppetDB不能知足需求了,如何處理? 那就須要橫向擴展PuppetDB,構建PostgreSQL集羣,其實大可沒必要如此憂愁。Puppetlabs官方給出的數據是使用一臺2012年的筆記本 (16 GB of RAM, consumer-grade SSD, and quad-core processor)運行PuppetDB和PostgreSQL足以支撐8000臺Puppet nodes每30分鐘一次的運行。

 

8 總結

    本篇中,咱們前後從軟件版本的升級,相關參數的調整,選擇Web服務器做爲容器,橫向擴展,縱向擴展,後端存儲的替換等多個方面考慮去提升Puppetmaster端的性能,具體到生產環境中,實際狀況會全部不一樣,可是方法都是相同的:分析問題本質,找出問題所在,肯定合理的優化方案。

相關文章
相關標籤/搜索