数百台のサーバに対して
- CPU
- メモリ
- HDD
の使用状況をサクッとチェックしたいなーと思ったのですが、さすがにmuninのグラフで見るのはダルすぎる。
というわけで日次でこういうページを作ってチェックするようにしました。
上記の情報が数字でダーっと並んでて、ついでに簡単に色付けとか、muninへのリンク張りとか、各項目でのソート機能付けたりとかをやってます。
CPUとメモリの使用率は前日の平均、ディスク使用率はバッチ実行時の値です。
最初はmuninのRRDファイルから作ろうかと思ったのですが(gist)、この程度の情報ならsysstatやdfの結果から作るほうが簡単なので、sshで集めてくることにしました。
とりあえずHTMLに出力してますが、CSVで出したりDBに突っ込んだりすれば各種調査に便利ですよ!
ソースコード
Ruby1.9版です
#!/usr/local/bin/ruby require 'net/ssh' require 'json' require 'erb' require 'pp' server_list_file = "/home/mikeda/check_servers/sv.list" # このファイルに調査対象のホストを記載 erb_template_file = "/home/mikeda/check_servers/resource.html.erb" def summarize_cpu(sar_cpu) _, _, user, nice, system, iowait, steal, idle = sar_cpu.split(/\s+/) { user: user.to_f, nice: nice.to_f, system: system.to_f, iowait: iowait.to_f, steal: steal.to_f, idle: idle.to_f } end def summarize_memory(sar_memory) _, kbmemfree, kbmemused, memused, kbbuffers, kbcached, kbcommit, commit = sar_memory.split(/\s+/) mem = { kbmemfree: kbmemfree.to_i, kbmemused: kbmemused.to_i, memused: memused.to_i, kbbuffers: kbbuffers.to_i, kbcached: kbcached.to_i, kbcommit: kbcommit.to_i, commit: commit.to_f } total = ( mem[:kbmemfree] + mem[:kbmemused] ) / 1024 used = ( mem[:kbmemused] - mem[:kbbuffers] - mem[:kbcached] ) / 1024 { total: total, used: used, usage: (100 * used.to_f / total).to_i } end def summarize_disk(df) disk = {} df.split("\n").each do |d| filesystem, size, used, avail, usage, mount = d.split(/\s+/) disk[mount] = { filesystem: filesystem, size: size.to_i, used: used.to_i, avail: avail.to_i, usage: usage.chop.to_i } end # /varが個別にマウントされていればその情報、それ以外は/の情報を返す disk['/var'] || disk['/'] end servers = open(server_list_file).readlines.map(&:chomp) resources = {} YESTERDAY_SAR = "/var/log/sa/sa#{(Date.today - 1).strftime("%d")}" servers.each do |host| begin Net::SSH.start(host, 'mikeda') do |ssh| resources[host] = {} sar_cpu = ssh.exec!("LANG=C sar -f #{YESTERDAY_SAR} | tail -1") resources[host][:cpu] = summarize_cpu(sar_cpu) sar_memory = ssh.exec!("LANG=C sar -r -f #{YESTERDAY_SAR} | tail -1") resources[host][:memory] = summarize_memory(sar_memory) df = ssh.exec!("LANG=C df -lmP | sed 1d") resources[host][:disk] = summarize_disk(df) end rescue => e STDERR.puts "#{host}: #{e.message}" end end ### HTML出力用 def color(value, warn, critical) if value > critical 'red' elsif value > warn 'yellow' else '' end end def color_cpu_usr(usage); color(usage, 30, 60) end def color_cpu_sys(usage); color(usage, 5, 10) end def color_cpu_io(usage); color(usage, 5, 10) end def color_memory(usage); color(usage, 60, 80) end def color_disk(usage); color(usage, 60, 80) end puts ERB.new(File.read(erb_template_file)).result ### JSON出力用 #puts JSON.pretty_generate(resources)
とりあえずコイツをcronで毎日実行してます
7 7 * * * /home/mikeda/check_servers/check_server_resource.rb > /var/www/html/files/check_servers/resource/resource_`date +\%Y\%m\%d`.html
ERBテンプレート
各項目でソートできるようにコレ使ってます
<!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8"> <title>サーバリソースチェック</title> <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script> <script type="text/javascript" src="/files/js/joequery-Stupid-Table-Plugin/stupidtable.min.js"></script> <script type="text/javascript"> $(function(){ $("table").stupidtable(); }); </script> </style> </head> <body> <table border="1"> <thead> <tr> <th data-sort="string">Host</th> <th data-sort="float">user</th> <th data-sort="float">system</th> <th data-sort="float">io</th> <th data-sort="float">idle</th> <th data-sort="int">メモリ使用率</th> <th data-sort="int">ディスク使用率</th> </tr> </thead> <% resources.each do |host, r| %> <tr> <td><a href="http://munin.mikeda.jp/server/<%= host %>/index.html#system"><%= host %></a></td> <td align="right" bgcolor="<%= color_cpu_usr(r[:cpu][:user]) %>"><%= r[:cpu][:user] %></td> <td align="right" bgcolor="<%= color_cpu_sys(r[:cpu][:system]) %>"><%= r[:cpu][:system] %></td> <td align="right" bgcolor="<%= color_cpu_io(r[:cpu][:iowait]) %>"><%= r[:cpu][:iowait] %></td> <td align="right" ><%= r[:cpu][:idle] %></td> <td align="right" bgcolor="<%= color_memory(r[:memory][:usage]) %>"><%= r[:memory][:usage] %>%</td> <td align="right" bgcolor="<%= color_disk(r[:disk][:usage]) %>"><%= r[:disk][:usage] %>%</td> </tr> <% end %> </table> </body> </html>
なんでもかんでもmuninやZabbixのグラフで見ようとするのは非効率的ですよ!