Docker 初心者は phusion/baseimage-docker を使おう

tl;dr

Docker 初心者は phusion/baseimage-docker をベースイメージとして使おう。
色々と便利だしハマる機会が減る。

遅ればせながら Docker 入門した

新たにアプリケーションを作る機会があり、週末を利用し遅ればせながら Docker について調べた。
すでにネット上に多くの入門記事がアップされていたおかげで導入自体は簡単にできたが、「まともな」イメージを作成しようとすると壁にぶちあたることになった。たとえば…

  • コンテナに ssh 接続するにはどうすればいいの?
  • syslog 起動してないの?
  • cron は?
  • 解析のために fluentd とか newrelic agent とかも入れたいな…

いずれも 1 コンテナ 1 プロセスしか許容されていないという思い込みによるもので、Docker 入門者の多くが通る道なようだ。

公式ドキュメントをちゃんと読めば複数プロセスを生やすために Supervisor を利用する方法が紹介されている。

Using Supervisor – Docker Documentation

まぁ、これはこれで良いのだけれど個人的には phusion/baseimage-docker の利用をオススメしたい。

複数プロセス管理以外にも Docker を使う上で便利な各種ツールや様々な問題を回避するための仕組みが用意されている。

積極的に巨人の肩に乗るべきだ。特に自分のような初心者は。

phusion/baseimage-docker とは

phusion/baseimage-docker(以下 baseimage-docker) とは Phusion Passenger という有名なソフトウェアを作成している Phusion が開発を続けている Docker イメージだ。

Phusion Passenger 自体は Rails アプリ開発者であれば一度は目にしたことがあると思う。Nginx や Apache の設定ファイルにちょろっと書くだけで、それらがアプリサーバに変わって動作してくれるという画期的なソフトウェアだ。公式サイトを見たら Python や Node.js にも対応しているらしい。知らなかった。

話がそれた。

baseimage-docker の利点として先にも述べたように、Docker を利用するにあたってぶち当たるであろう様々な問題を回避するための仕組みが用意されている。

いくつか紹介したい。

  • 正しい init プロセス
    Unix プロセスモデルでは init プロセス (PID 1) はすべての孤児プロセス(親プロセスが終了したプロセス)を回収し、正しく終了するという責務がある。しかしほとんどの Docker コンテナはこれを正しく行えていないために、ゾンビプロセスが発生しうる。
    また、 docker stop は 全プロセスを終了するために SIGTERM を init プロセスに送るのだが、残念ながらほとんどの init システムはハードウェアシャットダウンを前提としており Docker 内で正しく動作しない。これによりプロセスは SIGKILL によって殺され、正常終了せず、ファイルの破損が発生しうる。
    baseimage-docker は /sbin/my_init という init プロセスを利用することによってこれらの問題に対応する。

  • syslog-ng
    syslog はどんな場合でも必要だろう。baseimage-docker にははじめから syslog-ng が同梱されている。

  • SSH Server
    Docker には nsenter というツールが用意されているが、いくつか問題もある。使い慣れた SSH が利用できるのであれば幸せだ。baseimage-docker はデフォルトで SSH を利用でき、気になる場合には実行しないことも可能だ。(後述)

  • cron
    あると何かと役に立つだろう。

  • runit
    複数プロセスの管理に利用する。起動スクリプトをちょろっと書いて特定フォルダにいれるだけで良いのが有り難い(後述)

  • setuser
    特定のコマンドを別ユーザで実行するための便利ツール。 su より使いやすい。

init プロセス云々で分かるように Docker を使おうと思えば、一定の UNIX の知識を要する。これが過渡的なものなのか、そのうち解決されて誰でも気軽に使えるようになるのかは分からないけれど。

以下ではより詳しく baseimage-docker について紹介したい。

複数プロセスを管理する

baseimage-docker では /etc/service/<サービス名>run という名前をつけたシェルスクリプトをおくだけで、デーモンとして起動してくれるようになる。

公式よりサンプルを引用。 memcache ユーザで memcached を起動するスクリプト。

1
2
3
4
5
6
7
8
9
### In memcached.sh (make sure this file is chmod +x):
#!/bin/sh
# `/sbin/setuser memcache` runs the given command as the user `memcache`.
# If you omit that part, the command will be run as root.
exec /sbin/setuser memcache /usr/bin/memcached >>/var/log/memcached.log 2>&1

