Red Hat で Solution Architect として OpenJDK を担当している伊藤ちひろ(@chiroito)です。
この記事は、Red Hat Developerのブログ記事、Build lean Java containers with the new Red Hat Universal Base Images OpenJDK runtime images | Red Hat Developer の翻訳記事です。
Red Hat Universal Base Images (UBI) には、OpenJDK の完全な Red Hat ビルドが含まれています。Universal Base Images は UBI のエンドユーザライセンス契約の下で誰でも利用でき、Red Hat の顧客には完全にサポートされています。これらの「ビルダ」イメージは、特に Red Hat OpenShift 環境で使用する場合に、広範な Java ベースのアプリケーションの構築と実行に適しているように設計されています。これらのイメージには、開発ツール、Java コンパイラ、Maven、および関連するビルドツールを含む完全な Java Development Kit(JDK)が含まれています。
OpenShiftのS2I(source-to-image)プロセスでは、アプリケーションのソースコードをOpenShiftクラスタ内で簡単に構築・更新できます。また、基盤となるイメージやアプリケーションのソースが更新されるたびに、デプロイメントが更新されます。このワークフローでは、アプリケーションはビルダイメージの上に重ねられているため、デプロイメントには完全なJDKとMavenツールが含まれています。開発者の中には、よりスリムなベースイメージに基づいてデプロイメントを行いたいと考える人もいます。その場合、Maven を使用しないか、JDK ツールを完全に使用しないか、またはその両方を使用します。
このニーズに対応するため、Red Hat は新しい OpenJDK ランタイム・コンテナ・イメージをリリースしました。 このイメージには、完全なJDKやその他のビルドツールは含まれていません。この記事では、S2Iワークフローを使用してアプリケーションを自動的にデプロイするために、OpenShift環境内でこれらの新しいイメージを使用する方法を説明します。ここでは、Quarkusのクイックスタートをアプリケーションソースとして使用します。
S2IとQuarkusのクイックスタートでビルダイメージを使う
Quarkusのクイックスタートを開始するには、OpenShiftインスタンスにログインしていることを確認し、以下のコマンドを実行します。
# OpenShiftでのイメージ構築 $ oc new-app --context-dir=getting-started --name=quarkus-quickstart \ 'registry.access.redhat.com/ubi8/openjdk-11~https://github.com/quarkusio/quarkus-quickstarts.git#1.13.3.Final' # ビルドの完成を見守る $ oc logs -f bc/quarkus-quickstart # ルートを作成 $ oc expose svc/quarkus-quickstart # ルートのURIを取得 $ export URI="http://$(oc get route | grep quarkus-quickstart | awk '{print $2}')" # アプリをテスト! $ curl $URI/hello/greeting/quarkus
最初のコマンドである oc new-app
は、クイックスタートアプリケーションの構築とデプロイに必要なすべての OpenShift コンポーネントを作成します。すなわち、BuildConfig
、ubi8/openjdk-11
ベースイメージと結果のアプリケーションイメージの両方のImageStreams
、DeploymentConfig
とService
です。また,このコマンドはビルドとデプロイメントのインスタンスを作成します。oc expose
コマンドは、デプロイメントへのRoute
を作成し、実行中のWebアプリケーションをテストできます。
この設定の優れた点は、アプリケーションソースがGitリポジトリで更新されたときや、基盤となるビルダイメージが更新されたときに、新しいビルドを起動できることです。
ランタイムイメージ
さて、新しい部分です。ここでは、無駄のないランタイムイメージのために、新しい ImageStream
を定義します。このイメージの一部として、前のステップで作成されたアプリケーションの ImageStream
からアプリケーションの成果物をコピーします。また、初期のクイックスタートで自動的に行われたように、アプリケーションを稼働させるための他のOpenShiftの部品を定義する必要があります。それは"DeploymentConfig"、"Service"、"Route "の3つです。図1は私たちのプロセスを示しています。
DIYランタイムイメージを生成するためのOpenShiftのプロセス
まず、無駄のないベースイメージが必要です。ここではRed Hat UBI8 minimal base imageを使用します。これを ImageStream
として OpenShift にインポートする必要があります。それは以下のコマンドで簡単にできます。
$ oc create -n openshift -f https://raw.githubusercontent.com/jboss-container-images/openjdk/release/templates/runtime-image-streams.json
ここからは、無駄のないアプリケーション用のOpenShiftコンポーネントを定義していきます。まず、無駄のないランタイムアプリケーションのイメージを公開するためのImageStream
を作成します。
$ oc create imagestream quarkus-quickstart-runtime
次に、イメージを構築するための BuildConfig
が必要です。これはより複雑なので、コマンドラインではなくYAMLファイルで定義します。この記事の次のすべてのYAMLの断片については、その断片をファイルに保存して、OpenShiftに次のように読み込みます。
$ oc create -f snippet.yaml
BuildConfigは以下の通りです。
apiVersion: v1 kind: BuildConfig metadata: name: quarkus-quickstart-runtime spec: output: to: kind: ImageStreamTag name: quarkus-quickstart-runtime:latest source: images: - from: kind: ImageStreamTag name: quarkus-quickstart:latest paths: - sourcePath: /deployments destinationDir: ./deployments dockerfile: |- FROM - COPY deployments / CMD java -jar /deployments/quarkus-run.jar strategy: type: Docker dockerStrategy: from: kind: ImageStreamTag name: ubi8-openjdk-11-runtime:latest triggers: - type: ConfigChange - type: ImageChange imageChange: automatic: true from: kind: ImageStreamTag name: quarkus-quickstart:latest - type: ImageChange imageChange: automatic: true from: kind: ImageStreamTag name: ubi8-openjdk-11-runtime:latest
Note: イメージのDockerfileはYAMLの中にインラインで記述されています。ここでは"-"を代理の
FROM
イメージとして使用しています。YAMLのdockerStrategy
セクションは、FROM
行をubi8-openjdk-11-runtime
イメージストリームの最新イメージを表す値でオーバーライドするようOpenShiftに指示します。
Quarkus のクイックスタートイメージから /deployments
ディレクトリを新しい無駄のないイメージにコピーします。Quarkusのクイックスタートアプリケーション全体がこのディレクトリに存在することがわかっているので、コピーする必要があるのはこれだけです。特定のアプリケーションに応じて、さらなるステップが必要になるかもしれません。
最後に、無駄のないコンテナのCMD
がjava
を直接呼び出すように設定します。そして、これはアプリケーションのJARをコマンドラインで渡しています。
この構成では、基盤となる quarkus-quickstart
イメージ、またはベースの ubi8-openjdk-11-runtime
イメージに変更があった場合は、このイメージの再構築が行われます。
この断片を一時ファイルに保存し、前述のようにOpenShiftに読み込みます。これで、OpenShift はイメージの構築をスケジュールして開始するはずです。先ほどと同様に、ログを見て進行状況を確認できます。
$ oc logs -f bc/quarkus-quickstart-runtime
イメージサイズ
ビルドが完了したら、結果を確認してそのサイズをチェックできます。まず、ビルダイメージの上に重ねられた、通常のクイックスタート ImageStream
のサイズを取得します。
$ oc get istag quarkus-quickstart:latest -o json | jq .image.dockerImageMetadata.Size 308976772 => 295 MiB
比較のために、新しいランタイムイメージを入手してください:
$ oc get istag quarkus-quickstart-runtime:latest -o json | jq .image.dockerImageMetadata.Size 135747392 => 129 MiB
この新しいランタイム・イメージは、UBI8 OpenJDKの完全なビルダイメージの半分以下のサイズです。完全なビルダイメージには、完全なOpenJDKとMavenが含まれています。
最後の仕上げ
次に必要なのは、DeploymentConfig
、Service
、Route
の定義です。これらについては特に説明することがないので、1つのYAMLスニペットにまとめました。これを保存しておけば、先ほどのように oc create -f
で一度に読み込めます。
apiVersion: v1 kind: DeploymentConfig metadata: name: quarkus-quickstart-runtime spec: replicas: 1 selector: app: quarkus-quickstart-runtime template: metadata: labels: app: quarkus-quickstart-runtime spec: containers: - image: ' ' name: quarkus-quickstart-runtime ports: - containerPort: 8080 protocol: TCP triggers: - type: ConfigChange - imageChangeParams: automatic: true containerNames: - quarkus-quickstart-runtime from: kind: ImageStreamTag name: quarkus-quickstart-runtime:latest type: ImageChange --- apiVersion: v1 kind: Service metadata: name: quarkus-quickstart-runtime spec: selector: app: quarkus-quickstart-runtime ports: - port: 8080 protocol: TCP targetPort: 8080 --- apiVersion: v1 kind: Route metadata: name: quarkus-quickstart-runtime spec: to: kind: Service name: quarkus-quickstart-runtime
これらが読み込まれたら、同じ手法でルートを取得し、「Hello world」のURIを取得して、すべてが順調に進んでいることを確認します。
$ export URI="http://$(oc get route | awk '/quarkus-quickstart-runtime/ {print $2}')" curl $URI/hello/greeting/quarkus
まとめ
Universal Base ImagesのOpenJDK ビルダイメージは、OpenShift上でソフトウェアを構築してデプロイしたいと考えている様々なお客様のニーズに応えるために設計されました。しかし、このイメージの柔軟性は、イメージのサイズを犠牲にしています。開発者の中には、より小さなイメージや、ビルドツールのないイメージを望む人もいます。Red Hat は、このニーズに対応するために、新しい UBI OpenJDK ランタイムイメージを導入しました。この記事で紹介する方法では、新しいランタイムイメージに基づいてOpenShift内でDIY(do-it-yourself)アプリケーションイメージをカスタマイズして構築できます。また、この方法では、構成部品が変更されたときにイメージが再構築されるようになっています。
今後の課題
新しいランタイムイメージの主な目的は、可能な限り構成要素を少なくすることでした。既存のビルダイメージには、ランタイムイメージにはない多くの機能が含まれています。 その既存のビルダイメージは、機能的なランスクリプト(ただし、これに限定されません)、 メトリクス収集のための Prometheus エージェント、OpenShift の準備のためのプローブ、デフォルトのJVMおよびガベージコレクションのパラメータ、イメージを調整するための豊富な環境変数などを含んでいます。これらの機能を必要とする場合は、完全なビルダイメージが適しているかもしれません。逆に、できるだけ小さなランタイムイメージで、可動部が少なく、多少のDIYは気にしないという方には、ランタイムイメージの方が適しているかもしれません。
Red Hatでは、最新の技術を活用するためにコンテナを継続的に進化させています。多くの開発者にとって、イメージのサイズとデプロイに必要なサイズが重要な問題であることは承知しています。私たちは、リリースごとにOpenJDKビルダとランタイムイメージの両方のサイズを小さくするために継続的に取り組んでいます。現在、いくつかの有望な開発を進めています。どうぞご期待ください。