kmuto’s blog

はてな社でMackerel CREをやっています。料理と旅行といろんなIT技術

mackerel-agentのキューのシミュレーションを書いていた

年始にmackerel-agentのコードをひととおり読んでいたのだけど、キューの実装部分がコードだけでは読み取れなかったので、シミュレーションを書いて挙動実験をしていた。

(なお、公開してからFILOじゃなくてLIFOだよなということに気付いた)

mackerel-agentは、IaaSやオンプレサーバーにインストールしてもらい、Mackerelにそのホストのメトリックを定期的に送る小さな常駐エージェント。仮にネットワーク障害などでメトリックを送れないときがあっても、収集したメトリックを失わないようにキューを自身で保有し、復旧時に再送を試みる仕組みになっている(そうでないと、障害原因の検証に役立ったかもしれない詳細情報が失われてしまうので)。

mackerel-agent自体はGo言語で記述されており、ほとんどの箇所はGoビギナーでも理解しやすい。

ただ、キューの部分はGoの並行処理になっている上、単純なLIFO処理ではなくバラけさせていたり、溜まったときにはバーストモードっぽく頻度を変えているところがあったりで、いまいち挙動を理解しきれなかったので、シミュレータを作った。

github.com

かっこいいGUIやフロントエンドはなくて地道にCUIだけど、障害発生・復旧のときにキューの中でメトリックオブジェクトがどう動いていくのかというのを真似てみている。ただし、そもそもGoコードの読み方時点で間違っている可能性も大いにあり、「違うヨ…全然違うヨ…」かもしれない。

Goビギナーにとって、前職の退職直前に制作をお手伝いした『初めてのGo言語』(オライリー・ジャパン)が、コードリーディングにおいてとても役に立ったので、お勧めしたい。なお、直販のPDF電子版ではコード表現にカラーハイライトルールを有効化してあるですぞ。

git allsyncというのを作った

業務でGitのリポジトリを多数扱っていて、サポートのお手伝いのためにエラーメッセージからコードリーディングを串し刺しで探すことがある。で、このときに

  • 「うぉー見つからねーどれが出してるんだー」「まったくわからん」「pullしてないやん…」
  • 「なるほどーこれはあかんね」「いや確か直したってこの前聞いたよな」「pullしてないやん…」

といった悲しい出来事がまれによくあるケースになりそうなので、カレント直下のGitリポジトリ群をともかく最新にpullするツールを書くことにした。

この手のツールといえば、debian-installer開発の頃に使っていた、Joey Hessの通称mr、myreposが思い浮かぶのだが(パッケージはまだ配布されていてbrewにもある)、Perl依存はあまりしたくないというのと、ちょっとアレは用途に対して大きすぎる(VCS乱立期だったので、ほぼ全部のVCSに対応しようとしている)ので、git限定のシンプルなもので実装する。

github.com

単純にpullしかしない。デフォルトではブランチ名がmainかmasterのときのみpullする。

$ git allsync
[adventcalendar]...main pulled
[mackerel-agent]...master pulled
[mackerel-agent-plugins]...master pull error
error: Your local changes to the following files would be overwritten by merge:
        packaging/deb/debian/rules
Please commit your changes or stash them before you merge.
Aborting
Updating f6817a6..9b891c4
[mackerel-plugin-f2b]...master pulled
[mkr]...test-modify (skip)

Perl依存からRuby依存になっただけでは?という疑問は「RubyはOSレイヤー」と捉えることで置いておこう。

MackerelでFail2banのBAN IP数をグラフ化するためのプラグインを書いてみた

「Mackerelエージェントのプラグインの仕組みを知り、プラグインを書いてみる」練習として。プラグインテンプレートとしてGo言語のは用意されているのだけど、さっちゃんのアドベントカレンダー記事にもあるとおり、メトリック自体は「メトリックに付ける一意な名前」「値」「Unix時刻」をタブ区切りで出力するだけでよい。

c4se.hatenablog.com

ではRubyでさくっと書いてみるかーということで、題材としてはかねてからやろうかなと思っていた、Fail2banのBAN IP数を測ってみる。できたのはこちら。

github.com

kmuto.jpに訪れるいろいろな攻撃をFail2banで叩き落としているが、そのJAILルールごとに現在BANしているIP数をグラフ化している。

Fail2ban BAN IPのグラフ化

BANしているのを眺めてどんなメリットがあるんだという意見もあるが、「お、今日も攻撃お疲れさまです! 拒否させていただきます!」という気持ちを視覚化できる。ほかには、「年末年始、sshdbotネットワークのマシンも休みなのか静かめだけど、PostfixへのAUTH試行はわりとずっとあるんだなぁ」といった手法の違いも目に見える。

余談

Fail2banからは fail2ban-client banned を使えばJSONっぽいというかRubyオブジェクトっぽいのが出てくる。

Ruby的にはevalしてそのまま使えるし、fail2banのログ化されている時点で安全だろうとは思うが、mackerel-agentはrootで動いているのもあってさすがにevalは抵抗がある。

じゃぁJSONとして使うか、としたところでなんかパースエラーになってしまってしばし悩んだのだが、結局シングルクォート(')がダメで、ダブルクォート(")にしろということだった。経験値が1上がった。