この記事はGMOペパボ Advent Calendar 2019 8日目の記事です。
令和最初の夏にFTPサービスを監視するためのmackerel pluginを作成しました。初めてプラグインを作成した時に考えたことをパプリックな場に残すことで、私と同じようにこれから初めてmackerel pluginを作ってみようかと思っている人にとって僅かでも助けになれば幸いです。
なぜ作ったのか
障害の発生
業務でFTPサーバのユーザー認証に関するコンポーネントのアップデートを行った際に、認証が行えなくなる障害が発生しました。mackerelを用いてサーバ内部からと外形監視用サーバから監視を設定していましたが、ポート監視のみだったため、アラートにならず障害に気づくまで時間がかかってしまいました。
そこで、この障害の再発防止の一つとしてユーザー認証までをチェックするFTP監視を追加することにしました。
既存のプラグインの調査
まず最初にmackerelで利用できるpluginの調査を行ないました。mackerelの公式plugin集を調査したところ、check-tcpにftp オプションがあることを発見しました。しかしコードを斜め読みするかぎり、ユーザ認証まで行うようなものではないため要件にはマッチしないことがわかりました。またその他にもFTP監視に関するpluginはありませんでした。
mackerelのチェック監視はNagios pluginと互換性があるため、そのまま利用できることが多いです。そこで、次にNagios Pluginの調査を行いました。nagios pluginに機能的にマッチしそうなプラグインがを見つけましたが、メンテされているのか不明なところと、perlで書かれたpluginだったためそれだけのためにperlだったりを追加するのは得られるメリットに比較的し脆弱性対応などの手間が増えそうなので見送りました。
最後にftpコマンドをラップしたスクリプトを作成することでも環境にあまり手を加えずに求めていることは実現できそうでした。しかし、この頃にはmackerelで使うならmkrで簡単にインストールしたいという欲も出てきたため、goでpluginを作成することにしました。
mackerel pluginは、決められた形式でpluginを公開することで、mkrコマンドでpluginをインストールできます。
どう作ったか
機能の整理
まずは必要な機能について改めて整理し、作るところとそうでないところを明確にしました。
- FTPS対応(Implicti/Explicit)
- check-tcpで行えないftpの認証のみに絞りシンプルにする
オプションの定義
実装のイメージをより具体的に固めるためオプションを予め書き出しました。前述の機能の整理で自ずと必要なオプションは決まっていました。
- 接続に必要なホスト名、ポート番号
- FTPのユーザー名、パスワード
- FTPとFTPSの切り替え、FTPSのImplicti/Explicitの切り替え
- WainingとCritical の閾値
FTPライブラリの選定
GoDoc.org でFTPをキーワードにして調べたところ、次の2 つが見付かりました。
jlaffaye/ftp のほうがスター数やimportされている数も多く活発ですがFTPS Explicit modeに非対応なため、今回は、 secsy/goftpを採用することにしました。
実装中
実装自体は豊富にある既存のpluginを参考にできたので、特に難しいところはありませんでしたが、実装以前にいくつか困難だったことがありました。
FTPのテスト環境用意するのが面倒
一からFTPのセットアップは忘却の彼方だったので十数分であきらめました。vagrant boxがありましたが、私の環境でうまく動作しませんでした。DockerでFTPみたいなのをいくつかみつかましたが、FTPSは見つけられなかったりと動作検証の環境用意に時間がかかりました。最終的にはQiitaで見つけたこちらを手元のテスト環境として利用しました。
オプションの省略形
いちいち `– host`や` – ftps` など入力してられないのでオプションの省略形を用意することに決めてました。しかし実際にいざ割り当てようとしたとき、` – password`と` – port`のどちらに`-p`または`-P`を割り当てるべきかに悩みました。今でもまだ正解なのか判ってないですが、今回は悩んだ末に ` – port` に`-P`を、` – password`に`-p`を割り当てました。`-h`は他のコマンドに倣いhelpに割り当てることにしたため、` – host`に`-H`を割り当てることになり、` – port`も接続先に関するオプションなので大文字の`-P`にすることにしました。
チャレンジしたこと
モチベーションを落とさず継続的にメンテしていけるよう、面倒なリリース作業を楽にできるよう設定しました。
具体的には、CIに用いてるDrone.ioでtagが打たれた場合に Songmu/goxz で複数環境向けにbuildし、Droneのgithub-release pluginでリリースを作成するようにしています。
(drone.io を用いたのは普段業務で利用しているため、記法などに慣れていたためです。)
おわりに
今回要件にマッチする監視を実現するために既存のプラグインの調査や代替方法を検討し、mackerl pluginを作成しました。また部分的ではありますが、簡単なプラグインを作成する大まかな流れの一例を示しました。
まだブラッシュアップしていかなければならないコードなので、今後ともよろしくお願いします。(Issue・PR待ってます。)