Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
KubernetesでJVMアプリを動かすための実践的ノウハウ集 / JVM on Kuber...
Search
hhiroshell
July 22, 2019
Technology
40
17k
KubernetesでJVMアプリを動かすための実践的ノウハウ集 / JVM on Kubernetes
CloudNative Days Tokyo 2019 1D3 セッションのスライドです。
#CNDT2019 #OSDT2019 #RoomD
hhiroshell
July 22, 2019
Tweet
Share
More Decks by hhiroshell
See All by hhiroshell
LINEヤフーにおける超大規模プラットフォーム実現への挑戦と学び / Challenges and Lessons in Building an Ultra-Large-Scale Platform at LY Corporation
hhiroshell
3
1.2k
Architecting Kubernetes-Based Internal Developer Platforms: Essential Patterns and Practices
hhiroshell
0
87
Discover Your Tailored Platform Strategy with Real-World Practice
hhiroshell
1
200
Kubernetesでアプリの安定稼働と高頻度のアップデートを両立するためのプラクティス / Best Practices for Applications on Kubernetesto Achieve Both Frequent Updates and Stability
hhiroshell
10
3.8k
Platform EngineeringにおけるKubernetesの活用法とLINEヤフーにおける事例のご紹介 / Platform Engineering and Kubernetes Findy Lunch LT Edition
hhiroshell
7
1.7k
大規模Webアプリケーションプラットフォームを開発して軌道に乗るまでにやったこと / How to Put Platforms on Track
hhiroshell
2
2.5k
Kubernetesとカスタムコントローラーを活用したプラットフォーム開発・運用の勘所 / Platform Engineering and Kubernetes
hhiroshell
1
1.2k
Best Practices for Applications on Kubernetesto Achieve Both Frequent Updates and Stability
hhiroshell
3
680
Cloud Native Developers JP (cndjp) のご紹介 / about cndjp
hhiroshell
0
200
Other Decks in Technology
See All in Technology
UI State設計とテスト方針
rmakiyama
2
620
C++26 エラー性動作
faithandbrave
2
760
生成AIのガバナンスの全体像と現実解
fnifni
1
190
ハイテク休憩
sat
PRO
2
160
watsonx.ai Dojo #5 ファインチューニングとInstructLAB
oniak3ibm
PRO
0
170
第3回Snowflake女子会_LT登壇資料(合成データ)_Taro_CCCMK
tarotaro0129
0
200
AWS re:Invent 2024で発表された コードを書く開発者向け機能について
maruto
0
190
NilAway による静的解析で「10 億ドル」を節約する #kyotogo / Kyoto Go 56th
ytaka23
3
380
ガバメントクラウドのセキュリティ対策事例について
fujisawaryohei
0
560
kargoの魅力について伝える
magisystem0408
0
210
開発生産性向上! 育成を「改善」と捉えるエンジニア育成戦略
shoota
2
390
LINEヤフーのフロントエンド組織・体制の紹介【24年12月】
lycorp_recruit_jp
0
530
Featured
See All Featured
Testing 201, or: Great Expectations
jmmastey
40
7.1k
Code Reviewing Like a Champion
maltzj
520
39k
Being A Developer After 40
akosma
87
590k
VelocityConf: Rendering Performance Case Studies
addyosmani
326
24k
Art, The Web, and Tiny UX
lynnandtonic
298
20k
Writing Fast Ruby
sferik
628
61k
GraphQLの誤解/rethinking-graphql
sonatard
67
10k
The World Runs on Bad Software
bkeepers
PRO
65
11k
Imperfection Machines: The Place of Print at Facebook
scottboms
266
13k
[RailsConf 2023 Opening Keynote] The Magic of Rails
eileencodes
28
9.1k
Automating Front-end Workflow
addyosmani
1366
200k
ReactJS: Keep Simple. Everything can be a component!
pedronauck
665
120k
Transcript
Cloud Native Developers JP KubernetesでJVMアプリを 動かすための実践的ノウハウ集 @hhiroshell 1 CloudNative Days
Tokyo 2019 [1D3] #CNDT2019 #RoomD
Cloud Native Developers JP #CNDT2019 #RoomD 自己紹介 早川 博(はやかわ ひろし)
• Cloud Nativeな技術スタック担当のプリセールスエンジニア • エンジニアコミュニティ 「Cloud Native Developers JP」 オーガナイザー • Developers Summit 2018、Japan Container Days 12.18 登壇 2 @hhiroshell
Cloud Native Developers JP #CNDT2019 #RoomD 宣伝 • 皆さん自作キーボードやりましょう! 楽しいですよ!
3 遊舎工房さんの店舗はこちら→ ↓現在の@hhiroshellのキーボード • 本書きました!買って ください! 「Kubernetes実践ガイド」 北山 晋吾(著), 早川 博(著) https://www.amazon.co.jp/dp/B07TSBP3CZ/
Cloud Native Developers JP #CNDT2019 #RoomD ご注意 • このプレゼンテーションにおけるJDK/JREは、特に断りのない場合 OpenJDKを指しているものとしてご理解ください
4
Cloud Native Developers JP #CNDT2019 #RoomD お品書き • イントロダクション •
JVM on Kubernetes ノウハウ集 – JVMコンテナアプリの開発作業を楽にしよう – JVMコンテナをビルドしよう – JVMコンテナをデプロイしよう – JVMコンテナを監視しよう • まとめ 5
Cloud Native Developers JP #CNDT2019 #RoomD イントロダクション 6 #CNDT2019 #RoomD
Cloud Native Developers JP #CNDT2019 #RoomD JVMとコンテナワークロード • コンテナワークロードに対する一般的な期待 –
軽量、高可搬性、1コンテナ1プロセス • 従来までのJVMの考え方とコンテナとは相性が良くない面もある – 特にJava EEに代表されるアプリケーションサーバーは、1つのJVM上に複数の アプリケーションを動かすことが想定されている • JVMレイヤー上での可搬性 (.jar, .war, .ear) • JVMレイヤー上での管理・運用機能の作りこみ • 1つのJVMに大きなリソースを割り当てる傾向 JVMをコンテナで動かす場合、注意が必要な点がある 7
Cloud Native Developers JP #CNDT2019 #RoomD Cloud Nativeの世界においてJVMはオワコンか? • メジャーなミドルウェア製品で多く利用されている
– Kafka、Spark、Casssandra… • モダンなプログラミング言語で、JVMベースのものも多い – Scala、Kotlin… • 開発者のスキルセット – なんだかんだ言って、Javaエンジニアはたくさんいらっしゃる とはいえ避けて通るのは難しい。むしろ使えるのなら使っていきたい 8
Cloud Native Developers JP #CNDT2019 #RoomD 個人的なモチベーション • 「いちおうJavaエンジニアだし、Kubernetesも勉強してるし、JVM on
Kubernetesがんばってみよー」 9
Cloud Native Developers JP #CNDT2019 #RoomD JVM on Kubernetes ノウハウ集
10 #CNDT2019 #RoomD
Cloud Native Developers JP #CNDT2019 #RoomD JVM on Kubernetesのランドスケープ •
JVM on Kubernetesの考慮事項は、開発・運用全体に渡る…。 • ひとつずつ見てきます! 11 • ツールを活用して Kubernetesでも効率 よくローカル開発を 行う ② ビルド Build Containers • JVM固有の事情を考 慮しつつ、Dockerfile のベストプラクティ スに従ったコンテナ を目指す ③ デプロイ Deploy Containers • KubernetesでもJVM標 準の監視ツールを利 用する • Cloud Nativeな監視手 法も考慮する • コンテナのリソース 制限機能を考慮して、 適切なJVMパラメー タを設定する • ロールアウト前に暖 機運転を行う ① ローカル開発 Local Development ④ 監視 Monitoring
Cloud Native Developers JP #CNDT2019 #RoomD JVM on Kubernetesのランドスケープ •
JVM on Kubernetesの考慮事項は、開発・運用全体に渡る…。 • ひとつずつ見てきます! 12 ① ローカル開発 Local Development • ツールを活用して Kubernetesでも効率 よくローカル開発を 行う ② ビルド Build Containers • JVM固有の事情を考 慮しつつ、Dockerfile のベストプラクティ スに従ったコンテナ を目指す ③ デプロイ Deploy Containers ④ 監視 Monitoring • KubernetesでもJVM標 準の監視ツールを利 用する • Cloud Nativeな監視手 法も考慮する • コンテナのリソース 制限機能を考慮して、 適切なJVMパラメー タを設定する • ロールアウト前に暖 機運転を行う
Cloud Native Developers JP #CNDT2019 #RoomD JVMコンテナアプリのローカル開発を楽にしよう • ツールを活用してKubernetesでも効率よくローカル開発を行う –
Skaffold + Jibでローカル開発を省力化 13
Cloud Native Developers JP #CNDT2019 #RoomD JVMコンテナアプリの開発作業の課題 1. アプリケーションのコードを編集 2.
ローカルでビルド、自動テスト (Maven/Gradleなどのビルドツールを利用) 3. Dockerfileを編集 (必要な場合) 4. docker build / push 5. 開発用のKubernetesクラスターにデプロイ 6. 動作確認 (→ 1. に戻ってくりかえし) Kubernetes前提のJVMアプリ開発は手間がかかる 14 動作確認のために毎回Kubernetes にデプロイ 成果物をコンテナとしてビル ドする必要あり
Cloud Native Developers JP #CNDT2019 #RoomD Jib + Skaffoldがやってくれること 1.
アプリケーションのコードを編集 2. ローカルでビルド、自動テスト (Maven/Gradleなどのビルドツールを利用) 3. Dockerfileを編集 (必要な場合) 4. docker build / push 5. 開発用のKubernetesクラスターにデプロイ 6. 動作確認 (→ 1. に戻ってくりかえし) 面倒な作業を自動化してローカル開発を効率よく 15 ここの作業を自動化してくれ る!
Cloud Native Developers JP #CNDT2019 #RoomD Jibとは • Maven/Gradleプラグインとして利用可能な 、JVM言語アプリケー
ションのコンテナイメージ作成を省力化してくれるツール • 使い慣れたビルドツールでコンテナイメージが作成できる – Dockerfileフリー。使い慣れた記述形式 – Dockerfileのベストプラクティスを知らなくても高品質のコンテナが作れる (JVMアプリとして必要なファイルだけを選択的にコンテナに入れてくれる) • コーディングが滞らない – 高速でコンテナイメージをビルド。ビルド待ちを減らしてコードに集中 Dockerfileの編集とコンテナのビルドから、アプリ開発者を開放 16
Cloud Native Developers JP #CNDT2019 #RoomD Maven/GradleプラグインとしてのJibの利用方法 • Maven/Gradleのプラグインとして Jibを指定
• 作成するコンテナイメージのプロ パティをプラグインの設定値とし て記述する – mainClass : ENTRYPOINTとなるクラス – ports : コンテナの公開ポート – jvmFlags : JVMに与えるオプション (…etc) 17 plugins { application kotlin("jvm") version "1.3.10" id("com.google.cloud.tools.jib") version "1.0.1" } (…snip…) val main_class by extra("io.ktor.server.netty.EngineMain") (…snip…) Jib { container { ports = listOf(“8080”) mainClass = main_class // good defauls intended for Java 8 containers jvmFlags = listOf( “-server”, “-Djava.awt.headless=true”, “-XX:+UnlockExperimentalVMOptions”, (…snip…) ) } } build.gradle ファイルの記述例 →
Cloud Native Developers JP #CNDT2019 #RoomD Skaffoldとは • docker build/push/deploy
の一連のコマンド実行を自動化するツール – ローカルのコードの変更を検知して、 docker build/push/deployに相当する処理 を自動実行(クラスタ上のコンテナのホットスワップ)可能 • コーディングが滞らない – コードの編集結果を反映したコンテナが開発用Kubernetesクラスターに自動的 にデプロイされる。コードの修正内容の動作確認がすぐできる 面倒なBuild, Push, Deployを自動化 18
Cloud Native Developers JP #CNDT2019 #RoomD Skaffoldのプラグインアーキテクチャ • SkaffoldはBuild, Push,
Deployの各フェーズ自動実行する • それぞれのフェーズで実行する処理に様々なツールを選択可能 Build, Push, Deploy各フェーズの処理をプラグイン的に変更できる 19 Build Push Deploy > docker build > docker push > kubectl apply
Cloud Native Developers JP #CNDT2019 #RoomD Build Push Deploy Skaffold
+ Jib • Build, PushのフェーズでSkaffoldを利用できる SkaffoldのプラグインとしてJibを利用 20 Jibを実行 > kubectl apply
Cloud Native Developers JP #CNDT2019 #RoomD 【参考】Jibのイメージ作成の仕組み • ベースイメージに以下のレイヤーを 足したイメージが作られる
– 依存ライブラリ(.jar) – リソース(.conf, .properties, …etc) – classファイル(.class) (それぞれ別のレイヤー) • ファイルの変更内容に応じて必要な レイヤーを更新するだけなので高速 • 不要なファイルは自動的に除外され る 21 (… snip …) ============================================================ 13 MB $ jib-gradle-plugin:1.0.1 ============================================================ 2.6 MB app/libs/kotlin-reflect-1.3.10.jar 1.2 MB app/libs/kotlin-stdlib-1.3.10.jar 784 kB app/libs/kotlinx-coroutines-core-1.0.1.jar 730 kB app/libs/kotlinx-html-jvm-0.6.11.jar (… snip …) ============================================================ 814 B $ jib-gradle-plugin:1.0.1 ============================================================ 474 B app/resources/logback.xml 333 B app/resources/application.conf 7 B app/resources/hoge.conf ============================================================ 57 kB $ jib-gradle-plugin:1.0.1 ============================================================ 6.0 kB app/classes/example/ktor/AppKt$router$1$4$1.class 4.9 kB app/classes/example/ktor/AppKt$init$1$1.class 4.8 kB app/classes/example/ktor/AppKt$router$1$4$2.class 4.0 kB app/classes/example/ktor/AppKt$router$1$3.class (… snip …) ↑ dlayer(by @orisanoさん) にかけた結果の抜粋 https://github.com/orisano/dlayer
Cloud Native Developers JP #CNDT2019 #RoomD Skaffold + Jibを利用するプロジェクトの例 •
pom.xml – Jibをプラグインとして設定した mavenプロジェクトの定義 • k8s/web.yaml – Kubernetesクラスターに自動デプロ イするときに利用するManifest • skaffold.yaml – プラグインとしてJibとkubectlを使 うように設定 22 $ cd scaffold-jib-project $ tree . ├── README.adoc ├── pom.xml ├── k8s │ └─ web.yaml ├── skaffold.yaml └── src └─ main └─ java └─ hello ├─ Application.java └─ HelloController.java $ scaffold dev
Cloud Native Developers JP #CNDT2019 #RoomD Jib + Skaffoldがやってくれること 1.
アプリケーションのコードを編集 2. ローカルでビルド、自動テスト (Maven/Gradleなどのビルドツールを利用) 3. Dockerfileを編集 (必要な場合) 4. docker build / push 5. 開発用のKubernetesクラスターにデプロイ 6. 動作確認 (→ 1. に戻ってくりかえし) 面倒な作業を自動化してローカル開発を効率よく 23 ここの作業を自動化してくれ る!
Cloud Native Developers JP #CNDT2019 #RoomD 24 ここまで15分…。
Cloud Native Developers JP #CNDT2019 #RoomD JVM on Kubernetesのランドスケープ •
JVM on Kubernetesの考慮事項は、開発・運用全体に渡る…。 • ひとつずつ見てきます! 25 • ツールを活用して Kubernetesでも効率 よくローカル開発を 行う ② ビルド Build Containers • JVM固有の事情を考 慮しつつ、Dockerfile のベストプラクティ スに従ったコンテナ を目指す ③ デプロイ Deploy Containers • KubernetesでもJVM標 準の監視ツールを利 用する • Cloud Nativeな監視手 法も考慮する • コンテナのリソース 制限機能を考慮して、 適切なJVMパラメー タを設定する • ロールアウト前に暖 機運転を行う ① ローカル開発 Local Development ④ 監視 Monitoring
Cloud Native Developers JP #CNDT2019 #RoomD JVMコンテナをビルドする上での指針 • Dockerコンテナをビルドするときの一般的な指針に従うのが基本 –
Dockerfileを書くためのベストプラクティス(公式) • エフェメラル(使い捨て型)コンテナを作成すべし • …etc • JVMのコンテナの場合、コンテナのフットプリントを小さくするた めにJVM固有のノウハウが必要 – 適切なベースイメージの選択 – カスタムJREによるフットプリントの削減 – (もっと発展的なJVMコンテナのビルド手法…) JVM固有の事情を考慮しつつ、Dockerfileのベストプラクティスの実現を目指す 26
Cloud Native Developers JP #CNDT2019 #RoomD 適切なベースイメージを選択しよう • LTSならheadless(軽量OS版)やJREが選択可能。LTS以外は要件に合わせて 公式リポジトリからベースイメージを選択する場合、LTS
+ headlessがおすすめ 27 ベースイメージ 8 LTS 11 LTS 12 13 (EA) 14 (EA) Debian JRE/JDK JRE/JDK Debian (headless) JRE/JDK JRE/JDK Oracle Linux 7 JDK JDK JDK Alpine 3.10 JDK JDK Windows Server Core 1803 JRE/JDK JRE/JDK JDK JDK JDK Windows Server Core 1809 JRE/JDK JRE/JDK JDK JDK JDK Windows Server Core LTSC2016 JRE/JDK JRE/JDK JDK JDK JDK Docker公式リポジトリで公開されているOpenJDKイメージ https://k11i.biz/blog/2018/05/17/base-docker-images-for-java/ をベースに2019/07/18時点の情報に更新
Cloud Native Developers JP #CNDT2019 #RoomD 【参考】Project Portola • Alpine/muslで可動するOpenJDKを開発する、
OpenJDK配下の取り組み – Alpine Linuxとmusl Cライブラリを利用すること で、ベースイメージの大幅軽量化を目指す – 現在プロトタイプの開発が進められている – https://openjdk.java.net/projects/portola/ Alpineを利用してJVMコンテナの大幅軽量化を目指す 28
Cloud Native Developers JP #CNDT2019 #RoomD カスタムJREを作成してサイズを落とそう • デフォルトのJDKの全機能は、多くのアプリケーションでは不要 –
必要なもの: java.{lang,util,…}.*, javax.management.*, … – 不要なもの: corba, jaxws, … • JDK9でモジュールシステム(“Jigsaw”)が導入された – JDK自体をモジュール化するとともに、必要なモジュールだけを含むカスタム JREを生成するツール(jdeps/jlink)を提供 JDKの標準機能でフットプリント削減が可能 29
Cloud Native Developers JP #CNDT2019 #RoomD 30 https://www.slideshare.net/oracle4engineer/java-in-the-world-of-container-by-david-buck
Cloud Native Developers JP #CNDT2019 #RoomD 31 https://www.slideshare.net/oracle4engineer/java-in-the-world-of-container-by-david-buck
Cloud Native Developers JP #CNDT2019 #RoomD 32 https://www.slideshare.net/oracle4engineer/java-in-the-world-of-container-by-david-buck
Cloud Native Developers JP #CNDT2019 #RoomD 33 https://www.slideshare.net/oracle4engineer/java-in-the-world-of-container-by-david-buck
Cloud Native Developers JP #CNDT2019 #RoomD jdeps / jlink •
jdeps: – アプリケーションの.classや.jarファイルを解析して、依存するJVMモジュール を特定する • jlink: – 指定したJVMモジュールだけを含む、カスタムJREを生成する カスタムランタイムを作るためのJDK標準ツール 34 $ ${JAVA_HOME}/bin/jdeps target/cowweb.jar cowweb.jar -> java.base cowweb.jar -> java.logging … $ ${JAVA_HOME}/bin/jlink --output cowweb-jre --add-modules java.base,java.logging
Cloud Native Developers JP #CNDT2019 #RoomD 35 Dockerfile内でカスタムJREを作成する例 $ cat
target/Dockerfile FROM openjdk:11-jdk-slim AS jre-builder WORKDIR /jlink RUN jlink --output cowweb-jre --add-modules java.base,java.desktop,java.logging,java.management FROM debian:buster-slim WORKDIR /workdir COPY --from=jre-builder /jlink/cowweb-jre /opt/cowweb-jre ENV PATH /opt/cowweb-jre/bin:$PATH RUN mkdir /app COPY libs /app/libs COPY cowweb.jar /app CMD ["java", "-jar", "/app/cowweb.jar"]
Cloud Native Developers JP #CNDT2019 #RoomD カスタムJREを使ったコンテナのサイズ • Helidonを使ったシンプルなREST APIアプリケーションの例
– 144.8 (214 – 69.2) [MB] -> 89.8 (159 – 69.2) [MB] (JVMのサイズを約38%削減) 36 $ docker images | grep -e cowweb -e debian hhiroshell/cowweb v2.1-custom-jre 0233250b4900 3 minutes ago 159MB hhiroshell/cowweb v2.1 4af060beb2eb About an hour ago 214MB debian buster-slim 83ed3c583403 9 days ago 69.2MB
Cloud Native Developers JP #CNDT2019 #RoomD • Jib – JibとカスタムJREを組み合
わせることも可能 – Jibの設定で、ベースイ メージとしてカスタムJRE が入ったコンテナを指定 する • Native Image – GraalVMのNative Image生 成機能を利用 – ランタイムとアプリケー ションをまとめてバイト コード化してシングルバ イナリを生成する→これ をコンテナに入れる – 起動初期の劇的な高速化 とフットプリント削減 37 • SubstrateVM – JVMを必要なコンポーネ ントだけに絞って自力で ビルドする – 使わないJITコンパイラ、 GCアルゴリズム、などを 削りに削ると5MBくらい のランタイムを作成可能 – ご利用は用法用量を守っ て計画的に もっと発展的なJVMコンテナのビルド手法
Cloud Native Developers JP #CNDT2019 #RoomD 38 ここまで23分…。
Cloud Native Developers JP #CNDT2019 #RoomD JVM on Kubernetesのランドスケープ •
JVM on Kubernetesの考慮事項は、開発・運用全体に渡る…。 • ひとつずつ見てきます! 39 • ツールを活用して Kubernetesでも効率 よくローカル開発を 行う ② ビルド Build Containers • JVM固有の事情を考 慮しつつ、Dockerfile のベストプラクティ スに従ったコンテナ を目指す ③ デプロイ Deploy Containers • コンテナのリソース 制限機能を考慮して、 適切なJVMパラメー タを設定する • ロールアウト前に暖 機運転を行う • KubernetesでもJVM標 準の監視ツールを利 用する • Cloud Nativeな監視手 法も考慮する ① ローカル開発 Local Development ④ 監視 Monitoring
Cloud Native Developers JP #CNDT2019 #RoomD JVMコンテナをKubernetesにデプロイしよう • コンテナのリソース制限機能を考慮して、適切なJVMパラメータを 設定する
– コンテナレベルのCPU/メモリのリソース制限 • ロールアウト前に暖機運転を行う コンテナのリソース制限と暖機運転に注意する 40
Cloud Native Developers JP #CNDT2019 #RoomD チューニングパラメータの指針 • リソース制限(ここではCPU、ヒープメモリ、スレッド) –
かつてのJVMはcgroupsによるリソース分離を認識しなかったので、CPU利用量 やヒープメモリサイズなどのリソースの設定に注意が必要だった – JDK10以降コンテナランタイムのリソース制限の設定を認識する改善が導入 → 改善後のJVMの挙動を理解してコンテナのリソース制限に適切な設定を JVMをいじるのはその後で • GC – 1コンテナに割り当てるリソース量は、JVMが元来想定していた量より小さい → GCアルゴリズムの選択を再確認しよう コンテナのリソース制限を考慮して、適切な設定を 41
Cloud Native Developers JP #CNDT2019 #RoomD Docker/cgroups リソース制限を考慮した設定 - CPU
• JDKが認識してくるコンテナのCPU制限の設定 – --cpus, --cpu-shares, --cpu-quota • KubernetesでResource Quotaを設定するとコンテナの--cpu-sharesに マッピングされる。これをJVMが認識して動作する • 結果として、Runtime.availableProcessors()の返り値や、ForkJoinプール、 スレッドプールの割当量が変わる これらに依存して挙動を変えているライブラリやフレームワークも 影響を受ける (e.g. core.async, ElasticSearch, Netty) コンテナでCPU割り当て制限が行われた結果をJVMが認識する 42
Cloud Native Developers JP #CNDT2019 #RoomD Docker/cgroups リソース制限を考慮した設定 – メモリ
• JDKが認識してくるコンテナのメモリ制限の設定 – --memory • KubernetesでResource Quotaを設定するとコンテナの-mオプションに マッピングされる。これをJVMが認識して動作する • JVMのヒープメモリの設定は、コンテナに割り当てられたメモリ量 に対してエルゴノミクスによって決定される(JVMのデフォルトの 挙動) • チューニングが必要な場合は、追加で起動オプションを設定する コンテナでメモリ割り当て制限が行われた結果をJVMが認識する 43
Cloud Native Developers JP #CNDT2019 #RoomD 44 Docker/cgroups リソース制限を考慮した設定 $
cat target/cowweb.yaml kind: Pod apiVersion: v1 metadata: name: cowweb spec: containers: - name: cowweb image: hhiroshell/cowweb:2.1-jdk ports: - containerPort: 8080 resources: requests: cpu: 1000m memory: 512Mi limits: cpu: 1000m memory: 512Mi $ kubetl apply -f target/cowweb.yaml pod/cowweb created $ kubectl exec -it cowweb jshell Jul 20, 2019 4:11:38 PM java.util.prefs.FileSystemPreferences$1 run INFO: Created user preferences directory. | Welcome to JShell -- Version 11.0.4 | For an introduction type: /help intro jshell> Runtime.getRuntime().availableProcessors() $1 ==> 1 jshell> Runtime.getRuntime().maxMemory() $1 ==> 129761280
Cloud Native Developers JP #CNDT2019 #RoomD GC • コンテナでJVMアプリを動かす場合、リソースの割当量が比較的小 さいため、シリアルGCなどの少リソース向けのGCアルゴリズムが適
している場合がある – e.g) JDK11で1CPU, 512MBをコンテナに割り当ててJVMのデフォルトに任せる と、シリアルGCが選択される • リソース割り当て量とGCアルゴリズムの選択の考え方は、古くから ある議論。先達の知恵から学びましょう…。 – 参考資料: 「Javaパフォーマンス」/ Scott Oaks 著 少リソースで実行されるケースに合わせて、GCアルゴリズムに改めて注意 45
Cloud Native Developers JP #CNDT2019 #RoomD JITコンパイラ ロールアウトで気にすべきこと • JVMアプリケーションが最大の性能を発揮するには暖機運転が必要
– JVMは、実行中のプロファイルを参考にしながら、アプリケーションのコード を動的にバイトコードに変換している (c.f. JIT(Just in Time)コンパイラ) – コンパイルが進んでいない初期のJVMコンテナは理想的な性能を発揮しない 暖気運転をしていないJVMは理想的なパフォーマンスを発揮しない 46 001000111010101101 010001011101010111 010100101010000110 010101010101001101 0101000101010101… 実行時プロファイル
Cloud Native Developers JP #CNDT2019 #RoomD Kubernetes標準のルーティングで起きる問題 • スケールアウトで追加された直後のPodにも他と同量のトラフィック が分配され、処理が追いつかない場合がある
• 最悪Liveness Probeへの応答ができず、Podが再起動されてしまう • 対策は2つ – 暖機運転を自動化して、それが完了してからトラフィックを回す – トラフィックの配送量を制御する → Service Mesh 暖気運転が済んでいないJVMコンテナを高負荷に晒さない工夫を行う 47 Service トラフィック 追加したばかりのPodにも他と 同量のトラフィックが送られる
Cloud Native Developers JP #CNDT2019 #RoomD 暖機運転の自動化 • Podが起動したらReadiness ProbeがOKとなる前にサイドカーコンテナ
から暖機運転のトラフィックを送る • 暖機運転が完了したあとでReadiness ProbeがOKとなるようにする – 暖機運転完了までの十分なinitialDelaySecondsを設定する (または – 暖機運転が完了したら、サイドカーコンテナのReadiness ProbeをOKとする 48 Service トラフィック ① サイドカーコンテナから暖気 のトラフィックを送る ② Readiness ProbeがOKになるとServiceから トラフィックが送られるようになる
Cloud Native Developers JP #CNDT2019 #RoomD 49 暖機運転を自動化するmanifestの記述例 kind: Deployment
(... snip ...) spec: (... snip ...) template: (... snip ...) spec: containers: - name: cowweb image: hhiroshell/cowweb:2.1 (... snip ...) readinessProbe: httpGet: path: /health port: http initialDelaySeconds: 180 periodSeconds: 10 livenessProbe: httpGet: path: /health port: http initialDelaySeconds: 5 periodSeconds: 15 (左からの続き) - name: warmup image: radial/busyboxplus:curl command: ['/bin/sh', '-c'] args: ['sleep 15; for i in `seq 0 10000`; do curl "http://localhost:8080/cowsay/say"; done; tail -f /dev/null;'] • Readiness ProbeがOKとなるまで、Service経由で のPodへのトラフィックが流れないことを利用 し、Readiness Probeが開始されるまでの間にサ イドカーコンテナから暖気をかけている • (※)理想的には、サイドカーにReadiness Probeを設定しておいて、暖気が終わったらそ ちらをOKにする方が良いです。確実に暖気が 終わったところでトラフィックを流せます
Cloud Native Developers JP #CNDT2019 #RoomD Service Meshによるトラフィックの制御 • IstioなどのService
Meshを利用すると、Podに流すトラフィックの割 合を1%単位で調整できる – 追加したばかりのPodには少量のトラフィックを送り、暖気が進んできた段階 で徐々に増やす(カナリーデプロイメントに似たやり方) • 本番のトラフィックを暖気に利用するので、理想的な最適化が期待 できる 50 Virtual Service トラフィック 追加したばかりのPodには少量のトラ フィックを送り、徐々に増やす 99 % 1 %
Cloud Native Developers JP #CNDT2019 #RoomD JVM on Kubernetesのランドスケープ •
JVM on Kubernetesの考慮事項は、開発・運用全体に渡る…。 • ひとつずつ見てきます! 51 • ツールを活用して Kubernetesでも効率 よくローカル開発を 行う ② ビルド Build Containers • JVM固有の事情を考 慮しつつ、Dockerfile のベストプラクティ スに従ったコンテナ を目指す ③ デプロイ Deploy Containers • コンテナのリソース 制限機能を考慮して、 適切なJVMパラメー タを設定する • ロールアウト前に暖 機運転を行う • KubernetesでもJVM標 準の監視ツールを利 用する • Cloud Nativeな監視手 法も考慮する ① ローカル開発 Local Development ④ 監視 Monitoring
Cloud Native Developers JP #CNDT2019 #RoomD 52 ここまで32分…。
Cloud Native Developers JP #CNDT2019 #RoomD JVMコンテナを監視しよう • KubernetesでもJVM標準の監視ツールを利用可能(ただし一工夫必要) –
jcmd, jstackなどの基本的なツール – JFR (Java Flight Recorder) • Cloud Nativeな監視手法も考慮する – Prometheusによるメトリック監視 – OpenTracing準拠のトレーサーによる分散トレーシング → 各言語のフレームワークやライブラリでサポートされる方式があるのでそち らでの説明に譲りますm(_ _)m 目的やスキルセットに合わせて複数の手段を使い分ける 53
Cloud Native Developers JP #CNDT2019 #RoomD 標準的なJVM監視ツールをKubernetesで利用する • jcmd, jstackなどJDK付属の基本的なツールを使う場合、JDKのコンテ
ナをサイドカーとして追加してそのコンテナからツールを実行する (アプリケーションのコンテナにツールが含まれていないケースがあるため) • トラブルシューティングの場面で活躍 従来どおりのツールでトラブルシューティングできるが一工夫が必要 54 Service カスタムJREの アプリコンテナ 監視ツールが入ったサイドカーコンテナ 経由で監視ツールを実行 JDKのコンテナ kubectl exec –it /bin/sh jmcd
Cloud Native Developers JP #CNDT2019 #RoomD 55 サイドカーコンテナからのJDK標準ツールの利用 $ cat
target/cowweb.yaml kind: Pod metadata: name: cowweb (... snip ...) spec: (... snip ...) shareProcessNamespace: true containers: - name: cowweb image: hhiroshell/cowweb:v2.1 (... snip ...) - name: jtoolings image: openjdk:11-jdk-slim command: ['/bin/sh'] securityContext: capabilities: add: - SYS_PTRACE stdin: true tty: true $ kubetl apply -f target/cowweb.yaml pod/cowweb created $ kubectl exec -it cowweb -c jtoolings /bin/sh # jps 8 cowweb.jar 10127 Jps # jcmd 8 VM.flags 8: -XX:CICompilerCount=2 -XX:InitialHeapSize=8388608 - XX:MaxHeapSize=134217728 -XX:MaxNewSize =44695552…
Cloud Native Developers JP #CNDT2019 #RoomD 【参考】よく使うコマンド • $ jcmd
[プロセスID] VM.system_properties – System.getProperties()を通じて得られるのと同じ情報が出力される – コマンドラインで –D オプションとともに指定されたプロパティとアプリケー ションによって動的に追加されたプロパティ、 JVMごとのデフォルトのプロ パティがすべて含まれる • $ jcmd [プロセスID] VM.command_line – 実行時のコマンドライン引数を出力する • $ jcmd [プロセスID] VM.flags [-all] – 有効化されているJVMのチューニングフラグを出力する • $ jstack [プロセスID] – スレッドスタックを出力する 56
Cloud Native Developers JP #CNDT2019 #RoomD Java Flight Recorder(JFR)を使ったプロファイリング •
JFRとは – JVMのプロファイリングやイベント収集のためのフレー ムワーク – .jfrという形式のプロファイルデータとして、JVMとアプ リケーションの詳細な実行記録を取得 – アプリケーションの実行中に記録の開始、停止、.jfrの ダンプが実行可能 – Oracle JDKの商用機能だったがJDK11からOpenJDKに寄贈 され無償で利用可能に – 本番環境での豊富な利用実績 JFR → JVMの強力なプロファイリングツール 57
Cloud Native Developers JP #CNDT2019 #RoomD Kubernetes上でJFRを利用するときの構成 • .jfrはjcmdコマンドで取得。Volumeをマウントしてそこに出力する •
GUIとプログラムから.jfrにアクセス可能 58 JVMアプリ (カスタムJRE) .jfrの保存 kubectl exec –it cowweb -c jtoolings /bin/sh Flight Recordingの開始・停止・.jfrのダンプ Kubernetesクラスター jcmd JMC(GUIツール)による解析 JFR APIによる解析 JDK Javaプログラム + JFR API
Cloud Native Developers JP #CNDT2019 #RoomD JFRファイルの出力と収集 • jcmdの各種コマンドでFlight Recordingの開始、終了、.jfrのダンプな
どが行える – .jfrファイルはダンプすることによって取得する – 起動オプションを設定することでJVM起動時からFlight Recordingを開始するこ とも可能 • Kubernetes上で利用する場合 – .jfrのダンプを手動・自動実行するサイドカーコンテナを用意する – ダンプする先をコンテナ外の永続ストレージにしておく – カスタムJREでアプリを動かす場合 jlinkに --bind-services オプションを追加する 59
Cloud Native Developers JP #CNDT2019 #RoomD JVM起動直後からFlight Recordingを開始する例 60 kind:
Pod metadata: name: cowweb (... snip ...) spec: (... snip ...) containers: - name: cowweb image: hhiroshell/cowweb:2.1 command: ['java', '-XX:StartFlightRecording=name=cowweb,filename=/jfr/jfr-cowweb.jfr, ¥ delay=30s,maxage=2h,maxsize=10m,dumponexit=true', '-jar', '/app/cowweb.jar’] (... snip ...) volumeMounts: - name: jfr-volume mountPath: /jfr (... snip ...) volumes: - name: jfr-volume nfs: server: 10.0.40.8 path: “/jfr-example"
Cloud Native Developers JP #CNDT2019 #RoomD JFRの解析 1/2 • Java
Mission Control を使った解析 – JMCはJFRを解析する ためのGUIツール – トラブル発生時後の 原因究明に適してい る グラフィカルなGUIツールを使った解析 61
Cloud Native Developers JP #CNDT2019 #RoomD JFRの解析 2/2 • JFR
APIを利用する例 • → JFR Exporterを実装することも不可能ではない…。 JFR APIを利用すると、Javaプログラムから .jfrファイルを読むことができる 62 (...snip...) import jdk.jfr.consumer.RecordedEvent; import jdk.jfr.consumer.RecordingFile; public final class Main { (...snip...) void printG1GCEvents() throws IOException { List<RecordedEvent> gcEvents = RecordingFile.readAllEvents(Paths.get("/jfr/jfr-cowweb.jfr")).stream() .filter((e) -> e.getEventType().getName().equals("jdk.G1GarbageCollection")) .collect(Collectors.toList()); gcEvents.forEach(System.out::println); } (...snip…) }
Cloud Native Developers JP #CNDT2019 #RoomD まとめ • たくさんありますが、頑張っていきましょう! 63
• ツールを活用して Kubernetesでも効率 よくローカル開発を 行う ② ビルド Build Containers • JVM固有の事情を考 慮しつつ、Dockerfile のベストプラクティ スに従ったコンテナ を目指す ③ デプロイ Deploy Containers • コンテナのリソース 制限機能を考慮して、 適切なJVMパラメー タを設定する • ロールアウト前に暖 機運転を行う • KubernetesでもJVM標 準の監視ツールを利 用する • Cloud Nativeな監視手 法も考慮する ① ローカル開発 Local Development ④ 監視 Monitoring
Cloud Native Developers JP #CNDT2019 #RoomD 64
Cloud Native Developers JP #CNDT2019 #RoomD Fin. 65
Cloud Native Developers JP #CNDT2019 #RoomD 参考文献 • 「Java in
a World of Containers」 – https://www.slideshare.net/oracle4engineer/java-in-the-world-of-container-by- david-buck • 「Better Containerized JVMs in JDK10」 – http://blog.gilliard.lol/2018/01/10/Java-in-containers-jdk10.html • 「Javaパフォーマンス」 – https://www.oreilly.co.jp/books/9784873117188/ • 「備えあれば憂いなし!Javaトラブルシューティングはじめの一 歩」 – http://otndnld.oracle.co.jp/ondemand/javaday2017/D1-F3_JavaDayTokyo2017 66
Cloud Native Developers JP #CNDT2019 #RoomD 参考文献 • 「最適な Java
の Docker イメージを選びたい」 – https://k11i.biz/blog/2018/05/17/base-docker-images-for-java/ • 「Dockerfileを書くためのベストプラクティス 解説編」 – https://www.slideshare.net/zembutsu/explaining-best-practices-for-writing- dockerfiles • 「Dockerfileを改善するためのBest Practice 2019年版」 – https://www.slideshare.net/zembutsu/dockerfile-bestpractices-19-and-advice 67