### In Dockerfile:
RUN mkdir /etc/service/memcached
ADD memcached.sh /etc/service/memcached/run

注意

  • デーモンは(デモナイズしたりフォークしたりするのではなく)フォアグラウンドで起動すること
  • スクリプトは実行許可を与えること(chmod +x

起動時にスクリプトを実行する

baseimage-docker では /etc/my_init.d/ にシェルスクリプトをおくだけで、起動時に実行してくれる。

公式よりサンプルを引用。 起動した時間を記録するシンプルなスクリプト。

1
2
3
4
5
6
7
### In logtime.sh (make sure this file is chmod +x):
#!/bin/sh
date > /tmp/boottime.txt

### In Dockerfile:
RUN mkdir -p /etc/my_init.d
ADD logtime.sh /etc/my_init.d/logtime.sh

注意

  • スクリプトは実行許可を与えること(chmod +x
  • スクリプトは必ず正常終了させること。0 以外の exit コードで終了すると起動に失敗する。
  • スクリプトはデーモンプロセス起動 に実行される

環境変数の管理

baseimage-docker は環境変数を /etc/container_environment にいくつかの形式でファイルとしてダンプしてくれる。 これの何が嬉しいか。Nginx など子プロセスを生成する際にそれらに環境変数を隠してしまうサービスを利用する場合に、元々の環境変数を利用できるようになるのだ。

詳しくは wiki を参照されたい。

phusion/baseimage-docker

SSH で接続する

Docker に sshd を起動するかどうかは結構議論の分かれる部分だと思う。Immutable という観点では理想的には不要なのだろう。 が、現実的には管理のために接続の手段は用意しておいた方が便利だろう。セキュリティという観点では別のレイヤー(VPC 上のセキュリティグループなど)で担保できると思う。

baseimage-docker ではデフォルトで sshd が起動している。

sshd を起動したくない場合は以下を Dockerfile に追記しよう。

Dockerfile
1
RUN rm -rf /etc/service/sshd /etc/my_init.d/00_regen_ssh_host_keys.sh

nsenter の利点と欠点

sshd を起動するまでもなく nsenter というツールを利用すれば、docker コンテナ内でコマンドを実行することができる。

jpetazzo/nsenter

利点

  • コンテナ内で sshd の起動が不要
  • ssh キー設定が不要
  • どんなコンテナでも利用可能

欠点

  • nsenter によって実行されたプロセスは通常時と少々異なる振る舞いをする。例えば、コンテナ内のプロセスから kill することができない。子プロセスについても同様。
  • nsenter プロセスがシグナルによって終了した場合(例: kill コマンドによって)nsenter によって実行されたコマンドは殺されないし、クリーンアップも行われない。
  • 別のツールを学ぶ必要がある
  • Docker host の root 権限が必要
  • nsenter ツールが必要

まぁ、でも個人的には新たなツールをいれたくないので ssh で良いかなと思っている。

docker-bash ツール

ssh で接続する際の一般的な流れは、こんなものだろう。

  1. docker ps で実行中のコンテナ ID を調べて
  2. docker inspect -f "" <ContainerID> で IP 調べて
  3. ssh -i /path/to/yourkey root@CONTAINER_IP_ADDR

しかし Dockerfile を書きつつ環境構築している際にはこの手順がヒジョーに煩わしくなる。

docker-bash ツールを使えば手順はもっと単純になる。

インストールも簡単だ。

1
2
3
curl --fail -L -O https://github.com/phusion/baseimage-docker/archive/master.tar.gz && \
tar xzf master.tar.gz && \
sudo ./baseimage-docker-master/install-tools.sh

実行するには

1
docker-bash YOUR-CONTAINER-ID

で SSH 接続できる。

直近のコンテナ ID を取得するエイリアスを定義するともっと便利だ。

1
alias dl="docker ps --latest --quiet"

上記を .bashrc などに定義すると、

1
docker-bash `dl`

一発で接続できる。

終わりに

Docker はクセが強く、また現時点では UNIX に関する深い知識が要求される。 初心者が一からイメージを作るのは、練習であれば全く問題ないが、 実用を考えるのであれば、とりあえずは phusion/baseimage-docker からイメージを作ってみよう。 オリジナルイメージを作成するのは慣れてからでも、Docker のバージョンアップを待ってからでも遅くないハズだ。

また、Ruby や Python や Node.js を利用する場合には、同じく Phusion が用意している phusion/passenger-docker を利用すると良い。 これは phusion/baseimage-docker を拡張したもので、様々な便利ライブラリが同梱されている(ruby, python, node.js, git, その他言語毎に必要なライブラリ)。

Docker とは別に Nginx + Phusion Passenger でも色々とハマるのでそのうち記事を書きたいと思う。

エンジニアから見た WWDC 2014 雑感

ハードウェアの発表はなかったんですね。
しかし、エンジニア的には衝撃的&ワクワクする内容が多かった印象です。

衝撃

Swift

冒頭から衝撃的。
朝起きたら Objective-C が死んでいた。 Apple がハシゴを外すのはもはやお家芸か。

パッと見た限り、LL っぽくて書きやすくなりそう。 インタラクティブシェルもあるみたい。いいねいいね。 Objective-C とも同居できるようなので大きな混乱はないのでは。

パフォーマンス面でもネイティブコードに変換されるそうなので、問題なさそう。RubyMotion と同じ仕組みなのかな。

Swift – Apple Developer

追記: 2014-06-03 現在「swift lang」でググると別の言語がトップに表示される。
しばらくはネタとして揶揄されるんだろうな。罪のない言語を死滅においやる Apple △。

Apple「オレがルールだ!」

swift-lang.org

Extensibility

iOS アプリ間連携がよりスムーズになる。
Cocoa App 開発でよくつかう Scripting Bridge 機能の iOS 版か。 今後は iOS アプリ開発も他アプリとの連携を考えることが大切になりそう。

CloudKit

サーバサイドでの認証、ストレージ、検索機能を Apple が提供。基本無料。 開発者としては心理的、金銭的、時間的負担が下がりメリットありまくり。Apple ロックインが加速する。BaaS 死亡のお知らせか。

ワクワク

AirDrop の Mac <–> iOS 対応

いままでは iOS 同士または Mac 同士限定だった AirDrop が Mac <–> iOS 間で動作可能に。アプリ開発時にキャプチャとって Mac に送るということが多いので結構うれしい。

家族間共有

iPhone はパーソナルユースに。iPad はリビングに 1 台というシナリオがしっくりくると思うのでとても良い。

HealthKit

まずは SDK から公開。ハードも同時にくるかと思ったが。 健康アプリがますます増えそうで良い。 BLE を利用したガジェットとの連携も楽しみである。 先進的な病院へ自身の健康情報を共有するような未来は近いかもしれない。

Shazam 統合

ホームボタン長押しで曲名判明 –> iTunes Store で購入とシナリオは多くなりそうでとても嬉しい。音楽体験が変わりそう。

TestFlight 機能追加

詳細はわからないけれど、大好きなサービスなので期待。

HomeKit

これも詳細分からないけれど、Siri との連携が用意なら夢は膨らみそう。シームレスな体験が期待できそう。

その他

  • Yosemite はフラットな UI
    お、おう
  • タイトルバーはコンテンツに応じて変わる半透明
    うん
  • iMessage アプリをシームレスに、機能追加。Mac から電話もできるぞ!
    早くどこか買収すればよかったのに
  • Safari UI & パフォーマンス改善
    使わない
  • Mail UI & パフォーマンス改善
    使わない
  • カレンダー UI & パフォーマンス改善
    使わない
  • 通知センター改善
    使わない
  • QuickType
    使ってみると便利なのかも。
  • フォトアプリ改善
    うん
  • iCloud Drive、容量アップ
    おそらく、使わない
  • AppStore アップグレード
    ASO の会社しばらく大変そうだ
  • Touch ID API
    iPhone 5 なので。ロック画面とアプリ内で 2 段階認証は安心と思いつつ、乱用するとユーザには嫌われそう。
  • Metal & SpriteKit
    多分使わない

Web ディレクターのための iBeacon 入門

2014-05-12 GARAGE AKIHABARA にて、「Web ディレクターのための iBeacon 入門」と題したプレゼンを行いました。

  • iBeacon って最近よく聞くけど何なの?
  • iBeacon を使うとなにが嬉しいの?

などの基本的な知識に加え、今後現場で活かせる知識を得ていただけることを目指しました。

今のトコロ利用されているのは O2O の文脈や展示品の解説などといったシーンが多い印象ですが、 iBeacon の仕様は比較的シンプルであるため扱いやすく、また端末自体も非常に安価なため様々な場面で応用が効くかと思います。
今後どのようなサービスが展開されていくか、とても楽しみですね。

ZowLog 1.2 をリリースしました

ZowLog の新バージョン 1.2 をリリースしました。
#ZowLog のご紹介はこちらから → ZowLog という Mac 用メモツールを作りました

"ZowLog"

"ZowLog"

バージョン 1.2 では Evernote を起動していない状態でもメモを取ることができるようになりました。

また、「フォントサイズを大きくして欲しい」「等幅フォントで編集したい」というご要望にお応えして、編集時のフォントを選択できるようになりました!
#Evernote には標準フォントで書き込まれます

"Change font"

より使いやすくなった ZowLog を是非お試しください。

Mac App Store – ZowLog

いつになったら覚えるの?

いつまでたっても覚えられないのでつくりました。
デスクトップの端っこに置いています。

"mac special key symbols"

command は分かるんだよ。command は。

いつまでたっても覚えられないのでカレンダーにしてみました。
壁に貼って覚えようと思います。

"special key symbols calendar"

大きいサイズの画像はこちらから。ご自由にお使いください。
mac-special-key-symbols-big.png (1200x1200)

ZowLog という Mac 用メモツールを作りました

ZowLog という Mac アプリを作りました。

"ZowLog"

"ZowLog"

ZowLog はすばやくメモを書くためのツールです。Evernote に 1 日 1 つだけノートを作り、メモを追記していきます。

もしあなたが一日中 Mac の前でお仕事をされているのであれば、ピッタリのツールです。

有料です。200円。
売上は我が家のネコのカンヅメ代になります。ニャ。

日常的に Evernote を使ってメモをとられているのであれば、すぐに元を取っていただけると思います。

App Store からダウンロードできます。

Mac App Store – ZowLog

何がうれしいの?

はやいです。思いついたらすぐに起動、メモをとり始めることができます。

1 日に 1 ノート、時刻つきでメモが追記されていくため、自分だけのタイムラインのように使うこともできます。共有ノートブックに保存するよう設定すれば、チーム内の簡易業務日報ツールとして使うこともできるかもしれません。

"ZowLog"

このテのアプリ、iPhone や Android ではたくさんあるのですが、Mac には見当たらなかったので作りました。 私自身ほぼ一日中 Mac の前にいるため、Mac 上で簡単に Evernote にメモできるアプリが欲しかったのです。

外(あまりないですが)では iPhone アプリでメモを書き、オフィスや自宅では ZowLog でメモを書いています。どちらも書き込み先のノートは同じもの。1 日 1 ノートにまとめることでノートブックが散らからないよう意識しています。

快適。

ただし ZowLog を利用するには Evernote が起動している必要があります

この辺のデザインは非常に悩んだところではあります。 とにかくストレスなくサササッと書き込めることを優先し、今の仕様となりました。

「Mac でメモ取るヒトは Evernote の一つや二つ、起動しとるじゃろ。オフラインで使えんくなるのもよぉないしの。」

と、勝手に想像していましたが、Evernote を起動していない状態でも利用したいという声を早速もらっているので今後対応したいと思います。 ブラウザから Evernote を使う人がいるとは。使いにくくないですか。そんなことない?今度使ってみます。

(2014-04-25 追記)
バージョン 1.2 より Evernote が起動していない状態でもメモをとれるようになりました!
ZowLog 1.2 をリリースしました

考えるために書く

"ZowLog"

以下は余談です。

「考えるために書く」という行為がもっと意識されるようになると良いなと思っています。

書いて→伝える、だけではなくて。 書いて→考えて→書いて→考えて→(ループ)。

Facebook や Twitter に少しだけマジメな投稿を書いている時、「へぇ、私ってこんなふうに考えてたのね」と自身の意外な考えに気づいた経験、ありませんか。書いている時は同時に考えてもいるのです。

当たり前のようですけれど、意外と見過ごされがちなのかな、と。
書くことは考えることを強制する力があるみたいです。

例えば「今回の都知事選について」とか「あの話題のサービスを評価してやる」とか。書こうと思うと脳みそグルグル回転しませんか。「お台場に来た!」とか「今日は朝からパンケーキ☆」っていうのはなんていうか、ベツモノな気がしますけれど。

SNS やメールやメッセージングアプリを使うようになって、他人に対して「書く」機会は増えました。自分のために、考えるために「書く」機会が増えても良いんじゃないかなと。

私達の頭の中はとても複雑で、不安定です。フワフワして不透明で、曖昧で移ろいがちです。何かを考えているときにも、あっちが気になり、こっちが気になり、結局何を考えていたんだっけ?と迷子になる。「書く」ことは、そんな嵐の海にも似た荒れる意識の中にゆっくりと沈み込み、静かに自分自身と対話するための良きパートナーとなってくれるでしょう。

伝達の手段として「書く」だけではなく、ふわふらとしたアイディアを一歩一歩踏み固め、まとめるために「書く」ことがもっと認識されると良いと思っています。

シェアする

"ZowLog"

書いて→考えて→書いて→考えて→(ループ)→ 伝える

考えるために書いたメモはごく個人的なモノなので、ある程度まで整理できてしまえば捨ててしまって構わないです。でも、せっかくなら誰かに伝えると世界は少しだけよくなるかも。いいね!されたりリツイートされると承認欲求も満たせて自分も嬉しい。

ボク自身はエンジニアということもあり、普段は技術的なコトガラをメモすることが多いです。どこでハマったか、どうやって解決しようとしたか、面白いツールやライブラリを見つけた、とか。その中でも有用だと思ったことは少しだけ時間をかけてまとめて、Qiita やチーム内の Wiki や Chatwork などにポストしています。

ちょっとしたアイディアやヒトの反応を知りたいものは Twitter や Facebook にポストすることもあります。気持ちを整理するために書く感情的なメモはインターネットにはあまり公開しません。読んでみて気持ちの良いものではないですしね。

ボクは ZowLog + Evernote が一番使いやすいのですが、手に馴染むものであれば何でも良いです。それぞれが使いやすいツールを使うのが一番。紙とペンでもいい。Evernote でも emacs でも Sublime Text でもなんでも (vim でも)。お気に入りのエディタでメモを書いてみましょう!

おわりに

「考えるために書く」というお話は古今東西いろいろなところで話されていて特に目新しい話題ではないかもしれません。悩みがあれば書き出してみなさい、とか、新しい企画を立てるときにはマインドマップを書くとか。でも、そんな身構えなくてももっと自由に書き散らかしていいと思います。悩みが無くても企画を考えるのではなくても、もっと日常的に書いてみませんか。

参考

様々な小説、エッセイ、ブログ記事で「書く」ことによる効果を述べています。

計画について

考えながら走らないと進まないです。

計画は必ず立てないといけないです。
けれど完璧な計画なんてものはあり得なくて、
内外様々な要因によって変更は必ず発生します。

むしろ計画は随時見なおすべきものです。変更を恐れるべきではないです。
計画は自分や他人の見積もりの甘さを責めるためのものではなくて、
プロジェクトを前進させるための道具です。

「やることが全て出揃った!あとはやるだけだ!ヨーイドン!」
理想的ですし、精神衛生上よろしいのですが、現実的ではないです。

先を見ずに行動するのは愚か者ですが、
全てが明らかになってからでしか行動できないのは臆病者です。

考えながら走りましょう。

fluentd -> Elasticsearch 大量データ転送でトラブル

概要

  • fluentd でサービスの情報を転送し、Kibana で分析したい
  • これまでの過去データを一度に放り込みたい
  • データの件数が合わない
  • Kibana でエラーが発生する
  • 各種設定を見直すことで対応可能

背景

長い長いミーティングに疲れ、集中力を擦り減らしたアナタは 無意識のうちにブラウザを起動していました。

去年まで勤めていた会社の同僚がシェアした記事が目に止まります。

「fluentd + Elasticsearch + Kibana で今どきのログ分析!」

感化されやすいアナタはおもむろに VM を立ち上げ環境を構築します。 Web サーバから吐き出されたログはオシャレでイイ感じにチャート化され、 満足したアナタは VM を落とし、再び仕事に戻りました。

しばらく経ったある日のこと、ふと気づきます。 「ログだけじゃなくて、ユーザ属性の分析にもコレ使えそう。」

毎度オレオレ管理ページを作ることに疲れていたアナタは、 さっそくこの思いつきを行動に移しました。

が、簡単にはうまくいきません。 登録されるデータが想定より多かったり少なかったり。 Kibana はエラーメッセージを吐き出したり。 アナタは茨の道に踏み込んでしまったことに気づいたのです。

症状・原因・対策

症状①: 登録される record が少ない

登録されたレコードが想定より少ない。 この場合、様々な原因が考えられます。

原因1: 大量 index 作成の負荷

Kibana はデフォルトでは logstash-YYYY.MM.dd 形式の index を期待しており、 fluent-plugin-elasticsearch もその形式で index を設定します。

今回のように過去のデータを一括で(新規に)登録しようする場合、 日数分の index を作成するために大きな負荷が発生し、 処理に失敗する可能性があります。

その際には以下のような ProcessClusterEventTimeoutException がログに追記されます。

/var/log/elasticsearch/elasticsearch.log
1
2
3
4
5
[2014-01-31 11:57:46,255][DEBUG][action.admin.indices.create] [Mace, Gideon] [logstash-2013.06.13] failed to create
org.elasticsearch.cluster.metadata.ProcessClusterEventTimeoutException: failed to process cluster event (create-index [logstash-2013.06.13], cause [auto(bulk api)]) within 30s
    at org.elasticsearch.cluster.service.InternalClusterService$2$1.run(InternalClusterService.java:239)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1146)
    (...)

また、後述のように Elasticsearch では処理キュー数が閾値を超えた場合、 後続の処理を破棄される設定となっているために、index の作成自体がなされない可能性があります。

通常の利用シナリオではこのように一度に大量の index を作成することはあまりないため、問題になることは少ないでしょう。

対策

今のところ Timeout までの設定値を変更することはできないようです。 あらかじめ必要となる index を作成しておきましょう。

参考

原因2: 処理キューが閾値を超えた場合にリクエストを破棄する

Elasticsearch はデフォルトで閾値を超えたキューを破棄する設定となっています。 例えば index の作成は 50 個まで、bulk 処理は 20 個までといった具合。

メモリの消費を抑え適切に管理するための設定ではあるのですが、 この設定により作られるハズの index が作成されなかったり、 投入されるハズの record が作成されなかったりします。

対策

Thread Pool のキューサイズを変更します。

/etc/elasticsearch/elasticsearch.yml
1
2
3
4
5
6
7
8
# queue_size は実行するスレッドが存在せずペンディングされたリクエスト
# のキューの数の設定に使用します。キューが満杯の状態で
# リクエストが来た際には、そのリクエストは破棄されます。
# 制限をしたくない場合には -1 を設定してください。
threadpool.index.queue_size: -1 # デフォルト 200
threadpool.bulk.queue_size: -1 # デフォルト 50
# threadpool.search.queue_size: -1
# threadpool.get.queue_size: -1

注) サーバのスペック、処理したいデータ量に応じて設定してください。 不適切な設定はメモリの過剰消費によるメモリ不足やスラッシングの原因となる可能性があります。

