mruby-cgroupを有効にしてApacheのリソースをコントロールする話 その壱


前回はmod_mrubyを導入して簡単なRubyスクリプトでApacheの挙動を確認するところまでやりました。続いて今回もmrubyの話で、Cgroupを有効にしてその効果を確認するとこまでやろうかなっと思います。セミの声を聞きながら部屋でゴロゴロしていると気分だけは夏休み気分になるね〜。気分だけね。

cgroupって何づら?

LinuxKernelの機能の1つで、利用方法はいろいろとあります。が、難しい話はスルーしましょう。
cgroupを略さずに書くとコントールグループで、何のコントールかというとリソースです。
リソースっつうと、CPU、メモリ、ディスクI/Oとかですな。
コントロールと言っても色々ありそうだし説明文にするとややこしくなりそうなので、Wikipediaから抜粋して箇条書きにしてみますと。

  • リソース制限
  • 優先順位
  • どれだけのリソースを使用しているか計上
  • 隔離
  • 一時停止・再開など

などなど。
こうして書き出しただけでも色々なことができるのだなぁと。
ただ今回の目的はまずはApacheに対してCPUの利用を50%にしまぁーす。するってーと、参考サイトのままですが挙動の確認なので良しとします。

Cgroupじたいは以前にも少し触ってて。

関連記事
Cでサーバー監視のプログラムを作ってみよう その4

もう1年以上も前になるんですなぁ、なつかしや。

インストール

まずはcgroupを有効にするにはmod_mrubyもリビルドしなければいけません。
やるべきことはコメントアウトを外すだけではなくて色々必要なのでした。
まずはCgroupをインストールしてApacheがアクセス可能なグループを作成しときます。

# yum install -y libcgroup libcgroup-devel
# chkconfig cgconfig on
# service cgconfig start
# mkdir /cgroup/cpu/apache
# chown -R apache:apache /cgroup/cpu/apache
# ls -l /cgroup/cpu/apache/
合計 0
--w--w--w-. 1 apache apache 0  7月 19 23:02 2015 cgroup.event_control
-rw-r--r--. 1 apache apache 0  7月 19 23:02 2015 cgroup.procs
-rw-r--r--. 1 apache apache 0  7月 19 23:02 2015 cpu.cfs_period_us
-rw-r--r--. 1 apache apache 0  7月 19 23:02 2015 cpu.cfs_quota_us
-rw-r--r--. 1 apache apache 0  7月 19 23:02 2015 cpu.rt_period_us
-rw-r--r--. 1 apache apache 0  7月 19 23:02 2015 cpu.rt_runtime_us
-rw-r--r--. 1 apache apache 0  7月 19 23:02 2015 cpu.shares
-r--r--r--. 1 apache apache 0  7月 19 23:02 2015 cpu.stat
-rw-r--r--. 1 apache apache 0  7月 19 23:02 2015 notify_on_release
-rw-r--r--. 1 apache apache 0  7月 19 23:02 2015 tasks

続いてmod_mrubyのリビルド。
常に新しくなっていると思われるのでgit pullしておいて良いかなと思われ。

# cd mod_mrubyのディレクトリ
# git pull
# git submodule init
# git submodule update
# vim build_config.rb
mruby-cgroup.git #このコメントアウトを外して有効化します。
# cd mruby
# rake CFLAGS="-fPIC"
# cd ..
# ./configure
# make
# make install

これで多分(検証で色々と動かしていたので多分ってことで。もしかしたら何か抜けてるかもしれん。)
動くはず。
下のような感じのスクリプトを用意してアクセスしてみて、cgroup::CPUで使えるメソッドが表示されてればOKです。

c = Cgroup::CPU.new("apache/mod_mruby_group")
Apache.echo c.methods

ちなみにちゃんと動いていると指定されていたファイルができてます。
たぶん動いてるかも??ということはありませんww

# ls /cgroup/cpu/apache/mod_mruby_group/
cgroup.event_control  cpu.cfs_period_us  cpu.rt_period_us   cpu.shares  notify_on_release
cgroup.procs          cpu.cfs_quota_us   cpu.rt_runtime_us  cpu.stat    tasks

ここで一息

そのうちやるであろう動的なコントールに備えて、Apache::Scoreboardを使ってみた時の話でもしますか。
まずは最初は全く動かなくて、フックのタイミングが良くないのか?とかとか思って色々試していたのですが、どうやら

ExtendedStatus On

にする必要があったようだ。
・・・ぐぬぬ。
初歩的な問題なようである。

上手くデータがとれていると以下のように表示がされます。

- idle worker     = 6
- busy worker     = 2

実験のためにMPMの設定を極端に変えてみます。


# httpd.conf prefork.c
StartServers       1
MinSpareServers    1
MaxSpareServers   20
ServerLimit      256
MaxClients       256
MaxRequestsPerChild  4000

ApacheBenchでつんつくつんと突っついて変化を見てみます。
まずは実行前です。

- idle worker     = 0
- busy worker     = 1

ApacheBenchしてみます。
途中経過ですがドカドカっと増えて減ったとこ。

- idle worker     = 60
- busy worker     = 65

