2017年11月13日

Graphite

Graphite 可以即時收集、儲存、顯示時間序列類型的資料,由 Carbon, Whisper, Graphite-Web 三個元件組成的,其中 Graphite-Web 可用 Grafana 取代。

Graphite 是由三個元件組成的

  1. Carbon: 是一個 Twisted daemon,負責接受 Time Series Data 資料,把資料暫存到記憶體中

  2. Whisper: Graphite 專用的類似 RRD 的 database,儲存時間序列資料的小型資料庫

  3. Graphite-Web: 用 Django 實作的網頁介面,可用 Grafana 取代

安裝

如果直接要用 Docker 測試 Graphite 可參考 Docker image 網頁s Official Docker image for Graphite

用以下指令啟動 graphite docker container

docker run -d\
 --name graphite\
 --restart=always\
 -p 80:80\
 -p 2003-2004:2003-2004\
 -p 2023-2024:2023-2024\
 -p 8125:8125/udp\
 -p 8126:8126\
 graphiteapp/graphite-statsd
Port Service Usage
80 nginx reverse proxies the graphite front-end dashboard
2003 carbon receiver - plaintext backend
2004 carbon receiver - pickle
2023 carbon aggregator - plaintext
2024 carbon aggregator - pickle
8125 (UDP) statsd UDP based backend proxy
8126 statsd admin

如果要直接用 pip 安裝,參考 Installing From Pip 的文件,可用以下的程序。

首先參考上面的 port 對應,先啟動一個測試的 centos docker node,只安裝了 sshd。(note: TCP Port 3000 是給 grafana 使用的)

docker run -d \
 -p 10022:22\
 -p 80:80\
 -p 2003-2004:2003-2004\
 -p 2023-2024:2023-2024\
 -p 8085:8085\
 -p 8125:8125/udp\
 -p 8126:8126\
 -p 3000:3000\
 -e "container=docker" --privileged=true -v /sys/fs/cgroup:/sys/fs/cgroup --name graphitetest centosssh /usr/sbin/init

用以下指令安裝 graphite,安裝目錄為預設的 /opt/graphite

yum groupinstall -y "Development Tools"
yum install -y python-devel cairo-devel libffi-devel

yum install -y epel-release
yum install -y git
yum install -y python-pip
pip install --upgrade pip

pip install twisted


export PYTHONPATH="/opt/graphite/lib/:/opt/graphite/webapp/"
pip install --no-binary=:all: https://github.com/graphite-project/whisper/tarball/master
pip install --no-binary=:all: https://github.com/graphite-project/carbon/tarball/master
pip install --no-binary=:all: https://github.com/graphite-project/graphite-web/tarball/master

安裝完成後, whisper 安裝在 /usr/bin,carbon 跟 graphite-web 安裝在 /opt/graphite/

bin/
conf/
lib/
    Carbon PYTHONPATH
storage/
    log/
    rrd/
    whisper/        whisper 存放資料的目錄
    ceres/          ceres 存放資料的目錄
webapp/         Graphite-web PYTHONPATH
    graphite/       local_settings.py 的位置
    content/        static content 目錄

設定及啟動

先由設定檔範例複製一份設定檔

cd /opt/graphite/conf/

sudo cp storage-schemas.conf.example storage-schemas.conf  
sudo cp storage-aggregation.conf.example storage-aggregation.conf  
sudo cp graphite.wsgi.example graphite.wsgi  
sudo cp graphTemplates.conf.example graphTemplates.conf  
sudo cp carbon.conf.example carbon.conf

mkdir backup
mv *.example backup/

cd /opt/graphite/webapp/graphite/   
sudo cp local_settings.py.example local_settings.py 
Webapp Database

在 /opt/graphite/webapp/graphite/local_settings.py 中,有一部分 Database Configuration,這是要讓 Django 產生Graphite 使用的資料庫,用來儲存 user profiles, dashboards, and for the Events functionality。

預設使用 /opt/graphite/storage/graphite.db 這個 sqlite 資料庫,可改成 PostgreSQL or MySQL。

vi /opt/graphite/webapp/graphite/local_settings.py

# 修改 Timezone
TIME_ZONE = 'Asia/Taipei'

# 修改 database
DATABASES = {
    'default': {
        'NAME': '/opt/graphite/storage/graphite.db',
        'ENGINE': 'django.db.backends.sqlite3',
        'USER': '',
        'PASSWORD': '',
        'HOST': '',
        'PORT': ''
    }
}

產生 graphite.db

cd /opt/graphite
export PYTHONPATH="/opt/graphite/lib/:/opt/graphite/webapp/"

django-admin.py migrate --settings=graphite.settings --run-syncdb

