Cloud Native Days Tokyo(CNDT) 2019に行ってきた
TL;DR
- Cloud Nativeとは,
Kubernetes・OpenStackなどのツールを利用することではなく,
様々な資源(コンテナ・オーケストレーション・パイプライン・etc)を活用して問題解決に適した環境を創り上げていこうという考え方のこと - JVM言語のコンテナイメージをコンテナやKubernetesで利用するためには結構手間がかかる!!
最初に
私は現在2つのプロジェクト(大学生だけからなる)に参加しています.
そこではCloud Nativeなチームを意識したり,PaaSクラウドを作ったりしています.
その際,運用を意識していくとどうしても学生の知見だけでは解決が難しいことやベストプラクティスに辿り着けないという問題があります.
そんな時に,CNDTスカラーシップ枠が突如出現しました!!!
株式会社インプレス様と運営の方々に感謝です…!!
CNDTとは?
Cloud Nativeを支えている技術について,
運用者やOSSコントリビューターのエンジニア達の知見を吸収できるカンファレンスになります.
長々と話すのもあれなので,技術について話していきます
JVMコンテナを運用する際の注意点
セッション詳細
- スピーカー: 早川 博 (Hiroshi Hayakawa)さん
- タイトル: Cloud Nativeに立ち向かうJVMユーザー必見。KubernetesでJava/JVMアプリを動かすための実践的ノウハウ集
- URL: https://speakerdeck.com/hhiroshell/jvm-on-kubernetes
概要
コンテナは原則として,一つのコンテナに一つのアプリケーションという考え方があります.しかし,JVMはコンテナとは考え方が異なり,一つのJVMに複数のアプリケーションが搭載されます.
このように性質は異なりますが,JVM言語を用いたプロダクトは世に多く存在し,コンテナで使っていきたい or いかなければならないという要望もあります.
私が聞いたセッションは,JVMをコンテナで使っていこうという内容です.
JVMをコンテナ運用で利用する際の問題点
- ランタイム(openjdk)のイメージが,約300MB~と大きいこと
- JVMは,暖機運転が必要なためプロセス起動時はレイテンシが大きいこと
(1) ランタイムのイメージが大きい問題について
Dockerと相性の良いGolangでは,ビルドを行いプログラムを実行するにあたり,必要なモジュールだけを集めてシングルバイナリを吐き出します.これをイメージに乗せれば実行できるため比較的軽量(数10MB~)かつ起動が高速です.しかし,JVM言語においてはそうはいきません.
解決策は,以下の〜つです.
- 実行するプログラムに必要なモジュールだけを集めたCustom JREを作成する
- Javaアプリケーションの実行に必要なものだけを集めたイメージを作る
以下のリポジトリに,作業内容が入っています.
Scalaで,Akkaを用いた簡易的なAPIサーバを題材に行います.https://github.com/tozastation/Scala-Dockerize-Custom-Runtime
(1–1) 実行するプログラムに必要なモジュールだけを集めたCustom JREを作成する
- まずは,実行したいプログラムのfat-jarファイルを作成します.
次に,jdepsというjarファイルの依存モジュールを
リスト化するツールを用いて,依存関係を参照します.
> sbt assembly
> jdeps --list-deps target/scala-2.13/Scala-Try-Dockerize-Custom-0.1.jar
2. すると,fat-jarを実行するのに必要なモジュールのリストが出ます
java.base/sun.security.util
java.base/sun.security.x509
java.desktop
java.naming
jdk.unsupported
3. 次に,jlinkというCustom JREを作成するツールを用いて
上記のモジュールだけ含んだランタイムを生成します
> jlink --output custom-jre --add-modules java.base,java.logging,java.naming,java.desktop,jdk.unsupported
4. 以下のコマンドで,作成したランタイムとfat-jarで
プログラムが起動できます
> custom2/bin/java -jar target/scala-2.13/Scala-Try-Dockerize-Custom-0.1.jar
5. ここまでで,実行ファイルの容量を見てみましょう
- JRE: 400MB ?!
- JAR: 22MB
むむむ,非常によくない流れですね.JREが大きすぎます.
(1–2) Javaアプリケーションの実行に必要なものだけを集めたイメージを作る
sbt-native-packagerが提供するDockerizeツールが生成するDockerfileは,
ベースイメージが,JDKを含んだAlpineベースになります.
このDockerfileをビルドすると,イメージサイズは170MBほどでした.
先ほど作成した二つのファイルをAlpineコンテナに輸送して
ビルドしてみます
こちらDockerfileになります↓
FROM Alpine
WORKDIR /
COPY custom-jre /opt/custom-jre
COPY target/scala-2.13/Scala-Try-Dockerize-Custom-0.1.jar .
EXPOSE 8080
ENV PATH /opt/custom-jre/bin:$PATH
CMD ["java", "-jar", "Scala-Try-Dockerize-Custom-0.1.jar"]
なんとこのイメージjavaが実行できないし,サイズは400MBと最悪でした.しかし,JDK/JREを含むベースイメージに変更すると,実行できるように…!!?!
Custom JRE載せなくても動くので,jlinkとは何だったのかという気持ちに・・・(まだ知らないことがありそうです)
最終的にベースイメージは,openjdkが提供する,openjdk:8-jre-alpineに落ち着きました.イメージサイズは,100MBに減量し少しホッとしています.
(2) プロセス起動時はレイテンシが大きい問題について
次回に回したいと思います...
まとめ
バタバタした文章で申し訳ございません!
自分は,Go言語とKubernetes,Dockerなどを中心に普段は開発しています.Scalaを好きで学んでいたのですが,コンテナ運用時のサイズの大きさに悩んでいました.結局Goなのかな..と
そんな時に,まさに自分のためのようなセッションを聞けて物凄い楽しかったです!
今後もコンテナライズの知識をより深め,Kubernetesへのデプロイも継続して調査していこうと思います!