はじめに
Quarkusは、Red Hatが主導で開発するKubernetesネイティブのオープンソースJavaフレームワークです。マイクロサービスをJavaで実装する際のフレームワークとしてSpring Bootが選択肢に上がることが多いと思いますが、Quarkusはその新たな選択肢として2019年に登場しました。
Quarkusの特徴は、GraalVMのコンパイラにより、JavaのコードからLinuxネイティブのアプリケーションを生成できることです。この特徴から、省メモリで、通常のJavaアプリケーションよりも瞬時に起動するアプリケーションを実現することができます。
また、IBM Cloudでは、Quarkusが対象としているKubernetes関連のサービスとして以下のようなものを提供しています。(これら以外に、Red Hat OpenShiftのマネージドサービスもありますが、それはまた別の機会に触れたいと思います)
- IBM Cloud Kubernetes Service(IKS): マネージドKubernetesサービス
- IBM Cloud Container Registry : コンテナイメージのレジストリサービス
当記事では、Quarkusのサンプルアプリをネイティブ化し、それをコンテナ化したものをIKS上で稼働させてみます。
前提事項
当記事の執筆環境は以下になります。コマンド類はmacOSを前提にしています。Windowsの場合は、各項に記載の参考ページを参照ください。
- マシン : MacBook Pro (16インチ, Late 2019)
- OS : macOS Catalina (10.15.5)
全体の流れ
以降、以下の流れで進めていきます。
- 事前準備
- Quarkusサンプルアプリの準備・ネイティブ化・コンテナイメージ化
- IBM Cloud Container Registryの準備
- IBM Cloud Container Registryへのコンテナイメージのpush
- IKSクラスターの作成
- IKSへのマニフェストファイルのapply
事前準備
当記事の内容を実施するにあたり、以下のツールが必要となりますのでそれぞれ導入してください。
IBM Cloud CLI、Container Registryプラグイン、Kubernetes Serviceプラグイン
以下のコマンドにより、IBM Cloud CLIを導入してください。Container Registryプラグイン、Kubernetes Serviceプラグインも同時に導入されます。
curl -sL https://ibm.biz/idt-installer | bash
Docker
未導入の場合、上記のIBM Cloud CLIの導入により、一緒に導入されます。
JDK
JDK8以上を導入し、JAVA_HOMEを適切に設定してください。
Maven
Mavenのサイトから最新のMavenを入手し、導入してください。
導入手順はInstalling Apache Mavenを参照ください。
Homebrewが導入済みであれば、以下のコマンドで導入できます。
brew install maven
GraalVM
GraalVMのGetting Startedを参考に、GraalVMを導入します。
Homebrewが導入済みであれば、以下のコマンドで導入できます。
# JDK 8の場合
brew cask install graalvm/tap/graalvm-ce-java8
# JDK 11の場合
brew cask install graalvm/tap/graalvm-ce-java11
環境変数GRAALVM_HOMEを設定します。
# GraalVMのインストールディレクトリの配下の「/Contents/Home/」を設定
export GRAALVM_HOME=<GraalVMのインストールディレクトリ>/Contents/Home/
GraalVMのnative-image toolをインストールします。
${GRAALVM_HOME}/bin/gu install native-image
macOS Catalinaで、guコマンドでのインストールでエラー(警告)が出た場合は、以下のコマンドを実行して再度実行してください。
xattr -r -d com.apple.quarantine ${GRAALVM_HOME}/../..
参考:QUARKUS - BUILDING A NATIVE EXECUTABLE -> Configuring GraalVM
Quarkusサンプルアプリの準備・ネイティブ化・コンテナイメージ化
事前準備ができたので、ここからQuarkusのサンプルアプリの準備を進めていきます。
参考:QUARKUS - CREATING YOUR FIRST APPLICATION
MavenでQuarkusアプリを新規作成します。
mvn io.quarkus:quarkus-maven-plugin:1.6.1.Final:create \
-DprojectGroupId=org.acme \
-DprojectArtifactId=getting-started \
-DclassName="org.acme.getting.started.GreetingResource" \
-Dpath="/hello"
上記により、コマンドを実行したディレクトリ配下の「getting-started」ディレクトリに、Quarkusのサンプルアプリが作成されます。
このサンプルアプリには、「http://<ホスト名>:<ポート番号>/hello」というURLにアクセスすると「hello」という文字列を返すJAX-RSのAPIが含まれています。
以下のコマンドの実行により、サンプルアプリがコンパイルされ、Quarkusに内蔵されているサーバによりアプリが起動します。
# getting-startedディレクトリで実行する
./mvnw compile quarkus:dev
起動後、別のターミナルを起動して以下のコマンドをし、「hello」という文字列が返ることを確認してください。
curl -w "\n" http://localhost:8080/hello
確認できたら、上記の「mvnw」の実行をCtrl+Cで終了させてください。
次に、Quarkusのサンプルアプリをネイティブビルドします。
以下のコマンドを実行します。
./mvnw package -Pnative -Dquarkus.native.container-build=true
ネイティブビルドには数分程度の時間がかかるのでしばらく待ちましょう。
作成されたバイナリは64bit Linux用なのでこのままでは実行できません。
そのためDockerイメージ化し、Dockerコンテナとして実行します。
以下のコマンドを実行します。
getting-started の src/main/docker/Dockerfile.native という Dockerfile によりDockerイメージをビルドします。
docker build -f src/main/docker/Dockerfile.native -t quarkus-quickstart/getting-started .
Dockerイメージがビルドできたら、以下のコマンドでコンテナを実行します。
実行ログの「getting-started 1.0-SNAPSHOT native」という箇所から、ネイティブ化されて実行されていることが分かります。
❯ docker run -i --rm -p 8080:8080 quarkus-quickstart/getting-started
__ ____ __ _____ ___ __ ____ ______
--/ __ \/ / / / _ | / _ \/ //_/ / / / __/
-/ /_/ / /_/ / __ |/ , _/ ,< / /_/ /\ \
--\___\_\____/_/ |_/_/|_/_/|_|\____/___/
2020-08-10 05:03:56,672 INFO [io.quarkus] (main) getting-started 1.0-SNAPSHOT native (powered by Quarkus 1.6.1.Final) started in 0.018s. Listening on: http://0.0.0.0:8080
2020-08-10 05:03:56,672 INFO [io.quarkus] (main) Profile prod activated.
2020-08-10 05:03:56,672 INFO [io.quarkus] (main) Installed features: [cdi, resteasy]
IBM Cloud Container Registryの準備
ここからは、上記で作成したDockerイメージをpushし、IKSからpullできるようにするため、Container Registryを準備していきます。
IBM Cloud CLIで、IBM Cloudアカウントにログインします。
ユーザ・パスワードが聞かれますので入力してください。
また、地域の選択では「jp-tok」を選択してください。
ibmcloud login -a https://cloud.ibm.com
以下のコマンドを実行し、Container Registryの対象地域を設定します。
ibmcloud cr region-set ap-north
以下のコマンドを実行し、名前空間を新規に作成します。
ibmcloud cr namespace-add <任意の名前空間名>
IBM Cloud Container Registryへのコンテナイメージのpush
IBM Cloud Container Registryにコンテナイメージをpushする前に、Container Registryにログインしておきます。
ibmcloud cr login
コンテナイメージをpushできるよう、Quarkusサンプルアプリのイメージのタグを設定します。
docker tag quarkus-quickstart/getting-started:latest jp.icr.io/<名前空間名>/quarkus-getting-started:1.0
コンテナイメージをpushします。
docker push jp.icr.io/<名前空間名>/quarkus-getting-started:1.0
正常にpushされていることを確認します。
❯ ibmcloud cr image-list
イメージをリストしています...
リポジトリー タグ ダイジェスト 名前空間 作成日 サイズ セキュリティー状況
jp.icr.io/<名前空間名>/quarkus-getting-started 1.0 a19e4a0c4950 imanishi 17 minutes ago 45 MB 24 件の問題
OK
IKSクラスターの作成
IKSクラスター作成ページにアクセスします。
「プランの選択」で「無料」を選択します。
その他はデフォルトのままで、「作成」ボタンをクリックします。
以下の画面の上部のクラスター名(mycluster-free)の右側にクラスター作成の進行状況が表示されるので、「正常」となるまで待ちます(クラスターの作成には数十分程度かかります)。
クラスターの作成が完了後、クラスターにkubectlでアクセスできるように設定します。
以下のコマンドを実行し、再度ログインします。
(無料のIKSクラスターはus-southに作成されるので、リージョンをus-southに変更)
ibmcloud login -a cloud.ibm.com -r us-south -g Default
上記のクラスター作成完了画面に表示されている「ibmcloud ks cluster config ...」コマンドを実行します。
ibmcloud ks cluster config --cluster <画面に表示されている値を入力>
kubeconfigにクラスターの情報が設定されるので、以下のコマンドでコンテキストを切り替えます。
kubectl config use-context <クラスター作成時に設定したクラスター名(デフォルトは mycluster-free)>/<ibmcloud ks cluster config 実行時の--clusterオプションの値>
以下のコマンドを実行し、IKSクラスターのノードが取得できることを確認します。
kubectl get nodes
IKSへのマニフェストファイルのapply
最後に、Kubernetesのマニフェストファイルを作成し、IKSにapplyすることで、QuarkusサンプルアプリをIKSにデプロイします。
以下のコマンドを実行し、IKSのWorkerノードの「パブリックIPアドレス」を確認します。
ibmcloud ks worker ls --cluster <クラスター作成時に設定したクラスター名(デフォルトは mycluster-free)>
「quarkus-getting-started.yaml」というファイルを作成し、以下の内容をコピペします。
image で指定している <名前空間名> は、Container Registryの該当の名前空間名に置き換えてください。
apiVersion: apps/v1
kind: Deployment
metadata:
name: quarkus-getting-started
spec:
replicas: 1
selector:
matchLabels:
app: quarkus-getting-started
template:
metadata:
labels:
app: quarkus-getting-started
spec:
containers:
- name: quarkus
image: jp.icr.io/<名前空間名>/quarkus-getting-started:1.0
ports:
- containerPort: 8080
---
apiVersion: v1
kind: Service
metadata:
name: quarkus-getting-started
labels:
app: quarkus-getting-started
spec:
ports:
- port: 8080
selector:
app: quarkus-getting-started
type: NodePort
以下のコマンドで、上記のマニフェストファイルをapplyします。
kubectl apply -f quarkus-getting-started.yaml
以下のコマンドで、QuarkusサンプルアプリのPodが稼働している(STATUSがRunningである)ことを確認します。
❯ kubectl get pods
NAME READY STATUS RESTARTS AGE
quarkus-getting-started-85cf4884f-lnxg8 1/1 Running 0 13s
以下のコマンドを実行し、QuarkusサンプルアプリのNodePortサービスのポート番号を確認します。(下記の例では 32423)
❯ kubectl get service
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP xxx.xxx.xxx.xxx <none> 443/TCP 167m
quarkus-getting-started NodePort xxx.xxx.xxx.xxx <none> 8080:32423/TCP 24s
ここまでで確認したWorkerノードのパブリックIPアドレスと、NodePortのポート番号を組み合わせ、以下のcurlコマンドを実行します。
curl -w "\n" http://<WorkerノードのパブリックIPアドレス>:<NodePortのポート番号>/hello
「hello」という文字列が返れば成功です。
これでQuarkusのネイティブアプリをIKSにデプロイすることができました。