Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

小さく始める Docker container の deploy

578 views

Published on

Web アプリコンテナを deploy する際に検討するアレコレ

Published in: Technology
  • Be the first to comment

  • Be the first to like this

小さく始める Docker container の deploy

  1. 1. 小さく始める Docker Container の Deploy 2016.9.9 (Fri) M3 tech meetup! #3 エムスリー株式会社 エンジニアリングググループ 寺岡良矩 @yteraoka
  2. 2. Orchestration ツールは必須か? ● 誰かが運用してくれるなら Kubernetes とか Mesos (Marathon, Chronos) 使いたい... ● スモールスタートにはこれらの自前構築、運用は避けたい ● Docker 1.12 は Builtin になったので Swarm mode が使えたら(使い物になったら) 嬉しいな、この程度なら新バージョンが出てもクラスタごと作りなおすのも簡単 ● Docker 1.12 の衝撃 http://www.slideshare.net/yteraoka1/docker-112 ● Docker swarm mode 入門と ECS との比較 http://www.slideshare.net/yteraoka1/docker-swarm-mode-ecs-64682284
  3. 3. Swarm mode はちょっと様子見 ● 1.12 は RC での品質がちょっと不安な感じだった ● RC5 までガンガン更新されれた ● せっかく 1.11 で Swarm クラスタ構築したのでまずはこれで始めてみよう ● このこの資料を書くためにまた 1.12 を触ってみたけどまだ見送りかな、 残念
  4. 4. deploy に求められること ● 権限分離 ● 簡単 ● サービスが止まらない ● ローリングアップデート
  5. 5. 権限分離 ● 開発者が勝手に変更して勝手にデプロイ出来てはいけない ● 環境変数でDBのパスワードなどを渡しているがこれが見えてはいけない ● よって、次のようなことができてはいけない ○ docker inspect ○ docker exec ○ shipyard などの便利ツール ○ 勝手な image、勝手なオプションでの起動 (-v /var/run/docker.sock:/var/run/docker.sock)
  6. 6. 簡単 ● Jenkins ポチポチでできる ● scale も指定できる ● scale up / down できる ● 作るのも簡単 ○ docker-compose + shell script (< 100 lines)
  7. 7. 簡単 ● docker-compose.yml は事前に準備 image だけ環境変数渡し ○ docker-compose -p {project_id} up -d ○ docker-compose -p {project_id} scale app=N ● -p (project) に指定する {project_id} は deploy 単位で一意になるように生成 ● SERVICE_NAME という label にサービス名を設定しておくことで registrator がこの名前で consul にに登 録してくれるし、停止させるべき古いコンテナを探すのに使える ○ docker ps -f label=SERVICE_NAME=$service --format {{.Names}} ● ここから project 名が取り出せるので古いものを停止させる ○ docker-compose -p {old_project_id} stop --timeout XX ○ docker-compose -p {old_project_id} down
  8. 8. docker-comose.yml の例 version: '2' services: app: image: $IMAGE env_file: ./env ports: - 3000 environment: - "TZ=Asia/Tokyo" logging: driver: fluentd options: fluentd-address: fluentd-server:24224 tag: "docker.service-name" labels: - "SERVICE_NAME=service-name" mem_limit: 512m restart: always networks: - overlay networks: overlay: external: true
  9. 9. サービスが止まらない ● registrator と HAProxy + consul-template ● 新しく起動したコンテナを HAProxy に自動登録 ● HAProxy は healthcheck が成功するまでリクエストを流さない ● 新しく起動したしたコンテナの healthcheck が成功してから古いコンテナを停止する ○ deploy script の中で起動したコンテナに対して check を行う (tcp or http)
  10. 10. サービスが止まらない? 罠(1) ● https://github.com/gliderlabs/registrator/pull/431 ● registrator は `die` event で deregister するがそれでは遅すぎる ○ 死んだ後に HAProxy から外れるのでは遅い ● kill -> die -> stop -> destroy という流れなので SIGTERM を送る kill の時点で deresiter されることを期待するが SIGHUP などかもしれないということで互換性の 問題から merge されていない (1.8 までは stop 時に kill event は無かった、Signal の情報が渡されるのも API Version 1.22 から) ● この影響で connection draining がうまくいかない
  11. 11. サービスが止まらない? 罠(1) ● OpenSource なので自前でなんとかする --- a/registrator.go +++ b/registrator.go @@ -172,6 +172,10 @@ func main() { go b.Add(msg.ID) case "die": go b.RemoveOnExit(msg.ID) + case "kill": + if signal, ok := msg.Actor.Attributes["signal"]; ok && signal == "15" { + go b.RemoveOnExit(msg.ID) + } } }
  12. 12. サービスが止まらない? 罠(2) ● コンテナの停止処理 ● SIGTERM で良いの? unicorn の場合 ○ INT/TERM ■ quick shutdown, kills all workers immediately ○ QUIT ■ graceful shutdown, waits for workers to finish their current request before finishing. ● SIGQUIT が正解 ● nginx も QUIT が Graceful shutdown ● 使うソフトウェアに合わせましょう、signal だけじゃないかも
  13. 13. サービスが止まらない? 罠(2) ● SIGQUIT を送るには? ● dumb-init https://github.com/Yelp/dumb-init には Signal rewriting 機能がある ○ For example, to rewrite the signal SIGTERM (number 15) to SIGQUIT (number 3), just add --rewrite 15:3 on the command line. ● まさにコレ!! ● ENTRYPOINT [ “/dumb-init”, “-r”, “15:3”, “--” ] CMD [ “...”, “...” ]
  14. 14. サービスが止まらない? 罠(3) ● SIGTERM を受けた瞬間に HAProxy から外れるわけではない ● 余裕をもってしばらく待ってから停止する必要がある ● というわけで wrap script を用意する
  15. 15. サービスが止まらない? 罠(3) #!/bin/bash signal_handler(){ sleep 5 # wait for reloading HAProxy config kill -QUIT $pid } trap signal_handler SIGINT SIGTERM SIGQUIT bin/rails server -b 0.0.0.0 & pid=$! wait
  16. 16. サービスが止まらない? 罠(4) ● sleep してたら SIGKILL が飛んでくる!! ● docker stop ののデフォルトの待ち時間は10秒でその間に停止しない場合は SIGKILL で強制終了させられてしまう :( ● タイムアウトをのばそう ● docker-compose stop --timeout 30 ● docker-compose scale --timeout 30 ● down コマンドに timeout オプションは無いので stop してから down させる
  17. 17. deploy の状態遷移を確認
  18. 18. シーケンス HAProxy Swarm workers consul
  19. 19. シーケンス(新しいコンテナの起動) HAProxy Swarm workers consul registrator が consul に service を登録 新しいコンテナ docker-compose up
  20. 20. シーケンス(新しいコンテナの起動) HAProxy Swarm workers consul consul-template が consul の情報をを元 に haproxy.cfg を更新 新しいコンテナ docker-compose up
  21. 21. シーケンス(新しいコンテナの起動) HAProxy Swarm workers consul 新しいコンテナ HAProxy による Healthcheck docker-compose up
  22. 22. シーケンス(新しいコンテナの起動) HAProxy Swarm workers consul 新しいコンテナ Healthcheck の成功 によりアクセスが振 られ始める docker-compose up
  23. 23. シーケンス(古いコンテナの停止) HAProxy Swarm workers consul SIGTERM / SIGQUIT docker-compose stop
  24. 24. シーケンス(古いコンテナの停止) HAProxy Swarm workers consul SIGTERM / SIGQUIT kill event により registrator が consul から service を削除 docker-compose stop
  25. 25. シーケンス(古いコンテナの停止) HAProxy Swarm workers consul SIGTERM / SIGQUIT consul の情報から haproxy.cfg を更新 docker-compose stop
  26. 26. シーケンス(古いコンテナの停止) HAProxy Swarm workers consul 接続済みのリクエスト はそのまま処理 docker-compose stop
  27. 27. シーケンス(古いコンテナの停止) HAProxy Swarm workers consul docker-compose stop
  28. 28. シーケンス(古いコンテナの停止) HAProxy Swarm workers consul SIGQUIT による Graceful shutdown 完了 docker-compose down
  29. 29. シーケンス(古いコンテナの削除) HAProxy Swarm workers consul docker-compose down で掃除 docker-compose down
  30. 30. 残りの課題
  31. 31. ローリングアップデート ● 小さく始めているのでまだ必要となっていない ● 新しいのを必要なだけ起動した後に古いのを停止させている ● 実装は難しくないがその前に 1.12 にするんじゃないかな
  32. 32. 監視 ● これからの課題 ● 1.12 であれば Docker の HEALTHCHECK 機能が使えて、異常があれば自動で restart してくれるのだが… ● HAProxy での監視状態を監視するのが良いか
  33. 33. リソースモニタリング ● とりあえず zabbix の docker agent を入れているが自動でサービス単位のスクリー ンを更新する方法が知りたい、誰か教えてください :) ● 例えば JMX で何かの値を取得したい場合とか ● 1.12 で JMX 用ポートを LB に設定されても困る ● コンテナ内で agent を動かして push するしかないか
  34. 34. 状態の維持 ● Docker 1.12 の目玉機能、service の replicas を 5 などとしておけばクラスタ全体で 5 つのコンテナが稼働していることを維持してくれる ● Worker node が down した場合でも別の node で起動させてくれる ● 1.11 での Swarm ではこの機能が無く restart: always どまり ● Worker node が down した場合なにかしら対応が必要なので余裕をもったコンテナ 数での運用が求められる
  35. 35.

×