local_settings.py 的其他設定值,可參考文件 Graphite-web’s local_settings.py

Carbon

carbon 主要的設定檔為 /opt/graphite/conf/carbon.conf,設定檔分為多個區塊,每一個區塊對應到不同的 daemon,例如 [cache] 設定 carbon-cache,[relay] 設定 carbon-relay,[aggregator] 設定 carbon-aggregator。

可增加新的 cache 區塊,就會多一個 carbon-cache process,名稱為 b,Port 為 2004

[cache:b]
LINE_RECEIVER_INTERFACE = 0.0.0.0
LINE_RECEIVER_PORT = 2004
CACHE_QUERY_INTERFACE = 0.0.0.0
CACHE_QUERY_PORT = 7003

在 /opt/graphite/bin 資料夾中,可找到以下三種不同類型的 Carbon daemon

  1. cache:接受通過各種協議傳輸來的指標項數據並以儘可能高的效率將它們寫入磁盤;在接收到指標項時,將指標項值緩存在RAM中,並用底層的Whisper庫按照指定的時間間隔將這些值寫入 disk
  2. Relay:有兩個不同的用途,可複製並分區輸入的指標項。
  3. Aggregator:運作於 cache 前方,在 Whisper 記錄指標項前,緩存這些指標項一段時間。

有兩種方式啟動 carbon daemon

  1. 用 script 啟動 carbon daemon

    ## start
    cd /opt/graphite/bin
    ./carbon-cache.py start
    
    ## stop
    ./carbon-cache.py stop

    啟動後會出現

    Starting carbon-cache (instance a)

    可用 ps 及 netstat 查詢狀況

    # ps -efla | grep carbon-cache
    1 S root     12473     1  0  80   0 - 55806 -      07:42 ?        00:00:00 /usr/bin/python2 ./carbon-cache.py start
    0 S root     12476   196  0  80   0 -  2663 -      07:42 pts/0    00:00:00 grep --color=auto carbon-cache
    
    # netstat -nap | grep 2003
    tcp        0      0 0.0.0.0:2003            0.0.0.0:*               LISTEN      12473/python2
  2. 利用 system service 啟動 carbon service

    vi /usr/lib/systemd/system/carbon.service
    
    [Unit]
    Description=Graphite Carbon Daemon
    
    [Service]
    Type = forking
    GuessMainPID = false
    PIDFile = /opt/graphite/bin/carbon-cache-a.pid
    ExecStart=/opt/graphite/bin/carbon-cache.py start --pidfile /opt/graphite/bin/carbon-cache-a.pid
    ExecReload=/bin/kill -HUP $MAINPID
    KillMode=process
    Restart=on-failure
    RestartSec=42s
    
    [Install]
    WantedBy=multi-user.target

    起動 carbon service

    chmod 755 /usr/lib/systemd/system/carbon.service
    # reload carbon.service
    systemctl daemon-reload
    
    # enable
    systemctl enable carbon
    
    # start carbon service
    systemctl start carbon
    
    # stop carbon service
    systemctl stop carbon

/opt/graphite/conf/storage-schemas.conf

記錄儲存 metrics 的 retention rates,以 pattern 的方式比對 metric paths,並告訴 whisper 該用什麼頻率儲存 datapoints 以及處理歷史資料。

  1. 設定檔中有多個設定區塊
  2. pattern 比對由上至下依照順序比對,使用第一個符合的 pattern 的 metric name 的規則
  3. pattern 為 regular expressions
  4. 在發送第一個 metric 時,就決定了儲存資料的 retention 方式
  5. 如果修改這個設定檔,並不會改變已經產生的 .wsp 檔案,除非要用 whisper-resize.py 套用那些設定

預設內容為

[carbon]
pattern = ^carbon\.
retentions = 60:90d

[default_1min_for_1day]
pattern = .*
retentions = 60s:1d

每一個區塊的規則有三行

  1. [name] 區塊名稱
  2. pattern regular expression
  3. retentions = frequency:history 可有多個 frequency:history retention rate,中間用逗點隔開

ex1: each datapoint represents 10 seconds,只儲存 14 天的資料

[garbage_collection]
pattern = garbageCollections$
retentions = 10s:14d

ex2: metric scheme 為 servers..

[apache_busyWorkers]
pattern = ^servers\.www.*\.workers\.busyWorkers$
retentions = 15s:7d,1m:21d,15m:5y

有多個 retention 設定,最前面的是 most-precise:least-history,最後面的是 least-precise:most-history,whisper 會自動處理 downsample metrics (預設為 averaging)。為求資料正確,least-precise 必須要能被 most-precise 的時間間隔整除。

