Apache のアクセスログでオブジェクトサイズが "-" になってた [cloudpack OSAKA blog]
ナスです。
Cloudwatch logs のログを Elasticsearch Service に転送するの、簡単でいいですね。対象のロググループのアクションで、「Stream to Amazon Elasticsearch Service」を選べばいいだけですから。
docs.aws.amazon.com
でも、それで作成される Lambda Function が完璧かというとそうでもありません。残念ながらいろいろと調整しないといけないです。というか本番環境でそのまま使えた試しがまだ一回もないです… 使い方が悪いのかな。
Apache のアクセスログだけたまにエラーで転送されない
という事象に出くわしました。本当にたまにです。Elasticsearch Service に転送する Lambda のログを見ると、こんなエラーでした。
2017-04-19T00:00:00.700Z xxxxxxxxxxxxxx Failed Items: [ { "index": { "_index": "cwl-access_log-2017.04.19", "_type": "/var/log/httpd/access_log", "_id": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", "status": 400, "error": { "type": "mapper_parsing_exception", "reason": "failed to parse [bytes]", "caused_by": { "type": "number_format_exception", "reason": "For input string: \"-\"" } } } } ]
ちなみにログ転送する際に定義したフィルタは↓これです。
[host, id, user, date, request, status, bytes, other]
bytes に入れようとした値が -(ハイフン) だったので、それ数値じゃねーよ!って言われてます。
対処は簡単
対処法は 2 つあります。
1 つは、Lambda で bytes にあたる値が “-” だったら 0 にする。もう 1 つは、httpd 側でログフォーマットを変更する。です。
httpd のログフォーマットについては、ここをみれば ok です。
ログファイル - Apache HTTP サーバ バージョン 2.2
該当の説明を見ると、
この最後のエントリはクライアントに送信されたオブジェクトの、 応答ヘッダを除いたサイズを表します。コンテントがクライアントに送られなかった 場合は、この値は “-” になります。コンテントが無い場合に “0” をログ収集するには、%b ではなく %B を使ってください。
とありますので、ログフォーマットを %B に変更してやればいいわけです。結局、Lambda 側で調整することにしたので、httpd のログフォーマットで調整できるかどうかは試していませんが、たぶんできると思います。
この件で思ったのは、ログファイルごとにログフォーマットがちゃんと揃ってないと Elasticsearch Service に転送する時にエラーが出まくることになるので、注意が必要だということです。ミドルウェア等のログフォーマットはだいたい揃っていると思いますのでいいのですが、自社や他ベンダーが開発したアプリケーションのログも Elasticsearch Service に転送するなら、ログフォーマットがどうなっているかよく調べたほうがいいと思います。
Amazon Elasticsearch Service でデータが保存されなくなった話 [cloudpack OSAKA blog]
ナスです。
またまた Elasticsearch の話です。今回は Amazon Elasticsearch Service にデータが保存されなくなった話です。Amazon 特有の話なのかそうでないのかわかりませんが、実際に起こったので書いておきます。
気がついたら何も保存されていなかった
初期構築を終えて数日運用した後に Elasticsearch Service の様子を見てみたら、Indices タブにあるべきインデックス名が全く出ていませんでした。クラスタ数は 1 で設定してあるので、ステータスは常に Yellow だったので、これが原因とは思えない。かといってストレージの空きはわりとある。って状況で、最初はなかなか原因がわかりませんでした。
Monitoring タブで見れるグラフがなんかおかしい
Elasticsearch Service のグラフを見ていると、なんか気になる形を発見。Write IOPS が 0 だ…
この状況を基にいろいろ調べたら、このドキュメントが出てきました。
AWS サービスエラー処理 - Amazon Elasticsearch Service
なんかメモリくさいな… と思って、CloudWatch で Write IOPS と JVMMemoryPressure のメトリクスを見るとこうなってました。
JVMMemoryPressure が92,93% あたりを超えると Write IOPS が 0 になり、JVMMemoryPressure が下がると同時に Write IOPS も増えていました。
原因は?
ドキュメントには、
t2 インスタンスでは、[JVMMemoryPressure] メトリクスが 92% を超えた場合、クラスターが赤の状態になるのを防ぐため、Amazon ES はすべての書き込みオペレーションをブロックすることによる保護メカニズムをトリガーします。
と書いてありますが、この環境ではデフォルトの m4.large を使っていますので、どうやら t2 だけに限らないっぽいです。もしかしたらデフォルトのインスタンスサイズ& t2 がこれに引っかかるという可能性もあります。(他のインスタンスタイプでは試せてないのでわかりません
どう対処したのか?
今回は、データが多すぎてメモリも多く使われたのだと仮定して、先日書いた↓の対応を行いました。
nasrinjp1.hatenablog.com
不要なデータを消した直後から、JVMMemoryPressure も下がり、無事に Write IOPS もガンガン上がり始め、ようやくデータが保存されていきました。
他には、クラスタ数を増やす、インスタンスのサイズをあげる、等の選択肢もありますが、不要なデータがたまりすぎている状況なら素直に不要データを削除するのがいいと思います。後は、JVM 関連のパラメータ調整くらいですかね。
Elasticsearch Service はマネージドサービスですが、ちゃんと使い方や特性を理解した上で運用しないと痛い目にあうなと思いました。マネージドサービス=何も気にしなくても運用できる、ではないことを再認識させられました。