パラボラアンテナと星の日記

あることないこと

ECSにバッチ処理やらせるときにhako oneshotが便利

要約

ECSにバッチ処理をやらせるときに、 hako oneshotを使うと便利です。

hako oneshotを活用する話

先日(10/12)のDockerの勉強会*1にて、hako oneshot を活用する話をしました!

以下は私の職場での活用の一例。の雰囲気の図。

f:id:hoppie:20161016065844p:plain

以下がスライドです。

hakoについてちょっと紹介

github.com

Dockerコンテナのデプロイツールです。ECSに対応。

deployoneshotが主なサブコマンドです。

hako deploy

Dockerコンテナをデプロイする。 使い方はこちらの記事が詳しいです。

so-wh.at

hako oneshot

Dockerコンテナにバッチ処理的なタスクをやらせる。 使い方はこちらの記事が詳しいです。

so-wh.at

hako oneshotの様子

ECSに何かをやらせるときに、何回かAPIを叩くことになるのですが、 hakoがいろいろとやってくれます。

以下がその様子(簡略化のため分岐とかも適当な図で恐縮)です。

f:id:hoppie:20161016055117p:plain

f:id:hoppie:20161016062659p:plain

f:id:hoppie:20161016062716p:plain

f:id:hoppie:20161016062741p:plain

f:id:hoppie:20161016062821p:plain

利点・良いと思った機能

上記の通り、hako を使うことにより、このようなECS API叩く自前コードが減る のは大きな利点です。

hako oneshotを使ってみて他に感じた利点・良いと思った機能は

  • TaskDefinition重複登録されないようにチェックしてくれる
  • scale outも面倒見てくれる
  • dry-runがあるらしい
    • あまり使ってないけど使ってる人が便利っぽいと言っていた
  • コンテナの終了コードで終了してくれる
    • コンテナが終了コード0で終わればhako oneshotも0で終わる
      • 手元のシェルで && でつなぐ、とかできそう
  • C-cでabortできる

というところです。

まとめ

勝手にhako oneshotについて紹介しました!

間違い等ありましたらご指摘ください!

よろしくお願いいたします。

*1:Web Tech Tokyo #1(Docker Tips 共有会) http://web-tech-tokyo.connpass.com/event/40548/

jqの--exit-statusオプションについて調べてまとめたので100ブクマぐらいお願いします

manすると1文が長くてつらい。neither A nor Bとか懐かしい。両方否定ね。

man jq

   o   -e / --exit-status:
       Sets  the exit status of jq to 0 if the last output values was nei-
       ther false nor null, 1 if the last output value was either false or
       null,  or 4 if no valid result was ever produced. Normally jq exits
       with 2 if there was any usage problem or system error, 3  if  there
       was a jq program compile error, or 0 if the jq program ran.

まとめ

command stdout exit status
$ echo '{}' | jq . {} 0
$ echo '{}' | jq --exit-status . {} 0
$ echo 'true' | jq . true 0
$ echo 'true' | jq --exit-status . true 0
$ echo 'false' | jq . false 0
$ echo 'false' | jq --exit-status . false 1
$ echo 'null' | jq . null 0
$ echo 'null' | jq --exit-status . null 1
$ echo 'foo' | jq . *1 4
$ echo 'foo' | jq --exit-status . *2 4

以上です

*1:エラー出力にparse error: Invalid literal at line 2, column 0

*2:エラー出力にparse error: Invalid literal at line 2, column 0

Dockerコンテナが消費するメモリの最大値を知りたいのだが

ECSで、この画面で悩むんですが、皆さんどうされてるんでしょうか。。

「Maximum Memory」にメモリの上限値を入力する。

docker runの-mオプションに相当する。

f:id:hoppie:20160628065828p:plain

memory.max_usage_in_bytesを見て調べるということでどうか。

以下はAmazon Linuxの例。

$ # 調べたいコンテナを起動(-dでデタッチ)、コンテナIDを取得する
$ CID=$(docker run -d alpine sleep 100)
$
$ # 取得したコンテナIDからmax_usage_in_bytes(使用したメモリの最大値)
$ cat /cgroup/memory/docker/$CID/memory.max_usage_in_bytes
6422528

手元のubuntuだと、「/cgroup/memory/docker」の部分は「/sys/fs/cgroup/memory/docker」でした。

ちなみに以下はcgroupで取れるmemory関連の値。抜粋。

3.7. memory

memory.max_usage_in_bytes

cgroup 内のプロセスによるメモリー最大使用量をレポートします (バイト単位)。

memory.usage_in_bytes

cgroup 内のプロセスによる現在のメモリー総使用量をレポートします (バイト単位)。

memory.limit_in_bytes

ユーザーメモリーの最大値 (ファイルキャッシュを含む) を設定します。単位が指定されていない場合、その値はバイト単位と解釈されますが、より大きな単位を示すサフィックスを使用することが可能です (キロバイトには k または K、メガバイトには m または M、ギガバイトには g または G)。 root cgroup を制限するのには、memory.limit_in_bytes は使用できません。値を適用できるのは、下位階層のグループに対してのみです。 memory.limit_in_bytes に -1 と書き込み、現行の制限値を削除します。

おまけ

Dockerコンテナ内からDockerコンテナが消費したメモリの最大値を知るにはどうすればよいかを考えてみました。

(良い方法は思いつきませんでした、、、、)

-vオプションで/cgroupをマウントする。。。という方法でどうでしょうか。

$ docker run -v /cgroup/memory/docker:/docker:ro ...

rubyコンテナを走らせ、マウントされた/dockerディレクトリを見てmemory.max_usage_in_bytesをチェックする例です。

$ docker run \
  -v /cgroup/memory/docker:/docker:ro \
  -it \
  ruby:2.3.1-alpine irb
# memory.max_usage_in_bytesを取得するヘルパ定義
irb(main):001:0> def memory_max_usage_in_bytes
irb(main):002:1>   File.read(Dir["/docker/#{ENV.fetch('HOSTNAME')}*/memory.max_usage_in_bytes"].first).to_i/1024.0/1024.0
irb(main):003:1> end
=> :memory_max_usage_in_bytes
irb(main):004:0> memory_max_usage_in_bytes
=> 11.27734375

# サイズが1万、String配列を作る
irb(main):007:0> (1..10_000).map(&:to_s); nil
=> nil
irb(main):008:0> memory_max_usage_in_bytes
=> 11.80859375

# サイズが10万、String配列を作る
irb(main):009:0> (1..100_000).map(&:to_s); nil #ai
=> nil
irb(main):010:0> memory_max_usage_in_bytes
=> 17.55859375

# サイズが100万、String配列を作る
irb(main):011:0> (1..1_000_000).map(&:to_s); nil #ai
=> nil
irb(main):012:0> memory_max_usage_in_bytes
=> 77.29296875

# サイズが300万、String配列を作る
irb(main):013:0> (1..3_000_000).map(&:to_s); nil #ai
=> nil
irb(main):014:0> memory_max_usage_in_bytes
=> 278.29296875

まわりくどいですが、これはこれで便利な気がします。