Mackerel ブログ #mackerelio

Mackerelの公式ブログです

7月18日(水) データベースメンテナンスに伴うシステムの一時停止について

Mackerelプロダクトマネージャーの、id:Songmu です。表題の通り、計画的なシステムメンテナンスを実施いたします。

本メンテナンスはシステム停止を含むメンテナンスとなりますため、ご利用者のみなさまへは、ご迷惑をおかけいたします。今後も継続的によりよいサービスを提供するために必要不可欠なメンテナンスであるため、ご理解とご協力の程お願いいいたします。

実施予定日時

2018年7月18日(水) 15:00-18:00 (JST)

※上記は最長の場合。メンテナンス終了次第システムは再開します。

実施時間の内訳

  • 15:00-17:00 実際の作業を行うメンテナンスウィンドウ
  • 17:00-18:00 システム再開後のmackerel-agentからの再送などの確認を見越した予備時間枠

実施内容

データベースメンテナンス

当日の影響に関して

  • メンテナンス終了時刻は、最長ケースであり、作業終了次第メンテナンスは終了となります
  • メンテナンス開始後、暫くの間、Mackerelシステム全体が停止いたします
    • MackerelへのWebアクセスやMackerelエージェントのデータ投稿、APIアクセス(CLIツール含む)、アラート通知などができない状況となります
  • メンテナンス作業が終了し動作確認が取れ次第、メンテナンスを終了しその旨を告知します
  • mackerel-agentのメトリック投稿に関しては、メンテナンス中はmackerel-agent側でバッファリングがおこなわれ、メンテナンス終了後に再送されます
    • 正しく再送された場合、メンテナンス時間中のグラフも表示されます
    • 再送が完了しない状態でmackerel-agentを再起動したり、停止するとバッファリングされているデータが失われるのでご注意ください
    • メンテナンス中にmackerel-agentを起動する際は、Mackerel本体への疎通が失敗するため、起動も失敗します。

当日のお知らせに関して