参考

原因3: データマッピングに失敗している

Elasticsearch は新たに投入される record を解析し、 動的にデータ型を規定します。その後規定された型と合わないデータを 投入しようとすると MapperParsingException が発生します。

特に「日付のようなフィールド」を日付型と認識される可能性が あることに注意してください。

次のログは日付型のフィールドに空文字を設定しようとした場合に出力されました。

/var/log/elasticsearch/elasticsearch.log
1
2
3
4
5
6
7
8
[2014-01-31 12:39:07,907][DEBUG][action.bulk              ] [Nicholas Scratch] [logstash-2013.09.18][1] failed     to execute bulk item (index) index {[logstash-2013.09.18][xxxx_type][xxxxx_id_0000], source[{....}]}
org.elasticsearch.index.mapper.MapperParsingException: failed to parse [xxx_day]
        at org.elasticsearch.index.mapper.core.AbstractFieldMapper.parse(AbstractFieldMapper.java:416)
(...)
Caused by: org.elasticsearch.index.mapper.MapperParsingException: failed to parse date field [], tried both date format [dateOptionalTime], and timestamp number with locale []
        at org.elasticsearch.index.mapper.core.DateFieldMapper.parseStringValue(DateFieldMapper.java:487)
        at
(...)

対策

Elasticsearch の Default Mapping 設定を見直しましょう。 default-mapping.json という設定ファイルを作成することで、 デフォルトのマッピング設定を変更することが可能です。

