ディスクフルになる日を予測するスクリプトを書いた

ディスクフルになる日を予測するスクリプトを書いた

ある日、ディスク使用量が閾値に達し、アラートが発生しました。 アラートによって、ディスクの使用率が80%に達した、ということはわかりますが、さて、このアラートにはどのくらい緊急で対応する必要があるのでしょうか?。

ぼくはいつも、この問に答えるためにグラフを眺めて傾きが緩やかだからまだ大丈夫、傾きが急だから急いだほうが良いといった判断をしていました。 これをもうすこし定量的に判断できるようにしたいとおもい、ディスクフルになる日を予測するスクリプトを作成しました。

ディスク使用量の増え方を線形回帰しディスクフルになる日をみつけます。 線形回帰の手法には最小二乗法を利用しました。

どのように実装したかを簡単に説明します。 最初に、ぼくが面倒を見ているサービスでは監視サービスとして mackerel が導入されているので、API でメトリクスを持ってきます。

api_key = os.getenv("MACKEREL_API_KEY")
headers = {"X-Api-Key": api_key}
params = {"name": f"filesystem.{args.partition_name}.used", "from": start, "to": end}

r = requests.get(
    "https://mackerel.io/api/v0/hosts/3d2zGEvSwif/metrics",
    headers=headers,
    params=params
)

次に、最小二乗法で利用できるようにデータを整形します。 x は日付をunixtimeで表現したもの (mackrelからのレスポンスのデフォルトです) とし、y をディスク使用量をGBで表したものにします。

data = r.json()
x = [x["time"]  for x in data["metrics"]]
y = [y["value"]/ 1024 / 1024 /1024 for y in data["metrics"]]

そして、numpy で最小二乗法を計算します。今回は f(x)=ax+b という1次関数で近似します。下記のようなコードになります。

np.polyfit(x, y, 1)

(plofit については ここ を参照してください)

これを関数化し、ディスクフルになる日を、一年後までで検索します。 poly1d という多項式Python の関数として演算可能にするクラスを用います。 下記のようにになります。

val = np.poly1d(np.polyfit(x, y, 1))(x)

さて、以上がうまく動いているかどうかを確認するためグラフにしてみましょう。下記のようなコードです。

plt.figure(num=None, figsize=(10, 4), dpi=80, facecolor="w", edgecolor="k")
plt.scatter(x , y, alpha=0.5, color="blue", s=5)
plt.plot(x, val, label="d=1", color="red")
plt.show

すると、下記のようなグラフとなります。

f:id:happy_siro:20180726190111p:plain

うまく動いていそうですね。

ぼくが知りたいのはディスクフルになる日です。 なので、一年以内にディスクフルになってしまうのかどうかを調べてみましょう。

d = int(time.mktime(time.strptime("2018/7/20", "%Y/%m/%d")))
for i in range(365):
    d = d + 86400
    if np.poly1d(np.polyfit(x, y, 1))(d) > 1024:
        print(np.poly1d(np.polyfit(x, y, 1))(d))
        print(time.strftime('%Y/%m/%d', time.gmtime(d)))
        break;

こうすると、結果は例えば 2018/09/01 などと出ます。 出力された日付により、緊急度高めで頑張るか、のんびりと対応するかが定量的に判断できます。

以上です。