retentions = 15s:7d,1m:21d,15m:5y
1m = 60s, 60/15 = 4 (ok)
retentions = 180s:7d,300s:30d

300/180 = 3.33 (invalid)

ex3: default1minfor_1day 因為 pattern 設定為 .* ,必須放在最後面,中間的設定分別是給 statsd 及 collected 使用

[carbon]
pattern = ^carbon\.
retentions = 60:90d

[stats]
pattern = ^stats.*
retentions = 10s:6h,10m:7d,1d:5y

[stats_counts]
pattern = ^stats_counts.*
retentions = 10s:6h,10m:7d,1d:5y

[collectd]
pattern = ^collectd.*
retentions = 10s:6h,10m:7d,1d:5y

[default_1min_for_1day]
pattern = .*
retentions = 60s:1d

retentions 也可設定為 seconds-per-datapoint:count-of-datapoints 這種格式

例如

retentions = 60:1440

60 代表 the number of seconds per datapoint,而 1440 代表 the number of datapoints to store


/opt/graphite/conf/storage-schemas.conf

設定如何 aggregate 資料為低精確度的 retention rate

預設內容為

[min]
pattern = \.min$
xFilesFactor = 0.1
aggregationMethod = min

[max]
pattern = \.max$
xFilesFactor = 0.1
aggregationMethod = max

[sum]
pattern = \.count$
xFilesFactor = 0
aggregationMethod = max

[default_average]
pattern = .*
xFilesFactor = 0.5
aggregationMethod = average
  1. xFilesFactor 必須為 0~1 之間的 floating point number,指定要如何切割前一個 retention level slot,切割後必須要有 non-null values,這樣才能 aggregate 為 non-null value。
  2. aggregation Method,指定如何 aggregate values,可使用 average(預設), sum, min, max, last
  3. 在發送第一個 metric 時,就決定了這個設定值
  4. 如果修改這個設定檔,並不會改變已經產生的 .wsp 檔案,除非要用 whisper-set-aggregation-method.py 套用那些設定,例如: /opt/graphite/bin/whisper-set-aggregation-method.py /opt/graphite/storage/whisper/test.wsp max

ex1: pattern 是以 .min 結束的 metric,xFilesFactor 設定為 10% of the slots,前一個 retention level 中,最少要有 10% 的 datapoints,這樣才能 aggregate 到下一個 retention level

[all_min]
pattern = \.min$
xFilesFactor = 0.1
aggregationMethod = min

/opt/graphite/conf/relay-rules.conf

可將某些 metrics 轉送給特定的 backend,這是由 carbon-relay 這個 daemon 處理的

ex:

[example]
pattern = ^mydata\.foo\..+
servers = 10.1.2.3, 10.1.2.4:2004, myserver.mydomain.com

aggregation-rules.conf

可在收到資料時,將某些 metrics 合併在一起。


rewrite-rules.conf

利用 regular expression,修改 metric name

graphite-web
  • 用 script 啟動 graphite-web
cd /opt/graphite

export PYTHONPATH="/opt/graphite/lib/:/opt/graphite/webapp/"

./bin/run-graphite-devel-server.py --port=8085 --libs=`pwd`/webapp /opt/graphite 1>/opt/graphite/storage/log/webapp/process.log 2>&1 &
  • 用 service 啟動
vi /usr/lib/systemd/system/graphite.service

[Unit]
Description=Graphite web daemon

[Service]
Environment=PYTHONPATH=/opt/graphite/storage/whisper
ExecStart=/opt/graphite/bin/run-graphite-devel-server.py --port=8085 --libs=/opt/graphite/webapp /opt/graphite
ExecReload=/bin/kill -HUP $MAINPID
KillMode=control-group

[Install]
WantedBy=multi-user.target
chmod 755 /usr/lib/systemd/system/graphite.service
# reload graphite.service
systemctl daemon-reload
    
# enable
systemctl enable graphite
    
# start graphite service
systemctl start graphite
    
# stop graphite service
systemctl stop graphite

log

tail -f /opt/graphite/storage/log/webapp/process.log

check web process

# ps -efla | grep graphite-devel-server
4 S root       415     1  2  80   0 - 35864 -      01:27 ?        00:00:00 /usr/bin/python2 /opt/graphite/bin/run-graphite-devel-server.py --port=8085 --libs=/opt/graphite/webapp /opt/graphite
0 S root       422   415  7  80   0 - 73878 -      01:27 ?        00:00:01 /usr/bin/python2 /opt/graphite/bin/run-graphite-devel-server.py --port=8085 --libs=/opt/graphite/webapp /opt/graphite
0 S root       437   198  0  80   0 -  2663 -      01:27 pts/0    00:00:00 grep --color=auto graphite-devel-server