/etc/elasticsearch/default-mapping.json
1
2
3
4
5
6
7
8
{
    "_default_" : {
        "properties" : {
            "foo" : {"type" : "string"},
            "bar" : {"type" : "string"}
        }
    }
}

参考

症状②: 逆に登録される record が多い

登録されたデータが想定より多い。 fluentd のログにリトライした形跡がある。

原因

Elasticsearch の負荷が高いため、登録処理自体は行われたものの fluentd へのリプライに失敗。その後 fluentd がリトライを試み、 重複してデータが登録されたことが原因の可能性があります。

対策

なかなか難しい問題です… Elasticsearch 側でエラーが発生しないように頑張り、 ある程度の重複の発生を受け入れる or 頑張って削除するのが現実的でしょうか。

参考

症状③: Kibana で エラーが発生する(Parse Failure)

Kibana にて以下のようなエラーが発生する。

Parse Failure [No mapping found for [@timestamp] in order to sort on]

原因

空の index に対して検索を行い処理に失敗している可能性があります。 Kibana が生成するクエリの問題です。

対策

record が存在しない空の index は削除しましょう。

参考

症状4: Kibana で エラーが発生する(Could not contact Elasticsearch)

Kibana にて以下のエラーが発生する。

1
Error Could not contact Elasticsearch at http://x.x.x.x:9200. Please ensure that Elasticsearch is reachable from your system.

