All Articles

EC2上でffmpegを動かすと強制終了してハマった話

EC2上でffmpegを動かす時の注意点

社内の開発で最近流行りの動画を扱う機能を実装していたんですが、EC2インスタンス内で稼働しているDocker Container内でffmpegを使うと、結構な確率でプロセスが強制終了する問題に遭遇しました。 (さらに、一度終了するとメモリリークするのかどんどん失敗頻度があがるっぽい) m4.largeのスペックでも起きるし、最初はパラメータの問題かffmpegの問題だと踏んでかなり時間をかけて調べてたんですが、的外れでした。何の事はない、OOM-KIllerにやられてたのでした。

tail -f /var/log/messages
...
Memory cgroup out of memory: Kill process 11587 (ffmpeg) score 136 or sacrifice child
Killed process 11587 (ffmpeg) total-vm:540752kBundefined anon-rss:69412kBundefined file-rss:0kB

うん、殺されてた。というか先にこのログ見ろよって話なんですけどね…

中のソースコードまで見てないけど、ffmpegはエンコード実行時にメモリをオーバーコミットしてるっぽくて、メモリが不足し始めるのが原因かなって思います。

参考:http://passingloop.tumblr.com/post/11957331420/overcommit-and-oom-killer さらに、Amazon Linuxではswap領域が用意されないので(これが直接的な問題でした)、OOM-Killerの標的になるようです。

なので、EC2インスタンスの起動時にSwap領域を作ればffmpegは強制終了しなくなりました。具体的にはcloud-initで、

#cloud-config
bootcmd:
- cloud-init-per instance $(fallocate -l `cat /proc/meminfo | grep “MemTotal” | awk ‘{print $2}’`k /swap.img)
- cloud-init-per instance $(mkswap /swap.img)
- cloud-init-per instance $(swapon /swap.img)

という感じで、起動時にメモリと同量のSwap領域を作ります。 http://dev.classmethod.jp/cloud/ec2linux-swap-bestpractice/ を大いに参考にさせていただきました。なお、m4.largeではインスタンスストアは指定できないので、仕方なくEBS上に作成しました。起動して確認すると、

$ free
             total       used       free     shared    buffers     cached
Mem:       8179480    2218940    5960540        432     191844    1440456
-/+ buffers/cache:     586640    7592840
Swap:      8179476      30532    8148944

作成されていますね。ただし、AutoScaling Groupに対して設定するには、起動設定を作りなおさないといけなくて、これがとても面倒でした…。

オンプレミスなサーバでやってると、当然のようにSwap領域は準備されているものなので、自分もそう思い込んでいました。反省。AWSでffmpegでハードなエンコードをする時はこの設定を行うことを推奨します。