ステータスページ( http://status.mackerel.io )、及び本ブログ( https://mackerel.io/ja/blog/ )にて、状況報告をおこないます。

補助的に、公式Twitter( https://twitter.com/mackerelio_jp )も利用いたします。

本件に関するお問い合わせ先

support@mackerel.io へメールでお問い合わせ下さい。

今後ともMackerelをご愛顧くださりますよう、よろしくお願いいたします。

オーガニゼーションに招待できるメールアドレスのドメインを指定できるようになりました ほか

連続リリース200週達成まであと【2週】!

こんにちは。Mackerelチーム CRE の三浦(id:missasan)です。

それでは、今週のアップデート情報です。

オーガニゼーションに招待できるメールアドレスのドメインを指定できるようになりました

オーガニゼーションの設定画面(https://mackerel.io/my?tab=setting)より、オーガニゼーションに招待できるメールアドレスのドメインをホワイトリストで指定できるようになりました。 社内にのみ公開したい、特定の協力会社にのみ公開したい、などの場合に、ドメインを制限いただくことで、誤って想定しないユーザを招待してしまうことを防ぐことができます。

f:id:mackerelio:20180615190849p:plain

f:id:mackerelio:20180615191046p:plain

mackerel-plugin-aws-ecs にて ServiceName が指定できるようになりました

これまでは ClusterName を指定してメトリックを取得できましたが、加えて今回のリリースにより、ServiceName も指定できるようになりました。

これによりFargateをお使いの環境でも、サービス単位でのメトリックを取得いただけるようになりました。

また、このオプションを指定いただくと、RUNNING タスク数も取得できます。

github.com

Debian 7 サポート終了のお知らせ

Debian 7 のLTSサポートが 2018年5月31日 に終了したことに伴い、Mackerel における Debian 7 のサポートを終了いたします。

Mackerel でのサポート終了に伴い、今後 Debian 7 での動作保証をいたしません。また、Debian 7 にて mackerel-agent を使用している環境に関するお問い合わせにつきましては、サポートを終了いたします。

恐れ入りますが、ご了承いただければ幸いです。

Mackerel および mackerel-agent の対応環境に関しては以下のページを参照下さい。

mackerel.io

Linuxのloadavgが約7時間ごとに上昇する現象の原因

Mackerelチームのエンジニアのid:itchynyです。

「mackerel-agentを入れるとloadavgが7時間ごとに上昇する」

先日、このような問い合わせを複数のお客さまから受けました。私も実験してみたところ、確かに再現しました。EC2 t2.microにmackerel-agentを入れて簡単なログ監視とプロセス監視を設定し、数日放置しました。 f:id:mackerelio:20180611212106p:plain 確かに、約7時間ごとにloadavgが上昇しています。この周期のcronの設定はしておらず、またmackerel-agent内部でも7時間ごとに行う処理はありません。しかし、プラグインを多く入れるほどloadavgのピーク値も上がります。

本エントリーでは、この現象の原因について説明します。

loadavgが上昇する原因を調べるには、まずloadavg自体がどう計算されているかを知る必要があります。 まずは、Linuxがloadavgをどのように計算しているかを説明します。

Linuxのloadavgは、run queueにあるプロセス (running process) とディスクI/Oやロック待ちのプロセス (uninterruptible process) の総数の指数移動平均値です。 Linuxのプロセスには、以下のような状態があります。

 % man ps | grep -A 10 "^PROCESS STATE"
PROCESS STATE CODES
       Here are the different values that the s, stat and state output specifiers (header "STAT" or "S") will display to describe the state of a process:

               D    uninterruptible sleep (usually IO)
               R    running or runnable (on run queue)
               S    interruptible sleep (waiting for an event to complete)
               T    stopped, either by a job control signal or because it is being traced
               W    paging (not valid since the 2.6.xx kernel)
               X    dead (should never be seen)
               Z    defunct ("zombie") process, terminated but not reaped by its parent

この内の RD の状態のプロセスの数を、指数加重平均で平滑化した値がloadavgとなります。

loadavgの対象となるrunningとuninterruptibleなプロセスの総数を、時刻 t に対する関数として p(t) と表しましょう。 サンプリング間隔を  \Delta t、時定数を  T とすると、プロセス数の指数移動平均、つまり指数関数的に減衰する加重平均は以下のように書くことができます 1。 $$ \begin{align} L(t) &= \big(1 - e^{-\Delta t / T}\big) \big( p(t) + e^{-\Delta t / T} p(t - \Delta t) + e^{-2\Delta t / T} p(t - 2 \Delta t) + \cdots \big) \\ &= \big(1 - e^{-\Delta t / T}\big) p(t) + e^{-\Delta t / T} L(t - \Delta t) \end{align} $$ これまでの時刻の p(t) の指数移動平均値は、前の計算値 L(t-\Delta t) と現在の値 p(t) の加重平均値で表すことができます。 これまでのプロセス数の履歴を保持していなくても、前回のloadavgと現在のプロセス数から新しいloadavgを計算できるということです。

この漸化式をもとに、定数を適切に選んでシミュレーションした値 (\Delta t = 5, T=60, 300, 900) と、実際のLinux (EC2 t2.micro上で yes > /dev/null& を実行し、10分後にそのプロセスを落とす) で計測された値を比較してみると、以下のような結果が得られました。 f:id:mackerelio:20180608155746p:plain

Linuxのソースコードを参照しながら、実際に上記の漸化式をもとにloadavgが計算されていることを確認します。 まずは kernel/sched/loadavg.c を見てみましょう。

/* Variables and functions for calc_load */
atomic_long_t calc_load_tasks;
unsigned long calc_load_update;
unsigned long avenrun[3];

void calc_global_load(unsigned long ticks)
{
    unsigned long sample_window;
    long active, delta;

    sample_window = READ_ONCE(calc_load_update);
    if (time_before(jiffies, sample_window + 10))
        return;

    // ...

    active = atomic_long_read(&calc_load_tasks);
    active = active > 0 ? active * FIXED_1 : 0;

    avenrun[0] = calc_load(avenrun[0], EXP_1, active);
    avenrun[1] = calc_load(avenrun[1], EXP_5, active);
    avenrun[2] = calc_load(avenrun[2], EXP_15, active);

    WRITE_ONCE(calc_load_update, sample_window + LOAD_FREQ);

    // ...
}

loadavgの値は avenrun に格納されています。 この値の更新を定期的に行うために、 calc_load_update という値を LOAD_FREQ ずつ増やしながら、 jiffies (1 tickごとに1増える、時刻を表す変数) と比較していることがわかります。 つまりloadavgは更新間隔は LOAD_FREQ ごとに行われています。 この値は include/linux/sched/loadavg.h にかかれている通り、 5*HZ+1 ごとです。 HZ は1秒に何tick増えるかという値ですから 2、5秒と1 tickごとにloadavgが更新されるということがわかります。 では、実際に値を計算している calc_load を見てみます。

/*
 * a1 = a0 * e + a * (1 - e)
 */
static unsigned long
calc_load(unsigned long load, unsigned long exp, unsigned long active)
{
    unsigned long newload;

    newload = load * exp + active * (FIXED_1 - exp);
    if (active >= load)
        newload += FIXED_1-1;

    return newload / FIXED_1;
}

分岐の処理を無視して一つの式に書いてみます 3

 avenrun[0] = ((FIXED_1 - EXP_1) * active + EXP_1 * avenrun[0]) / FIXED_1;

ここで include/linux/sched/loadavg.h によると EXP_1 = 1884, FIXED_1 = (1<<11) です。 また上の方で求めた漸化式に \Delta t=5, T = 60 を代入すると次のようになります。 $$ \begin{align} L(t) = \big(1 - e^{-1/12}\big) p(t) + e^{-1/12} L(t - \Delta t) \end{align} $$ 整数演算にするために11bitシフトした (FIXED_1 倍した) 値で計算していることと、e^{-1/12}2^{11} がおよそ1884であることを確かめると、確かに漸化式とLinuxで行われている計算が一致することがわかります。 loadavg5, 15も同様に確認できます。

loadavgはおよそ5秒ごとに、その瞬間のrun queue内のプロセス数 (calc_load_tasks) と漸化式を用いて更新されています。 正確には 5*HZ+1 tickごとに計算されています。 この +1 が、約7時間ごとにloadavgが上昇する現象の原因です。

mackerel-agentは1分ごとにメトリックを収集するために、プラグインのプロセスを開いています。 loadavgの再計算が5秒ぴったりから少しだけずれているために、mackerel-agentがメトリック収集を始めるタイミングとloadavgの再計算のタイミングが定期的に一致するのです。

HZ が1000の環境では、loadavgは5.001秒ごとに更新されます。これを5000倍すると 25005秒 すなわち 6時間56分45秒 という周期で、+1 の部分が溜まって 5*HZ と一致します。この周期は、mackerel-agentのメトリック収集間隔である60秒の倍数ではありませんが、プロセスを開くタイミングとloadavgの更新が (0.003秒ずれますが) ほぼ重なる現象が6時間57分ごとに起きるのです。

HZ が250の環境では、5*HZ+1 を1250回繰り返すと 6255秒 すなわち 1時間44分15秒 となります。この周期でloadavgが上がってもよいはずですが、mackerel-agentのメトリック収集タイミングと0.012秒ずつずれていくのが無視できません。60秒の倍数となるのはさらに4倍、つまり6時間57分周期で、mackerel-agentのメトリック収集のタイミングとぴったり重なります。私の検証環境では HZ=250 でした。エントリー冒頭のグラフを見ると、確かに6時間57分の周期で高さの揃ったピークが立っていることがわかります。さらに、このピークの1時間44分前後で小さなピークが立っているところがあるのも見て取れます。これは HZ が250であることに由来する現象です。

loadavgの更新間隔はなぜぴったり5秒間隔の更新ではないのでしょうか。 Linuxの中では様々なプロセスが独自の周期で処理を行っています。 例えば5秒間隔で処理を行うようなプロセスがあると、loadavgの再計算タイミングとぴったり一致することが起こる可能性があります。 意図せずタイミングが合致してloadavgが上昇する現象が起きるのを防ぐために、周期を5秒から少しずらしているのです。 この経緯は、5*HZ1足すことになったパッチのコミットメッセージや、メーリングリストを読むとわかります。

Linuxにおけるloadavgの更新間隔は、意図的に5秒から少しずれています。この少しのずれが溜まっていき、約6時間57分の周期で60秒の倍数となります。mackerel-agentは60秒ごとにプラグインのプロセスを開いており、このタイミングがloadavgの再計算タイミングと合う現象が周期的に起こります。これが、mackerel-agentを入れるとloadavgが定期的に上昇する現象の原因です。この現象は、collectdTelegrafなど、他のモニタリングツールでも報告されています。

参考文献


  1. 係数の和が1であることを確かめることができます。加重平均であるための必要条件です。

  2. このエントリーの HZ はカーネルのタイマー周波数 CONFIG_HZ であり、ユーザーランドの周波数 USER_HZ と区別する必要があります。 getconf CLK_TCK/proc/stat から得られる値は USER_HZ であり、x86では100と決まっています。カーネルのタイマー周波数は grep "CONFIG_HZ=" /boot/config-$(uname -r) で調べるか、 watch -n1 "grep ^jiffies /proc/timer_list | head -n1" の増え方で見ることができます。

  3. 分岐の処理は、まったくプロセスがない状態で 0.0、プロセスが常に一つある状態で 1.0 となるようにするための処理です。この処理が全くなければいつまで経ってもloadavgが 1.0 になりませんし、分岐なしに常に足すという処理にしてしまうと、idle状態で 0.0 になりません。かつては 0.5 相当を足してから割ることで四捨五入になっていたのですが、idle状態で 0.0 にならない問題が指摘されて、プロセス数が増えているときだけ切り上げする形になっています。詳しくはパッチメーリングリストを参照してください。

SSL証明書の有効期限を監視できるチェックプラグインを追加しました ほか

こんにちは。Mackerelチーム CRE の三浦(id:missasan)です。

Mackerel はこれまで毎週リリースを目標に開発を進めてきました。 実はこのリリースで197週連続リリース達成となりました!

200週達成まで、あと3週と迫っています。はやくも社内ではお祝いパーティーの準備が始まりつつあります。

今からちょうど2年ほど前、100週達成のときを振り返ってみると、Mackerel ユーザーグループが発足したタイミングでもありました。

mackerel.io

200週達成に向けて、記念になるようなリリースも検討しておりますので、ぜひ楽しみにお待ちください!

それでは、今週のアップデート情報です。

Mackerel 関連 OSS をアップデートしました

go-check-plugins v0.21.0

  • [check-ssl-cert] SSL証明書の有効期限を監視できるチェックプラグインを追加しました。
  • [check-ntpoffset] ntpサーバを指定してオフセットを確認できるようになりました。
  • [check-mysql] socketファイルを指定するオプションを追加しました。

コントリビュートいただいたみなさま、ありがとうございました。

TLS1.0による通信を停止しました

mackerel.io

以前よりお伝えしていましたとおり、本日(6月6日) TLS1.0による暗号化通信を停止しました。

TLS1.1以上に対応していない、古いOSやブラウザからmackerel.io の閲覧ができなくなります。また、古いOSや、OpenSSL環境からMackerel APIを利用できなくなります。

Mackerelが正式にサポートしている環境*1 にてご利用いただければと思います。TLS1.1以降未対応の場合、対応済みの環境に移行してください。

この度はご迷惑をおかけしますが、安全な環境でサービスをご利用いただくための対応であることをご理解いただければと思います。

API からサービスの作成・削除ができるようになりました

こんにちは。Mackerelチーム CRE の三浦(id:missasan)です。

先週は AWS Summit 2018 Tokyo に出展してきました。 会場は大賑わいで、ブースに立ち寄ってくださる方もひっきりなしといった様子でした。 ビジネスチームだけでなく、エンジニアもMackerelのユーザ層の方々の生の声が聞けるすばらしい機会になりました。

f:id:mackerelio:20180604145155j:plain プロダクトオーナーの松木がミニセッションをしました。 たくさんの方にお立ち寄りいただきました。

f:id:mackerelio:20180604143541j:plain 前回のリリースブログで実物をご紹介できていなかった新しいノベルティの扇子です。

次回は、AWS Summit 2018 Osaka に出展予定です。 普段なかなかお会いできない、関西地方の方々にお会いできることもとても楽しみです!

それでは、今週のアップデート情報です。

API からサービスの作成・削除ができるようになりました

これまで GUI から設定可能だったサービスの作成・削除が API からも実行できるようになりました。 サービスの作成を自動化していただきやすくなりました。 たとえば、API を使ってサービスメトリックを投稿する際に新しいサービスを作成したいようなときにも、すべてAPIから実施していただけます。

詳細は以下をご覧ください。

mackerel.io

グラフ定義からメトリック系列が削除できるようになりました

こんにちは。Mackerelチーム CRE の三浦(id:missasan)です。

今週は AWS Summit 2018 Tokyo にブース出展します。

www.awssummit.tokyo

新しいノベルティ 扇子 も当日ブースで配布予定なので、みなさまぜひお立ち寄りください! 実物の仕上がりは当日のお楽しみです。

f:id:mackerelio:20180528141255p:plain

それでは、今週のアップデート情報です。

グラフ定義からメトリック系列が削除できるようになりました

ホスト詳細のカスタムメトリックと、サービスメトリックのグラフ定義からメトリック系列を削除することができます。新しいメトリックが投稿されると再度メトリック系列が作成されます。

サービスメトリックのグラフで不要な系列がある場合のお掃除にお使いください。

以下、手順のご紹介です。

グラフ定義一覧からの変更

[カスタムメトリック] というカテゴリ表示の横 [設定] をクリックします。

f:id:mackerelio:20180528140319p:plain

各グラフ定義の横 [編集] をクリックします。

f:id:mackerelio:20180528140115p:plain

削除したいメトリック系列の [x] をクリックします。

f:id:mackerelio:20180528140619p:plain

個別のグラフ定義から

各グラフ右上の [グラフ定義] の設定ボタンをクリックします。 (削除できるのは、カスタムメトリックとサービスメトリックです。)

f:id:mackerelio:20180528140645p:plain

削除したいメトリック系列の [x] をクリックします。

f:id:mackerelio:20180528140832p:plain