また、 Elasticsearch のログには以下のようなエラーが記録される。

/var/log/elasticsearch/elasticsearch.log
1
2
3
4
5
[2014-01-31 13:58:28,444][WARN ][http.netty               ] [Nicholas Scratch] Caught exception while handling client http traffic, closing connection [id: 0xad362931, /x.x.x.x:36389 => /x.x.x.x:9200]
org.elasticsearch.common.netty.handler.codec.frame.TooLongFrameException: An HTTP line is larger than 4096 bytes.
        at org.elasticsearch.common.netty.handler.codec.http.HttpMessageDecoder.readLine(HttpMessageDecoder.java:642)
        at org.elasticsearch.common.netty.handler.codec.http.HttpMessageDecoder.decode(HttpMessageDecoder.java:182)
        (...)

原因

検索対象の index が多く、リクエスト URL の長さが規定値を上回っている可能性があります。

対策

Elasticsearch の max_initial_line_length を設定します。

/etc/elasticsearch/elasticsearch.yml
1
2
(...)
http.max_initial_line_length: 100k

参考

(おまけ)Elasticsearch スニペット

  • 全 index の取得

    curl -XGET http://localhost:9200/_aliases?pretty=1

  • type を指定して取得

    curl -XGET 'http://localhost:9200/_all/my_type/_search?pretty'

  • 全 index の削除

    curl -XDELETE 'http://localhost:9200/_all'

  • type を指定して削除

    curl -XDELETE 'http://localhost:9200/_all/my_type/'

参考

RDBMS と NoSQL の使いわけかた

RDBMS と NoSQL の使いわけの基準について。

議論は出尽くして擦り切れた感があるのだけれども、 ぼく自身の経験から得られた基準をまとめておこうと思う。

適材適所という言葉に従うための基準。

  • 汎用性を考えるとやっぱり RDBMS に分がある
    • どちらを使うべきか迷うなら RDBMS で良い
    • 枯れた技術だし、実績も情報もたくさんある
    • 石を投げれば SQL マスターやパフォチューに苦労した先人達に当たる
  • NoSQL と相性のいいユースケース
    • 使いすてのアプリケーション
      • プロトタイプ
      • キャンペーン
    • モデル(コレクション)の数が少ない
      • 10 個くらいが閾値
      • キャッシュストレージ
      • ログストレージ

「スキーマデザイン考えなくて良い!ひゃっほう!」ってな考えの基での NoSQL の採用は問題の先送りにしかならず、 熱力学第二法則よろしく日々データモデルは複雑化していき、つぎはぎだらけのシステムがあなたのプライベートを殺す。