Prometheus 2.0 + goofys + Amazon S3

# # Prometheus Advent Calendar 2017 7日目
の記事です

# # Prometheusのストレージについて
Prometheus serverのローカルストレージはクラスタリングやレプリケートされません。なので、耐障害性や長期保存を実現する構成を検討すると[Remote storage integration](https://prometheus.io/docs/prometheus/latest/storage/#remote-storage-integrations)を導入したり、Prometheusを複数台同時稼働させてヒストリ／トレンド用のサーバを別に用意したり、方法はいくつかあると思いますが、S3にデータを保管できれば、少なくともクラウド環境においては、Prometheusのストレージが抱える課題は解決するのでは？（パフォーマンスは一旦置いておく）と思って、S3に保存できるのかどうかを試してみました。

# 結論
だめでした。

だめでしたが、そこにいたる経過だけでも残しておこうと本記事を書きます。

検索しても同様な記事が出てこないのが、そんなのはなからダメに決まっているから誰もやっていない、のか、たまたま誰も記事に残していなかったから、のどちらなのかな。

# # やったこと

- Prometheus serverの導入
- goofysの導入
- S3バケットの作成
- EC2インスタンスにS3バケットをマウント
- `--storage.tsdb.path`にマウントポイントを指定

# # goofysの導入からマウントまで
goofysを導入してマウントさせるところまでは、情報が豊富なので調べながら実施。
テスト用に `test-for-prometheus` という名前のバケットを作成しています。

```bash:パッケージのインストール
$ sudo yum install golang fuse
```

```bash:インストール
$ export GOPATH=$HOME/go
$ echo $GOPATH
$ go get github.com/kahing/goofys
$ go install github.com/kahing/goofys
```

```bash:マウント
$ mkdir ~/mount-goofys
$ ./go/bin/goofys test-for-prometheus ~/mount-goofys
$ df -hT
ファイルシス        タイプ   サイズ  使用  残り 使用% マウント位置
/dev/xvda2          xfs         10G  4.3G  5.8G   43% /
devtmpfs            devtmpfs   471M     0  471M    0% /dev
tmpfs               tmpfs      496M     0  496M    0% /dev/shm
tmpfs               tmpfs      496M   13M  483M    3% /run
tmpfs               tmpfs      496M     0  496M    0% /sys/fs/cgroup
tmpfs               tmpfs      100M     0  100M    0% /run/user/1000
test-for-prometheus fuse       1.0P     0  1.0P    0% /home/ec2-user/mount-goofys
```
作成したバケットにマウントできていることが確認できました。

# # Prometheusを起動してみた
EC2 にS3をマウントした状態で、ストレージのパスにマウントポイントを指定してPrometheus を起動します。

パスは`/home/ec2-user/goofys`です。

```bash:Prometheusの起動
./prometheus --storage.tsdb.path=/home/ec2-user/goofys &
```

```bash:起動後のメッセージ
level=info ts=2017-12-04T15:22:44.518225058Z caller=main.go:215 msg="Starting Prometheus" version="(version=2.0.0, branch=HEAD, revision=0a74f98628a0463dddc90528220c94de5032d1a0)"
level=info ts=2017-12-04T15:22:44.518333843Z caller=main.go:216 build_context="(go=go1.9.2, user=root@615b82cb36b6, date=20171108-07:11:59)"
level=info ts=2017-12-04T15:22:44.518368849Z caller=main.go:217 host_details="(Linux 3.10.0-693.5.2.el7.x86_64 #1 SMP Fri Oct 13 10:46:25 EDT 2017 x86_64 ip-10-0-0-253.ap-northeast-1.compute.internal (none))"
level=info ts=2017-12-04T15:22:44.521532251Z caller=web.go:380 component=web msg="Start listening for connections" address=0.0.0.0:9090
level=info ts=2017-12-04T15:22:44.525475101Z caller=main.go:314 msg="Starting TSDB"
level=info ts=2017-12-04T15:22:44.527198442Z caller=targetmanager.go:71 component="target manager" msg="Starting target manager..."
level=error ts=2017-12-04T15:22:45.000988247Z caller=main.go:323 msg="Opening storage failed" err="open DB in /home/ec2-user/goofys: Lockfile created, but doesn't exist"

[1]+  終了 1                ./prometheus --storage.tsdb.path=/home/ec2-user/goofys
```

```bash:エラーメッセージ抜粋
msg="Opening storage failed" err="open DB in /home/ec2-user/goofys: Lockfile created, but doesn't exist"
```

lockfileに関するエラーがでました。エラーの根本原因を解消する方法がわからなかったので、lockfileを生成しないオプションをつけて回避してみました。

```bash:no-lockfileオプションをつけてPrometheusを実行
./prometheus --storage.tsdb.path=/home/ec2-user/goofys --storage.tsdb.no-lockfile
```

回避実行後、問題なく動き出したのでいけるかもと思ったのですが、しばらくしてcompaction処理に関するエラーが出力されました。やっぱりだめでした。


```bash:起動後のエラー
level=info ts=2017-12-04T15:17:31.605759686Z caller=compact.go:361 component=tsdb msg="compact blocks" count=1 mint=1512400200000 maxt=1512400500000
level=error ts=2017-12-04T15:17:33.361261637Z caller=db.go:260 component=tsdb msg="compaction failed" err="persist head block: rename block dir: rename /home/ec2-user/goofys/01C0H1N1AN3A5X0MK74PRSAY9M.tmp /home/ec2-user/goofys/01C0H1N1AN3A5X0MK74PRSAY9M: directory not empty"
level=info ts=2017-12-04T15:17:34.361568694Z caller=compact.go:361 component=tsdb msg="compact blocks" count=1 mint=1512400200000 maxt=1512400500000
level=error ts=2017-12-04T15:17:35.814231038Z caller=db.go:260 component=tsdb msg="compaction failed" err="persist head block: rename block dir: rename /home/ec2-user/goofys/01C0H1N40SMRS10YJMVJPWPJPM.tmp /home/ec2-user/goofys/01C0H1N40SMRS10YJMVJPWPJPM: directory not empty"
level=info ts=2017-12-04T15:17:37.814513215Z caller=compact.go:361 component=tsdb msg="compact blocks" count=1 mint=1512400200000 maxt=1512400500000
level=error ts=2017-12-04T15:17:38.578344691Z caller=db.go:260 component=tsdb msg="compaction failed" err="persist head block: rename block dir: rename /home/ec2-user/goofys/01C0H1N7CP6E80WWEJK8N2D7KY.tmp /home/ec2-user/goofys/01C0H1N7CP6E80WWEJK8N2D7KY: directory not empty"
level=info ts=2017-12-04T15:17:42.580103661Z caller=compact.go:361 component=tsdb msg="compact blocks" count=1 mint=1512400200000 maxt=1512400500000
level=error ts=2017-12-04T15:17:43.965570722Z caller=db.go:260 component=tsdb msg="compaction failed" err="persist head block: rename block dir: rename /home/ec2-user/goofys/01C0H1NC1M4QWZC9WSR0BCWB2H.tmp /home/ec2-user/goofys/01C0H1NC1M4QWZC9WSR0BCWB2H: directory not empty"
level=info ts=2017-12-04T15:17:51.965865517Z caller=compact.go:361 component=tsdb msg="compact blocks" count=1 mint=1512400200000 maxt=1512400500000
level=error ts=2017-12-04T15:17:53.678202798Z caller=db.go:260 component=tsdb msg="compaction failed" err="persist head block: rename block dir: rename /home/ec2-user/goofys/01C0H1NN6XEEK8NBCYX0EQFXW6.tmp /home/ec2-user/goofys/01C0H1NN6XEEK8NBCYX0EQFXW6: directory not empty"
level=info ts=2017-12-04T15:18:09.678508478Z caller=compact.go:361 component=tsdb msg="compact blocks" count=1 mint=1512400200000 maxt=1512400500000
level=error ts=2017-12-04T15:18:10.986053949Z caller=db.go:260 component=tsdb msg="compaction failed" err="persist head block: rename block dir: rename /home/ec2-user/goofys/01C0H1P6GENM7ZV34AQ1FNWC8P.tmp /home/ec2-user/goofys/01C0H1P6GENM7ZV34AQ1FNWC8P: directory not empty"
```

compaction処理の中で、blockディレクトリをrenameする処理が失敗しているよう。

compaction処理が正常に走らないのですが、Prometheus自体は動き続けていますので生データはどんどん蓄積されていきます。compactionされないtmpディレクトリが延々と生成されます。ディレクトリ名にtmpとついているものの、中身はいつものblockディレクトリのそれと同じであり、データ自体も問題ないようです（クエリを投げて、それらしい値が返ってきているので）。内部的には、tmpというblockを生成して、リネームしているんだなというのがわかりました。

```
block名.tmp -> block名
```

S3のディレクトリ（オブジェクト）は、中にファイルが存在しているとmvできない仕様ということで、これはもうどうしようもないなという感じでした。どなたかもし解決法ご存知でしたら教えてください。


```bash:block名.tmpディレクトリたち
drwxr-xr-x. 2 ec2-user ec2-user   4096 12月  4 16:37 01C0H0YA135H8P219CH1RXWWHP.tmp
drwxr-xr-x. 2 ec2-user ec2-user   4096 12月  4 16:37 01C0H105VT3VJP7TYC3S6H9XXW.tmp
drwxr-xr-x. 2 ec2-user ec2-user   4096 12月  4 16:37 01C0H121PKN8WV8G06Q0DJ08X6.tmp
drwxr-xr-x. 2 ec2-user ec2-user   4096 12月  4 16:37 01C0H13XNQYMZX82WX5H477HFN.tmp
drwxr-xr-x. 2 ec2-user ec2-user   4096 12月  4 16:37 01C0H15T7FFQPKTTAC5BHDRD0Z.tmp
drwxr-xr-x. 2 ec2-user ec2-user   4096 12月  4 16:37 wal
```