Tuned | ||
---|---|---|
HOME |
sysctl や udevルール、rc.local などばらばらのファイルで設定していたカーネルやデバイスのチューニングを、Profile という単位でまとめて集中管理できるツール。CPUの負荷などに応じて動的なチューニングを行うことも可能だが、今のところ自分はスタティックな用法にのみフォーカスして使っている。これがなかなか使える。提供されているドキュメントや情報が不足しているのが難点。また、まだ成熟しきっていないところがあり、ちょっとばかしイナしながら使ってやる必要がある。
CentOS 7 をインストールした時、パッケージグループ選択の結果たまたま入ったのをきっかけに触り始めた。実は RHEL/CentOS 6 の時代から存在していたようだ。tuned はデーモンとして動作し、負荷状況に応じた動的なチューニングもできる。それが tuned の主な使い方だと思い込んで毛嫌いしていたのだが、スタティックな使い方をすると、とくに出しゃばらず非常に便利であることが分かった。
Tuned は主に以下のコンポーネントから成る。
systemd の tuned サービスユニットから呼ばれている /usr/sbin/tuned は、python で書かれたスクリプトだ。
/etc/tuned/tuned-main.conf に、動的チューニングを行うかどうかなど、基本的な動作設定が定義されている。
/usr/lib/tuned/ 配下に、既製のプロファイルが各々ディレクトリとして存在する。ディレクトリ名 = プロファイル名 だ。また、プロファイルから共用するための環境変数やシェルファンクションを定義したスクリプトインクルードファイルもここにある。
カスタムプロファイルやカスタムスクリプトファンクションファイルなどは /etc/tuned/ 配下に置くことが推奨されている。こちらの方が /usr/lib/tuned/ にあるものよりも優先される。プロファイルは別のプロファイルの内容を継承したり特定の項目をオーバーライドしたりすることもできる (カスタムプロファイルに限った話ではないが)。
チューニングは tuned の プラグイン を介して行う仕組みになっている。主なところでは、sysctl, disk(I/OスケジューラやReadAheadなど), cpu(governor等)、それに、既存のプラグインで網羅されていないことをカスタムスクリプトで行うための script プラグインがある。プラグインの実体は /usr/lib/python2.x/site-packages/tuned/plugins/ に plugin_*.py という名前で格納されている。
プロファイルは、プロファイル名を名前としたディレクトリと、そこにある tuned.conf が最低限の構成となる。ここからは customserver というプロファイルを作成するものとして説明する。
Tuned はドキュメントが甚だ不足していて、既存のサンプルコンフィギュレーションを見本にするしか確実な方法がないのが実情。どうせなら、あらかじめ、既製のどのプロファイルを下地にするのが最適か選んでおくとよい。システムプロファイルディレクトリ /usr/lib/tuned/ 配下を物色して、新しく作ろうとするプロファイルの性質に似たものを探す。ここでは throughput-performance プロファイルを叩き台にすることにして、それをカスタムプロファイルディレクトリへ新しい名前でコピーする。
# cp -a /usr/lib/tuned/throughput-performance /etc/tuned/customserver
/etc/tuned/customserver/tuned.conf を編集する。コンフィグは [name] ブロックで構成される。[main] ブロックを除いては、プラグイン毎にひとつのブロックを構成する。例えばこんな塩梅だ。これは単なる例であり項目数もかなり絞っているし、最適値はマシンの用途や仮想か物理かによっても全く異なるので、このまま使おうとしないでいただきたい。
# # tuned configuration # [main] include=throughput-performance <- 継承するプロファイル。他のどのプロファイルも継承しないのなら[main]ブロック自体不要。 [cpu] replace=1 <- ※ force_latency=1 governor=performance energy_perf_bias=performance min_perf_pct=100 [sysctl] replace=1 vm.dirty_ratio = 30 vm.min_free_kbytes = 131072 vm.swappiness = 30 kernel.shmall = 939524096 kernel.shmmax = 939524096 kernel.sem = "250 32000 100 128" fs.file-max = 6815744 [vm] replace=1 transparent_hugepages=never [disk] replace=1 device=sd* <- ※ elevator=deadline [netif_ringsz] enabled=false <- ※ verbose=true <- ※Tunedのデバグ にて解説 logging=debug <- ※Tunedのデバグ にて解説 type=script script=set-ringsz.sh
プラグインブロックは [PluginName] とするのが通常だが、[my_data_disk] などという全く別の名前にしてその中で type=disk のようにプラグインを指定する方法もある。ただし、継承元に [disk] という標準名の diskプラグインブロックがあって、継承先の diskプラグインブロックは [data_disk] + type=disk で指定した時、後者のパースの結果が「適用対象デバイスなし」(後述のdeviceパラメータ参照) となってしまった。継承元と継承先に同じプラグインのブロックがある時は [ブロック名] は合わせた方が無難なようだ。
replace=1 (つまりtrue) は、他のプロファイルを継承 (include) している場合に、項目を置き換えることを意味する。replace=1 が指定されていないブロックは、「マージとなる」とマニュアルに書いてある。しかし、どこを見ても説明が不十分。継承を使っている場合で、継承元にも同じ名前のあるブロックは、必ず replace=1 にしておくのが間違いないと、筆者は思っている。実験してみると、replace について以下のことくらいしか分からなかったからだ。
というわけで、どんなケースでどのようにマージされるのかわけが分からず、意図せぬ値の結合を避けるため、今のところ replace=1 は常に宣言するべきとの結論に至った。
先ほども話に出た devices= パラメータは、そのプラグインブロックの適用対象にするデバイスを限定したい時に使う。ワイルドカード "*" も使用可能だ。プラグイン毎に、例えば diskプラグインなら sd[a-z], hd[a-z], vd[a-z] などディスクデバイスと思しきブロックデバイス名のルールがあらかじめ決められていて、devices= パラメータを指定しなければ、マシンに存在するそれら全てのデバイスが適用の対象となる。これは "devices=*" と指定したのと同じだ。また、カンマ区切りのリストも指定可能で、例えば "devices=sda,sdb" となる。さらに、除外指定も可能で、その場合 "devices=!sdc,!sdd" といった記述になる。
[netif_ringsz] ブロックの記載例のように、ブロックに enabled=false を宣言すると、そのプラグインブロックの適用を無効にすることができる。継承元にも同じ名前のブロックがあれば、継承元のブロックも適用されない。
例の最後にある [netif_ringsz] は、ネットワークインターフェイスのリングバッファ(ハードウェアバッファ) をチューニングしたくて筆者が独自に作ったシェルスクリプトを駆動する scriptプラグインブロックだ。従来なら udevルールか/sbin/ifup-local でやっていたことである。
script= の右辺には、絶対パスではなく、プロファイルディレクトリ内に存在するファイル名を書かなければならない。set-ringsz.sh は、ここで言う /etc/tuned/customserver/ に置くことになる。カスタムスクリプトを書くに当たっては、いくつかお約束事がある。スクリプト例を示しながら説明しよう。
#!/bin/sh . /usr/lib/tuned/functions . /etc/tuned/my_functions start() { save_ringsz set_ringsz 2048 1024 } stop() { restore_ringsz } process ${1:+"$@"}
必ず、`source /usr/lib/tuned/functions' で tuned のシステムプロファイルディレクトリにあるシェルインクルードファイルを読み込むこと。
スクリプトには、start() ファンクションと stop() ファンクションが定義されていること。scriptプラグインでは、tuned がプロファイルの適用時に "start" 引数、適用解除時や別のプロファイルへの推移の際に "stop" 引数を付けてスクリプトを呼んでくる。stop/start 引数の振り分け処理には、tuned の functionsインクルードで定義されている process() ファンクションを使う。最初は知らずに case ステートメントで直接書いてみたが動きが安定しない - "reinventing the wheel" というやつで無意味なのでやめておくこと。
もうひとつの約束事は、start の際には、これから変更しようとしている値の現在値をキャッシュファイルに記録し、stop の際にはそれをリストアすることだ。これらの処理は、自力で書く必要がある。このケースでは、それらのファンクションは my_functions という別体ファイルに書いた。必ず分けなければいけないというわけではないが、他にもスクリプトを書いた時に使い回せるという思惑からだ。キャッシュファイルディレクトリとファイルの拡張子は tuned 作りつけの functions の中で、それぞれ変数 $STORAGE と $STORAGE_SUFFIX にアサインされているのでそれを利用する。
tuned の管理には tuned-adm コマンドを使う。tuned 本体同様これも python でできている。
利用可能なプロファイルのリストを得るには、
# tuned-adm list
現在適用されているプロファイルを知るには、
# tuned-adm active
前述で作ったプロファイルを適用するには、
# tuned-adm profile customserver
プロファイルをアンロードしてシステムのデフォルトに戻すには、
# tuned-adm off
プロファイルの設定内容を書き換えたからといって、一旦 off して剥ぎ取る必要はなく、customserver プロファイルがアクティブな状態で再度 `tuned-adm profile customserver' してやれば、プロファイルはアンロード->リロードされて更新後の設定が反映される。
動的チューニングを使わなくても、起動時にプロファイルを適用させるためには、tuned サービスはスタートアップするようにしておく必要がある。つまり RHEL/CentOS 7 ならば `systemctl enable tuned.service' だ。起動時には、最後に適用されていたプロファイルが適用される。ただし、最後に `tuned-adm off' しておいてシステムを再起動すると、謎のお勧め(recommend) 機能のお節介なのか、balanced プロファイルあるいは virtual-guest プロファイル (おそらく試験環境が仮想マシンだから) が勝手に適用されていたりする。プロファイルの適用をやめたくなったら、きっぱり tuned.service のスタートアップを disable すべきだ。
tuned は、ジャーナルやSYSLOGを通さずに直接 /var/log/tuned/tuned.log にログを吐く。
tuned.conf で使えるパラメータに、verbose=, logging= という汎用パラメータがある。verbose はブーリアン値で true か false のいずれかで既定値は false、logging は重篤順に critical, error, warning, info, debug のいずれかで既定値は info。[main] ブロックに書けばそのプロファイル全体で効かせることができるし、特定のプラグインブロックで唱えればそのブロックに対してのみ効くことになる...とマニュアル等に書かれているが、CentOS 7.2 で試した限り、全く効かない。結局、tuned の起動オプションに -D を指定することによってログにデバグ情報も出力され、verbose= を true にしようが false にしようが、logging= が debug だろうと info だろうと、ログの冗長性に全く変化は見られなかった。
サービスを systemd で制御している RHEL/CentOS 7 では、tuned のランタイムオプションをうまく指定するためにちょっとした工夫が要る。tuned のサービスユニットに、追加のランタイムオプションを読み込む仕組みがないからだ。しかし、大元の /usr/lib/systemd/system/tuned.service ファイルを変更するのは行儀が悪い。代わりに /etc/systemd/system/tuned.service.d/override.conf を作り一部設定をオーバーライドする。直接作っても構わないのだが、`systemctl edit tuned.service' とやると override.conf の一時ファイルがテキストエディタ (既定では nano で開く - 珍しい) で開かれるので、下記の内容を打ち込み、言われるままの一時ファイル名で保存する。そうすると /etc/systemd/system/tuned.service.d/ ディレクトリと override.conf が出来上がる。
[Service] EnvironmentFile=-/etc/sysconfig/tuned ExecStart= ExecStart=/usr/sbin/tuned -l -P $OPTIONS
一旦 ExecStart= を空にしてから宣言しなおすのがポイント。さもないとエラーでユニットが起動しない。あとは /etc/sysconfig/tuned ファイルを作り OPTIONS="-D" と書けば準備OK。`systemctl daemon-reload && systemctl restart tuned' すれば、以降 tuned.log にはデバグ情報が出てくる。デバグが済んだら、sysconfig/tuned の OPTIONS 行をコメントアウトするかファイルごと削除すればいい (EnvironmentFile= の指定に "-" を入れているのでファイルがなくてもエラーにはならない)。