網址為 http://localhost:8085

data in

有三種方式,可發送 metrics 資料給 graphite: Plaintext, Pickle, and AMQP。

這些工具 是能跟 graphite 一起運作的資料收集工具,有分為 collection, forwarding, visualization, monitoring, and Storage Backend Alternates 這些種類。

collection 要注意 collectd, diamond, forwarding 要注意 statsd, visualization 則是 grafana, Storage Backend Alternates 則是 ceres, InfluxDB

  • Plaintext Protocol

這是 carbon 支援的最基本的接收資料的方式。資料格式為

<metric path> <metric value> <metric timestamp>
echo "local.random.diceroll 4 `date +%s`" | nc localhost 2003
  • Pickle Protocol

pickle 是比較有效率的資料發送方式,可一次發送多個 metrics 資料。資料格式為

[(path, (timestamp, value)), ...]

pickle receiver port 預設為 TCP 2004,必須將 pickle 資料加上 header,封裝為以下這種格式的 message,才能發送給 pickle server

payload = pickle.dumps(listOfMetricTuples, protocol=2)
header = struct.pack("!L", len(payload))
message = header + payload
  • AMQP

如果 carbon.conf 的 AMQPMETRICNAMEINBODY 設定為 True,就支援跟 Plaintext 一樣的資料格式,ex: echo "local.random.diceroll 4 date +%s",如果設定為 False,就要省略 local.random.diceroll。

functions

Graphite Functions

  • url相關的函數:

url中可以帶有*,會選擇出多個 metrics:

&target=rest.getUser.count.*          
&target=rest.get*.count.succeeded     
&target=rest.getUser.count.{succeeded,failed}
&target=rest.server[1-20].getUser.count    

因為url中的每個 . 代表了一層目錄,所以不能用rest.* 選出 rest.getUser.count

  1. maxSeries,sumSeries,averageSeries: 將 * 代表的多個counter通過某個方式運算一個值。 ex: sumSeries(rest.getUser.count.*),將 * 代表的metrics 加總。

  2. groupByNode,url中有兩顆參數,將第1顆星星代表的多個Series組合,而第2顆代表的則分開來顯示。 groupByNode(ganglia.by-function...cpu.load5,2,"sumSeries"),第一顆星代表服務器,第2顆星代表服務器,此函數將顯示每台Server上所有函數的CPU總和。averageSeriesWithWildcards,sumSeriesWithWildcards也有類似的功能。

  3. aliasByNode,將 * 中的 metric 的名稱當做Alias,aliasByNode(rest.getUser.count.*, 1),alias就是succeeded或failed

  4. exclude,單獨去除某個 metric,exclude(servers*.threads,"server02") 就是只顯示某些 metric

  5. highestAverage,highestMax,只顯示值最高(還可以是最低)的幾個metrics。

  6. currentAbove,currentBelow,以last值(或是max,min,avg值)做條件過濾。

  7. asPercent,以幾個metrics相對的百分比來顯示。

  • 圖形相關的函數

  1. legendValue(rest.getuser.latency, 'avg', 'max'),圖形下面顯示數據的最大小值、平均值(可以是last, avg, total, min, max)

  2. threshold(60, "latency 60ms threshold","red"),在圖形裡顯示警戒線。

  3. consolidateBy(rest.getuser.latency, 'max'),如果看一週的曲線,圖上的每個點包含了多個datapoint的數據,不用本函數,默認行為是算平均值,可以用本函數設為取max,min,sum等。

  • 其他:

  1. summarize(rest.getuser.latency, "1min"),按1分鐘進行聚合而不是原來的10秒。聚合的方式默認是sum,也可以是avg,max,last。

  2. 將自增長的metric轉化為TPS: perSecond(rest.getuser.totalCount),但當前版本此函數好像不存在,一個解決方式是:scaleToSeconds(deriviative(rest.getuser.totalCount),1) ,第一個函數先算出兩個點之間的差值,第二個平均到每秒。

  3. integral(rest.getUser.count),顯示所有datapoint的逐漸累積值。

  4. hitcount, 將rate換算成totalCount,能跨越各種時間長度。

  5. Timeshift, 可以比較當前數值和一週前的數值(兩條線): &target=alias(summarize(rest.getuser.count, "1min"), "today")&target=alias(summarize(rest.getuser.count, "1min"),"1w"), "last week")。 movingAverage,幾個datapoint的移動平均值。

References

Step by Step Install of Graphite with Carbon and StatsD on CentOS 7.1.x

Graphite 部署實戰

使用 Statsd + Graphite 的 Monitoring 心得

DevOps實戰:Graphite監控上手指南

Practical Guide to StatsD/Graphite Monitoring

Graphite學習系列