今日の業務用途で利用されているサーバー・クライアント型のアプリケーションの多くはクラウドでの実行を前提として作られておらず、物理サーバーや仮想マシンのような比較的レガシーな環境で実行されているため、拡張性や柔軟性が低い、パフォーマンスが思うように出ない、運用コストが高い等の課題を抱えています。アプリケーションをクラウド環境で実行し、クラウドが持つ迅速性、拡張性・柔軟性・サービス型の利用モデル等の特徴を活用することができれば、アプリケーションが抱える課題の解決に向けて前進することができます。本記事では、広く利用されている既存のJavaアプリケーションのソースコードや開発プロセスに対して影響を与えることなくコンテナ化を実現し、クラウド環境で実行可能にする手法をご紹介します。
-
Refactoring - リファクタリング:アプリケーションコードをクラウド環境での実行に対して最適化するために修正し、クラウドが提供するマネージドサービスを採用し、クラウドの特性を最大限活用する。
-
Relocate - リロケート:既存のアプリケーションの実行環境を変えずに、物理的な場所のみを変更する。
-
Rehost - リホスト:既存アプリケーションに手を加えず、アプリケーションをクラウドに移行する。
-
Replatform - リプラットフォーム:アプリケーションには可能な限り変更を加えず、クラウドが提供するマネージドサービスを活用する。
-
Repurchase - リパーチェィス:アプリケーションを再購入し、新しいものに変更する。
-
Retain - リテイン:検討の結果、移行が不要・不可能であり、現在のアプリケーションをそのまま維持・利用する。
-
Retire - リタイア : 不要となったアプリケーションの利用を停止する。
アプリケーションをリファクタリングして「モダナイゼーション」することで、クラウド上での実行に最適化することができれば、クラウドが持つ拡張性、柔軟性を最大限に活用し、運用コストも削減することが可能になります。しかし、アプリケーションのリファクタリングは容易ではありません。既存アプリケーションを適切に分解し、クラウドが提供する機能をどう活用するか検討し、アプリケーションの実装を変更することになるため、非常に多くの人と時間を要するプロジェクトになります。そこで、比較的現実的にクラウドに移行するための方針として考えられるのがアプリケーションの「リロケート」、「リホスト」、「リプラットフォーム」によるクラウドへの「マイグレーション」です。アプリケーションに変更を加えない、もしくは軽微な変更によりアプリケーションの実行環境をクラウドに移行します。
オンプレミスのVMware仮想基盤であれば、VMware Cloud™を利用することで容易にAWS、Azure、Google Cloud等にリロケートすることが可能です。本記事ではリロケートから一歩進んで、既存のJavaアプリケーションをリプラットフォームによりクラウド移行する方法をご紹介します。リプラットフォームによるクラウド移行では、クラウドの特性をフル活用することは困難ですが、実行環境がクラウドにかわることにより、クラウドの持つ一部の特性を活用することでアプリケーションが抱える課題を解決し、将来的にアプリケーションのリファクタリングの検討も比較的容易になります。
コンテナ化によるJavaアプリケーションのリプラットフォーム
Javaは非常にポピュラーな開発言語であり、多くのアプリケーションがJavaで開発されています。一般的にJavaで開発されるウェブアプリケーションは、開発のビルドツールによりJARやWARファイルを作成し、Apache TomcatやJettyのようなアプリケーションサーバーにデプロイして実行されます。すでに開発環境やプロセスが確立されている場合、成果物となるJARファイルやWARファイルからコンテナイメージを生成することで、現在のソースコードや開発プロセスに対して影響を与えることなく、アプリケーションをKubernetes等で実行することが可能になり、クラウドへの移行が容易になります。
コンテナイメージを作成するには、Dockerfileと呼ばれるコンテナイメージを作成するためのプロセスを記述したファイルを作成します。既存のWARファイルをTomcatコンテナイメージ上で実行する場合、以下のようなDockerfileを作成することでコンテナイメージの作成が可能です。
FROM tomcat:9.0.71-jdk11
ENV CATALINA_HOME /usr/local/tomcat
ENV PATH $CATALINA_HOME/bin:$PATH
WORKDIR $CATALINA_HOME
COPY demo-app.war webapps/demo-app.war
作成したDockerfileを指定して、docker buildコマンドよりコンテナイメージのビルドが可能です。作成したコンテナイメージはdocker pushコマンドでレジストリに登録することが可能です。
$ docker build -f Dockerfile -t harbor.demo.netone.co.jp/library/demo-app:latest .
$ docker push harbor.demo.netone.co.jp/library/demo-app:latest
コンテナ化したJavaアプリケーションはKubernetesクラスター上でDeploymentを作成することでPodとして実行することが可能です。Open Container Initiative(OCI)が標準化したコンテナイメージが作成されるため、どのパブリッククラウドやプライベートクラウドであってもKubernetesが利用できればどこでも実行が可能です。Kubernetesクラスター上にDeploymentとして作成することで、コンテナはPodとして起動します。Deploymentのレプリカ数を変更すればPod数の増減も容易です。また、起動したPodはServiceやIngressリソース等を経由して外部に公開することも可能です。
$ kubectl create deployment demo-app --image=harbor.demo.netone.co.jp/library/demo-app:latest
$ kubectl get pod
NAME READY STATUS RESTARTS AGE
demo-app-569bf99c78-8j4xf 1/1 Running 0 18s
$ kubectl scale deployment demo-app --replicas=3
deployment.apps/demo-app scaled
$ kubectl get pod
NAME READY STATUS RESTARTS AGE
demo-app-569bf99c78-8j4xf 1/1 Running 0 3m11s
demo-app-569bf99c78-fd8p8 1/1 Running 0 8s
demo-app-569bf99c78-vtsgx 1/1 Running 0 8s
コンテナ化の課題
上記の通り、WARファイルを含むコンテナイメージを作成することで比較的簡単にJavaアプリケーションをクラウドに移行することが可能になりますが、コンテナイメージの作成には、Dockerfileの作成が必須です。上記の例ではDocker社のパブリックレジストリであるDocker Hubで公開されているDocker 公式イメージにWARファイルを追加して、コンテナイメージにしています。この公式イメージはDocker社が中心となっているコミュニティが作成しているものです。公開されているDockerfileを見ると、ベースイメージとしてubuntu:22.04が利用されており、Eclipse TemurinのOpenJDK 11.0とApache Tomcat 9.0.71をインストールして構成されています。Docker公式イメージなので、ある程度は信頼できるもののセキュリティの観点から透明性の高いコンテナイメージを利用したい場合は、Dockerfileでベースイメージに対して必要なコンポーネントを追加し、パフォーマンスやセキュリティを踏まえて各コンポーネントで指定すべきオプションを考慮する必要があるため、プロダクション環境に適したコンテナイメージをビルドするためのDockerfileを作成し、継続して管理することは容易ではありません。
コンテナ化を実現するCloud Native Buildpacks と kpack
Cloud Native Buildpacksはアプリケーションのソースコードからコンテナイメージを生成することができるオープンソースのツールです。JavaだけでなくGo、Python、Ruby、PHP等様々な言語に対応しており、言語やフレームワークを自動的に認識してアプリケーションをビルドし、アプリケーションを実行するためのコンテナイメージをビルドすることができます。Cloud Native Buildpacksを利用すると、Dockerfileを意識することなくコンテナイメージをビルドすることが可能です。Cloud Native BuildpacksはDockerやKubernetes環境で利用することができ、Kubernetes上で利用するためのツールとしてkpackがオープンソースで開発されています。kpackを利用するとKubernetes上でソースコードからコンテナイメージを作成することが可能です。
例えば、GitHub上にあるgo-demowebというソースコードからコンテナイメージをビルドするには、kpack用のCLIであるkpを利用して、以下のように実行します。Kubernetes上でビルド用のPodが実行され、ソースコードの取得・ビルドと、コンテナイメージのビルドが実行され、指定したコンテナレジストリにコンテナイメージが格納されます。
$ kp image create go-demoweb \
--tag harbor.demo.netone.co.jp/myproject/go-demoweb \
--git https://github.com/masanara/go-demoweb.git \
--git-revision main
上記コマンドによりKubernetes上にはimageリソースが登録され、継続的にGitHub上のリポジトリをモニタリングし、mainブランチに新たなコミットが発生する度に自動的にコンテナイメージが再ビルドされ、ビルドされた新しいイメージはコンテナレジストリにプッシュされます。
JARファイルを利用したコンテナイメージの作成例
上記の方法は、Cloud Native Buildpacks(kpack)によりアプリケーションのビルドとコンテナイメージのビルドを同時に行っていましたが、Javaプログラムの場合はソースコードだけでなく、既存のビルドツールを利用して作成されたJARファイルやWARファイルを指定してコンテナイメージをビルドすることも可能です。例えばdemo-app.warがある場合、HTTPアクセス可能な場所においたWARファイルを--blobオプションとして指定してkpコマンドを実行することでコンテナイメージを作成することができます。
$ kp image create demo-app \
--tag harbor.demo.netone.co.jp/myproject/demo-app \
--blob http://192.168.0.1/demo-app.war
kpによって作成したイメージは以下の様にリビジョンが指定されます。
$ kubectl get image
NAME LATESTIMAGE READY
demo-app harbor.demo.netone.co.jp/myproject/demo-app@sha256:ccd99af5aac11dce4dcf845055f31e4241884232238b24bb40c60845f7bd09f7 True
Kubernetesクラスター上でこのコンテナイメージを指定してDeploymentを作成することで、アプリケーションはKubernetes上でPodとして起動することが可能になります。
$ kubectl create deployment demo-app \
--image=harbor.demo.netone.co.jp/myproject/demo-app@sha256:ccd99af5aac11dce4dcf845055f31e4241884232238b24bb40c60845f7bd09f7
$ kubectl scale deployment demo-app --replicas=2
$ kubectl get pod
NAME READY STATUS RESTARTS AGE
demo-app-78796f4c8d-c7h8l 1/1 Running 0 2s
demo-app-78796f4c8d-j6xbq 1/1 Running 0 46s
Kubernetesの機能によって常に2つのPodが起動するよう制御されます。また、コンピュートリソースが不足した場合もKubernetesのオートスケール機能により自動的にスケールアウトする等のクラウドならではの運用が可能になります。
このようにkpackを利用することで、既存のJavaアプリケーションの開発はそのままに、成果物として生成されるWARファイルからコンテナイメージを作成することが可能になるため、アプリケーションのソースコードや、開発環境・プロセスに変更を加えることなくコンテナとして実行することで、リプラットフォームが可能となります。なお、コンテナ作成に利用されるベースイメージ(Stack)やBuildpackはBuilderとして管理されており、利用されているランタイムやライブラリに脆弱性が発見された場合、新たなBuilderを利用してビルドすることで脆弱性対応が可能です。
Tanzu Build Service と Tanzu Application Platform
本ブログ記事でご紹介したkpackはVMware社が中心となってオープンソースで開発されているソフトウェアです。オープンソースを利用する場合はコミュニティサポートが基本となりますが、VMwareはkpackの商用プロダクトとしてVMware Tanzu® Build ServiceTMを提供しています。Tanzu Build Serviceを利用することにより、VMwareのソフトウェアサポートを受けることが可能です。また、クラウドネイティブなアプリケーション開発と実行を支援するためのソフトウェアスタックであるVMware Tanzu® Application PlatformTMはTanzu Build Serviceだけでなく、ビルドしたコンテナイメージを実行するためのコンポーネントであるKnative Serving (Cloud Native Runtimes for VMware Tanzu®)や、これらのツールを連動させるためのCartographer、ウェブベースのGUI等が含まれています。Tanzu Application Platformを既存の開発プロセスに組み込むことで、アプリケーションのモダナイゼーションを加速することが可能になります。Tanzu Application Platformに関しては、こちらのBlog記事も御覧ください。
まとめ
kpackやTnazu Build Serviceを利用することにより、既存のJavaアプリケーションのソースコードや開発プロセスに対して影響を与えることなくコンテナ化しクラウド環境で実行することで、クラウドが持つ迅速性、拡張性・柔軟性・サービス型の利用モデル等の特徴を活用することが可能になります。クラウドへの移行を検討・推進されているお客様は、リロケートやリホストの次の一歩として、Javaアプリケーションのコンテナ化を検討されてはいかがでしょうか。