Se ha denunciado esta presentación.

Spring Boot の Web アプリケーションを Docker に載せて AWS ECS で動かしている話

3

Compartir

Próximo SlideShare
Jenkins 2.0 (日本語)
Jenkins 2.0 (日本語)
Cargando en…3
×
1 de 54
1 de 54

Más Contenido Relacionado

Más de JustSystems Corporation

Audiolibros relacionados

Gratis con una prueba de 30 días de Scribd

Ver todo

Spring Boot の Web アプリケーションを Docker に載せて AWS ECS で動かしている話

  1. 1. Spring Boot の Web アプリケーションを Docker に載せて AWS ECS で動かしている話 #jjug_ccc #ccc_g1 JJUG CCC 2018 Fall 2018/12/15
  2. 2. 自己紹介 • 株式会社ジャストシステム 福嶋 航 • Twitter @fukushiw • Java歴約20年、JavaでWebサービス作っています • #Java100 本ノックの人 https://github.com/JustSystems/java-100practices
  3. 3. このセッションについて • 人生で初めて、WebサービスをDockerコンテナ 化してAWS ECSを使ってプロダクションリリースし たものについての話です • AWS ECS や Dockerコンテナ について、基本 的なところは把握されている前提になっています • まだまだ慣れていないことやわかっていないことが あるため、セッション後や懇親会でぜひ情報交換 させてください
  4. 4. セッションの流れ 1. システム構成 (Dockerコンテナにしたもの、しなかったもの) 2. 各自の開発環境とビルド・デプロイの流れ (マージリクエストの前にやることと後にやること) 3. β環境と本番環境、環境ごとの設定の切り替え (Gitのブランチ・プロファイル・環境変数をうまく使う) 4. 本番運用に向けた「その他」の必要なこと (ログ出力設定、監視設定) 5. まとめ
  5. 5. 1 システム構成 (Dockerコンテナにした もの、しなかったもの)
  6. 6. サービスの性質 • 企業向けWebサービス • 24/7稼働 • 個人向けWebサービスに比べ、アクセス頻度は 高くない • 取り扱うデータ量は多い(数百GB~数TB)
  7. 7. JJUG CCC 2018 Springの資料 UI コア機能 外部連携 RDB キャッシュ キャッシュ キャッシュ 主要機能3 RDB 主要機能2 RDB 主要機能1 RDB サブ機能3 サブ機能2 サブ機能1 サブ機能6 サブ機能5 サブ機能4 RDB キャッシュ キャッシュ キャッシュ RDB キャッシュ サブ機能7 RDB 各機能(コンテキスト)は それぞれDockerコンテナとして動作 (複数配置しALBで分散)し、 REST APIでやりとり :
  8. 8. もうちょっと具体的に(抜粋) Internet Web Server / UI container other containers Independent Instance2 Independent Instance 1 GitLab
  9. 9. AWS ECSの採択経緯 • 弊社はAWSをよく使っていた • Kubernetes の学習コスト懸念 • AWS Fargate のランニングコスト懸念
  10. 10. Dockerコンテナにしたもの • ほぼすべての機能(十数種類のコンテナ) • Availability Zone A と Availability Zone C に それぞれ1つずつ配置(一部は2つずつ配置) • WebサーバのコンテナとUIのコンテナは同じタス ク定義にして、他は別々のタスク定義にした (理由は後述)
  11. 11. Dockerコンテナにしなかったもの • 将来 AWS Fargate にスムーズに移行できる 自信がなかったもの • 他ファイルシステムのボリュームをマウントしたり、バッ チやWebサービスが協働して動作する機能 • crontabに慣れ親しんでいているため、精神的に 「EC2インスタンスだからいざとなればなんとかなる」と 安心したかった機能 当然、Dockerコンテナにしてもできる。できるのだが、なんか、保険的な・・・。
  12. 12. WebサーバとUIのコンテナ Internet Web Server / UI container other containers Independent Instance2 Independent Instance 1 GitLab
  13. 13. WebサーバとUIのコンテナ(拡大図) こうなっています Web Server UI container Internet 宛先 https:443 http:80 http:8080 Web Server UI container
  14. 14. WebサーバとUIのコンテナ Web Server UI container Internet 宛先 https:443 http:80 http:8080 http:8080 本当はこうしたかった Web Server UI container
  15. 15. WebサーバとUIのコンテナ X-Forwaded-For X-Forwaded-Proto X-Forwaded-Port - - - オリジナルIP https 443 オリジナルIP https 443 Web ServerのIP http 8080 Web Server UI container Internet 宛先 https:443 http:80 http:8080 http:8080 Web Server UI container
  16. 16. WebサーバとUIのコンテナ X-Forwaded-For X-Forwaded-Proto X-Forwaded-Port - - - オリジナルIP https 443 オリジナルIP https 443 Web ServerのIP http 8080 Web Server UI container Internet 宛先 https:443 http:80 http:8080 http:8080 Web Server UI container
  17. 17. WebサーバとUIのコンテナ X-Forwaded-For X-Forwaded-Proto X-Forwaded-Port - - - オリジナルIP https 443 オリジナルIP https 443 Web ServerのIP http 8080 UI container にいる Spring Boot のリダイレクト応答(http:8080宛て)を 右側の ALB が戻してくれず詰んだ(解決方法がわからなかった) Web Server UI container Internet 宛先 https:443 http:80 http:8080 http:8080 Web Server UI container
  18. 18. WebサーバとUIのコンテナ で結局こうした Internet 宛先 https:443 http:80 http:8080 Web Server UI container Web Server と UI container の Dockerコンテナを 分けずに同一にするのは、「1コンテナ1アプリケーション」 のベストプラクティスに反するので、踏みとどまった Web Server UI container
  19. 19. 再掲 Internet Web Server / UI container other containers Independent Instance2 Independent Instance 1 GitLab
  20. 20. 2 各自の開発環境とビルド・ デプロイの流れ (マージリクエストの前に やることと後にやること)
  21. 21. 各自の開発環境 • PC • メモリは16GB以上必須(24~32GBは欲しい) • Windowsが多数派、Macな人もちらほら • IDEはほぼ皆何かしら使っている • Eclipse • IntelliJ IDEA • Visual Studio Code • など • Git • 一番早いのはコマンド :nerd_face:
  22. 22. マージリクエストまで • Issueを作る/アサインする • 粒度はまちまち • コーディング、テスト • ローカル用プロファイルで動作させる Spring Boot アプリケーションが入った Dockerコンテナをビルド・ 起動 • 単体テストは、他マイクロサービスのところはモック • コードの自己レビュー
  23. 23. マージリクエスト • 担当者以外が保守できるか、を最重視 • 実装理由のコメントや、APIドキュメントも重視 • 複雑なロジックはじっくり読む • マージ前の動作確認まではできなかった • 相当な量がやってくるので、時間的に無理 • マージ後の確認でSpring Boot起動時にエラーに なるとか、コンパイルエラーになるものもまれに…… このあたりはシステム化したかったが、できなかった
  24. 24. マージ後 • GitLab CIで開発環境にデプロイ • 特定のブランチへのPUSHで以下を自動実行  jarビルド (mvn clean install)   ↓  Dockerイメージビルド (docker-compose build)   ↓  ECRに登録 (docker push)   ↓  ECSのタスク定義&サービス更新 (ecs-deploy)   ↓  Mattermostに通知 (curl) • GitLabでそのブランチにPUSHできる人を限定 • 複数の環境ごとにブランチを用意(後述)
  25. 25. マージが終わったらデプロイ  
  26. 26. すぐにデプロイされない罠 • Dockerコンテナをホストポート固定で動作させる場 合、1つのEC2インスタンスでは同一タスクは1つしか 起動できない。ここで EC2インスタンス数=タスク 数 にすると、デプロイ時の動作は   タスク停止→draining→タスク起動 となる。新しいタスクの起動が前のタスクの drainingが完了するまで待たされるのですぐに新 Dockerコンテナが起動しない。 • ホストポートをダイナミックにすれば関係ない
  27. 27. CASE 1 EC2インスタンス数>タスク数の場合 もうちょっと詳しく
  28. 28. Case1 インスタンス数>タスク数 Container A1 タスク定義= A1:1 Instance 2 (1)Instance1でA1:1タスク実行中 Instance 1
  29. 29. Case1 インスタンス数>タスク数 Container A1 タスク定義= A1:1 (2)新しいタスクA1:2はすぐにInstance2にデプロイ   され、A1:1 は draining に。 Instance 1 Container A1 タスク定義= A1:2 Instance 2 draining
  30. 30. Case1 インスタンス数>タスク数 (3)drainingされたコンテナは消える Instance 1 Container A1 タスク定義= A1:2 Instance 2
  31. 31. CASE 2 EC2インスタンス数=タスク数の場合 もうちょっと詳しく
  32. 32. Case2 インスタンス数=タスク数 Container A1 タスク定義= A1:1 (1)Instance1とInstance2でA1:1タスク実行中 Instance 1 Container A1 タスク定義= A1:1 Instance 2
  33. 33. Case2 インスタンス数=タスク数 Container A1 タスク定義= A1:1 (2)片方のインスタンスでdraining、もう一方は   A1:1のまま Instance 1 Container A1 タスク定義= A1:1 Instance 2 draining
  34. 34. Case2 インスタンス数=タスク数 Container A1 タスク定義= A1:2 (3)drainingが完了すると新しいタスクがデプロイ   され、もう一方がdrainingになる。 Instance 1 Container A1 タスク定義= A1:1 Instance 2 draining
  35. 35. Case2 インスタンス数=タスク数 Container A1 タスク定義= A1:2 (4)drainingが完了すると新しいタスクがデプロイ   される。 Instance 1 Container A1 タスク定義= A1:2 Instance 2
  36. 36. drainingにかかる時間 • ターゲットグループの属性「登録解除の遅延」で指定 • 新しいタスクをデプロイすると、すぐには置き換わらず、こ こで指定した時間が経過するまで待たされる • タイムアウトを長くすれば、処理中が途中で中断されるリ スクは下がるが、デプロイに時間がかかってしまう
  37. 37. 3 β環境と本番環境、環境ごと の設定の切り替え (Gitのブランチ・プロファイル・ 環境変数をうまく使う)
  38. 38. 複数のβ環境と1つの本番環境 本番環境 β環境1 β環境2 β環境3
  39. 39. β環境1 • 各マイクロサービスが最初に結合を行う環境 • 更新サイクルが早い • 本線には取り込まない可能性があるものもここで 試すことは可能(敷居が低い) • とはいえ影響のあるものは Mattermost で声 を掛けてから
  40. 40. β環境2 • 第三者評価を行う環境 • 開発チームがβ環境1で確認を終えているものが デプロイされる • デプロイ手順も含めて本番環境に投入する前の リハーサルの場となる
  41. 41. β環境3 • 性能評価を行う環境 • インスタンスタイプや台数は本番環境と同じ • 負荷を掛けて、本番環境に必要なインスタンス タイプやECSタスクの個数、割り当てメモリ等を 導き出すための材料を得る
  42. 42. プロファイルの切り替え • 各β環境や本番環境用はそれぞれプロファイルを 分けて定義 micro-service-1/src/main/resources/ application-beta1.properties application-beta2.properties application-beta3.properties application-production.properties @Profile("application-beta1")
  43. 43. ブランチの切り替え • ブランチポリシーは Git Flow を採用 • master, develop, feature, release, hotfix • GitLab CI でビルドする際は、環境ごとに別々 のブランチにPUSH • β環境1ビルド・デプロイ用ブランチ、同2用、同3用 • 本番環境ビルド・デプロイ用ブランチ ブランチを分けることでミス防止
  44. 44. 環境変数の利用 • Spring Framewok はプロパティファイルよりも 環境変数を優先してくれるので、Docker イメー ジを作り直すことなく、ECSタスクの環境変数の 変更(とサービスの更新)だけで動作設定を 変更できる • Dockerイメージビルドして、ECRにアップロードし て、・・・は、数分~十数分かかることも • ECSタスクの変更だけであれば数十秒のWeb画面 操作だけで更新完了
  45. 45. 4 本番運用に向けた 「その他」の必要なこと (ログ出力設定、 監視設定)
  46. 46. ログ出力(要件) • 同一種類のコンテナのログは時系列に見たい • あとで分析に使えるようにしたい • エラーレベルのものは監視アラートを出したい
  47. 47. ログ出力(構成) Log Server S3 Bucket containers on EC2 file fluentd mount EC2 instance mainerror Zabbix agent
  48. 48. ログファイル2種 • 全行のファイルとエラーだけの行を分けたい • エラーだけの行を Zabbix agent で監視 • コンテナの標準出力は以下のように設定 (見やすいように改行していますが実際は1行です) ENTRYPOINT [ "/bin/bash", "-c", " $JAVA_HOME/bin/java $JAVA_OPTS -jar ./program.jar --spring.profiles.active=$SPRING_PROFILE | tee > (grep --line-buffered -e "^[0-9-]* [0-9:.]* ERROR.*" >> /path/to/error.log) | tee -a /path/to/main.log " ]
  49. 49. 監視内容(プログラムの外側) • エラーログ監視 • Zabbix agent がエラーログファイルの変更を監視 • EC2インスタンス監視(CPU/メモリなど) • ECS監視(リザーブ領域との対比等) • Docker space は特に重要 • Webアクセス監視 などなど
  50. 50. 監視内容(プログラムの内側) • ヘルスチェック • ALBからのヘルスチェックのエンドポイントを作成 • 各マイクロサービスが依存するRDBやキャッシュへの 通信の疎通まで確認。204 or 500 で応答。 • アプリケーションメトリクス • 処理キューの長さ、動作スレッド数、など • 重要処理の処理時間も入れたかったが、これから
  51. 51. 未解決事件  
  52. 52. コンテナ間通信が502エラー Internet Web Server / UI container other containers Independent Instance2 Independent Instance 1 GitLab ここの通信が502になる 1日に数回から十数回発生 原因不明 リトライで対処中 誰か教えてください :pray:
  53. 53. 5 まとめ
  54. 54. まとめ • Spring Bootアプリケーションのマイクロサービス はAWS ECSで普通に使える • Webサーバと入口のコンテナだけ1つのタスクに同居 させ、他は別々のタスクにした • Dockerコンテナ入れ替え時の待ち時間に注意 • 3つのβ環境を含めた4環境で別々にGitLab CIでビルド・デプロイ、環境変数を活用 • ログはコンテナから母艦経由S3へ • 監視はプログラムの外側と内側の両方

×