終わった後です。
このあとMaxSpareServersの設定値まで減っていくはず。

- idle worker     = 94
- busy worker     = 2

終了だ。

- idle worker     = 19
- busy worker     = 1

微妙に長くなりましたが、これで上手くデータはとれていることは分かりました。
しかしスレッド数とかはちゃんと取れてるのに、ロードアベレージが取れないのはどこかミスってるのだろうか。。
では本題に戻りましょう。

mruby-cgroupの実験

参考サイト
人間とウェブの未来
リクエスト単位でApacheのリソースを制御するためのmrubyを使った制御DSLコードの紹介

単純に全てのリクエストをCPU50%に制御!というのをやってみます
以前作っていた円周率計算CGIをリクエストして挙動を見てみる。

  PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND
 2726 apache    20   0 38660 7720 2052 R 99.7  0.8   0:07.01 index.cgi

実行スパーン!これで成功です!

  PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND
 4165 apache    20   0 38660 7716 2052 R 49.9  0.8   0:14.88 index.cgi

いやぁ、分かりづれ〜!(^_^メ)

ということで

suexec環境で試してみる

少しはわかりやすくなるかと思うので、take、jiro、sayoの3人に試していただくとしよう。
設定はこんな感じで何でもOkになっています。

<Directory /home/*/public_html>
  Options All
  AllowOverride All
  AddHandler cgi-script .cgi .pl .php
</Directory>

<VirtualHost *:80>
  DocumentRoot /home/take/public_html
  ServerName  take.example.com
  SuexecUserGroup take take
</VirtualHost>

<VirtualHost *:80>
  DocumentRoot /home/jiro/public_html
  ServerName  jiro.example.com
  SuexecUserGroup jiro jiro
</VirtualHost>

<VirtualHost *:80>
  DocumentRoot /home/sayo/public_html
  ServerName  sayo.example.com
  SuexecUserGroup sayo sayo
</VirtualHost>

ところがどっこいで、ここでひとつ問題が発生、suexecのDocrootが/var/wwwでした。
ググってみるとどうやらリビルドは不要で、バイナリで編集したら変更できるらしいので、生まれて初めてemacsを使ってみました。
生まれ〜て〜、はじめ〜て〜。

編集前

# /usr/sbin/suexec.org -V
 -D AP_DOC_ROOT="/var/www"
 -D AP_GID_MIN=100
 -D AP_HTTPD_USER="apache"
 -D AP_LOG_EXEC="/var/log/httpd/suexec.log"
 -D AP_SAFE_PATH="/usr/local/bin:/usr/bin:/bin"
 -D AP_UID_MIN=500
 -D AP_USERDIR_SUFFIX="public_html"

編集後

[root@testcentos sbin]# suexec -V
 -D AP_DOC_ROOT="/home"
 -D AP_GID_MIN=100
 -D AP_HTTPD_USER="apache"
 -D AP_LOG_EXEC="/var/log/httpd/suexec.log"
 -D AP_SAFE_PATH="/usr/local/bin:/usr/bin:/bin"
 -D AP_UID_MIN=500
 -D AP_USERDIR_SUFFIX="public_html"

じゃじゃーん。成功しました。
パーミッションも戻さないと、動かないの〜よ〜。

# chmod 4755 /usr/sbin/suexec
# ls -la /usr/sbin/suexec
-rwsr-xr-x. 1 root apache 13984  7月 20 01:17 2015 /usr/sbin/suexec

これでtakeとjiroに円周率計算CGIにアクセスしてみませう。

  PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND
 4866 take      20   0 38660 7720 2052 R 24.9  0.8   0:01.67 index.cgi
 4868 jiro      20   0 38660 7716 2052 R 24.9  0.8   0:01.04 index.cgi

これが結果ですが、合計で50%なので2人で50%でちゃんと動いているってのがさっきよりは分かると思います。
3人用意する必要もなかったわけですがまぁいいでしょう。

余談になりますが、円周率計算もなかなかリソースが必要なようでこの結果はこうなっちゃいました。

ab01

とまぁ、せっかくなのでユーザー毎に制限をしてみますか。
条件はバーチャルホストだったらドキュメントルートかホストネームはユニークだと思うので、今回はドキュメントルートで指定。
分かりやすくするようにtakeさんの場合は5%なんて数字にしてみます。

s = Apache::Server.new
if s.document_root == "/home/take/public_html"
  c = Cgroup::CPU.new("apache/mod_mruby_group")
  c.cfs_quota_us = 5000
  PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND
 6051 jiro      20   0 38660 7716 2052 R 44.9  0.8   0:15.19 index.cgi
 6055 sayo      20   0 38660 7720 2052 R 44.9  0.8   0:10.41 index.cgi
 6053 take      20   0 38660 7720 2052 R 10.0  0.8   0:02.58 index.cgi

これで前回よりは使ってる感が出てまいりました。これで&条件でも付け足せばそれなりな形になると思われ。
元からこのプログラムにはリソースをあまり使いたくないなぁなんて時にも使えますね。

そんな感じで今回はおわり〜。

Similar Posts:


Leave a Reply

Your email address will not be published. Required fields are marked *