Chef Infra Clientの「静かなる侵食」を止める:メモリリークとの戦い方
こんにちは。インフラの世界へようこそ。
Chefという道具に出会ったあなたは、幸運です。サーバーを「手作業」ではなく「コード」で定義する。このパラダイムシフトは、あなたのインフラ運用を劇的に楽にしてくれます。
しかし、大規模な環境や長期稼働するサーバーでChefを運用していると、「Chef Infra Clientが動くたびにメモリが少しずつ減っていく」という、エンジニアを夜も眠れなくさせる現象に遭遇することがあります。
今日は、初心者の方でも直感的に理解できるよう、Chefの役割から入り、この厄介な「メモリリーク」をどう制圧するか、現場の最前線の知見を共有します。
—
1. Chef Infra Clientとは何か?
Chefは、「サーバーの状態を定義し、その通りに自動修復する」ためのツールです。
- Chef Server: サーバーの「あるべき姿(Recipe)」を管理する司令塔。
- Chef Infra Client: 各サーバー上で動き、司令塔の指示を受けて設定を適用する「実行部隊」。
通常、Chef Infra Clientは30分に1回程度、バックグラウンドで自動実行されます。この時、Rubyのランタイムが毎回立ち上がり、膨大なリソースをスキャンします。ここが、メモリ問題の発生源になり得るのです。
—
2. まずはここから:HelloWorldとセットアップの要点
Chefをインストールしたら、まずは「自分自身の設定を管理する」感覚を掴みましょう。
インストールと初期設定
Chef Workstationをインストールし、PATHを通す
これが「コードを書くための環境」になります
curl -L https://omnitruck.chef.io/install.sh | sudo bash -s — -P chefdk
HelloWorld的レシピ
`hello.rb` というファイルを作り、以下のコードを書いてみてください。
ファイルが存在することを確認し、内容を書き込む
file ‘/tmp/hello.txt’ do
content ‘Chef is working!’
action :create
end
`chef-apply hello.rb` を実行して、`/tmp/hello.txt` が生成されれば成功です。これが「冪等性(べきとうせい)」の第一歩です。何度実行しても、結果は同じになります。
—
3. なぜメモリが肥大化するのか?(本題:トラブルシューティング)
さて、ここからが本題です。Chef Infra Clientが長時間稼働するとメモリが枯渇する原因は、主に2つあります。
原因①:Rubyのガベージコレクション(GC)の怠慢
ChefはRubyで書かれています。RubyのGCは賢いですが、メモリに余裕があるときは「まだ掃除しなくていいや」とサボる癖があります。これを強制的にチューニングします。
対策: 環境変数でGCを制御する。
`/etc/default/chef-client` (またはsystemdのユニットファイル) に以下を追記します。
メモリ断片化を防ぐため、GCの閾値を引き下げる設定
export RUBY_GC_HEAP_FREE_SLOTS=100000
export RUBY_GC_MALLOC_LIMIT=64000000
これにより、Rubyはより積極的にメモリを解放するようになります。
原因②:Ohaiプラグインの暴走
Chef実行の最初に行われる「サーバー情報の収集」をOhaiと呼びます。自作のOhaiプラグインや、複雑すぎるネットワーク環境下では、Ohaiがメモリを爆食いします。
診断方法:
どのプロセスがメモリを食っているか、定点観測しましょう。
Chef実行中のメモリ消費を追跡
ps aux | grep chef-client
もしChef実行前後でメモリ使用量が数100MB単位で増え続けるなら、特定のOhaiプラグインが原因です。
—
4. 現場で役立つ「メモリリークを防ぐ」設計思想
初心者の方に伝えたい、最も重要なルールはこれです。
1. 無限ループを避ける: Chefのレシピ内で外部コマンドを呼び出す際、巨大な出力を変数に格納しないでください。それはそのままメモリに直結します。
2. Ohaiをシンプルに: 不要なプラグインは無効化しましょう。`client.rb`で制御可能です。
# client.rbでの設定例
# 不要なOhaiプラグインをロードさせない
ohai.disabled_plugins = [ :Passwd, :Command ]
3. 定期的な再起動: どんなに完璧なコードでも、長期間のプロセス実行にはリスクが伴います。systemdのサービスとして運用するなら、`MemoryMax` を設定して、上限に達したらプロセスを再起動させるのが、最も確実な「大人の運用」です。
—
最後に:完璧を目指さず、自動化を目指そう
メモリリークのトラブルシューティングは、最初は怖く感じるかもしれません。しかし、それはあなたがシステムを深く理解しようとしている証拠です。
「なぜリソースが減るのか?」という問いを持ち続け、設定を少しずつ調整する。そのプロセスこそが、エンジニアとしてのスキルを底上げします。
これをマスターすれば、あなたはもう「サーバーの番人」です。次はどんな自動化に挑戦しますか? 困ったときは、またいつでも聞きに来てください。応援していますよ!