概要
Spring Bootで開発したアプリケーションをKubernetes環境上へ展開してみたため、備忘録も兼ねてまとめます。
なお、jarのビルドやコンテナイメージ作成などを1つ1つ順に進める形式で実施しております。
(実際はCloud Native Buildpacks等を利用するとより簡単かと思います)
本記事の対象
- Kubernetesを触り始めた方
- SpringアプリケーションをKubernetes上へ展開したい方
用意するもの
- Springで開発したアプリケーション
- Kubernetes環境
- コンテナリポジトリ
Springで開発したアプリケーション
ご自身で展開してみたいSpringアプリケーションをご用意ください。
なお、本記事では過去作った以下のアプリケーションを展開してみております。
こちらのアプリケーションはビルドはMavenでJavaのバージョンは11を指定しており、本記事でもそれベースで記載しています。
そのため、必要に応じてご自身のアプリケーションのものと置き換えていただけたらと思います。
Kubernetes環境
以下図のようなKubernetes環境となります。
本来はコンテナイメージを作成する環境と展開先のKubernetes環境は分けた方がよいと思いますが、今回はまとめて展開先のMasterNode上でイメージ作成なども実施しております。
一応以下記事に同じ構成を作成する手順をまとめております。
コンテナリポジトリ
コンテナイメージを作成したあとに格納しておくためのコンテナリポジトリが必要となります。
本記事ではDocker Hubを利用しておりますが、プライベートリポジトリなどがあればそちらでも問題ないと思います。
手順
それではここからアプリケーションをKubernetesへ展開するまでの手順を記載します。
流れは以下となります。
- アプリケーションのビルド
- コンテナイメージの作成
- コンテナリポジトリへ登録
- Kubernetesへデプロイ
なお前述でも記載した通り、本記事では上記手順すべてMasterNode上で実施しています。
アプリケーションのビルド
まず対象のアプリケーションを用意します。
ここではgit hubからクローンします。
git clone https://github.com/murajo/RandomGreetingSpring.git
続いてビルドするためのパッケージをインストールします。
※対象のアプリケーション側に合わせてMavenをインストールしています
sudo apt install maven
# 動作確認
mvn --version
# 出力
Apache Maven 3.6.3
Maven home: /usr/share/maven
Java version: 11.0.17, vendor: Ubuntu, runtime: /usr/lib/jvm/java-11-openjdk-amd64
Default locale: en_US, platform encoding: UTF-8
OS name: "linux", version: "5.4.0-135-generic", arch: "amd64", family: "unix"
ビルドツールの準備が出来たため、用意したアプリケーションのフォルダへ移動してビルド用のコマンドを実行します。
mvn install
# 出力抜粋(若干時間がかかる)
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
無事にビルドが完了しますと、targetフォルダの中にjarファイルが作成されます。
作成されたjarファイルを試しに実行してみて動作を確認してみます。
私のアプリケーションではREST APIで3種類のJSONから1つをランダムで返す仕組があるため、試しにcurlを実行してみます。
# jarを実行
java -jar target/RandomGreeting-0.0.1-SNAPSHOT.jar
# curlで動作確認
curl -X POST http://localhost:8080/greeting/search
# 出力
{"greetingId":3,"greeting":"Good evening","imagePath":"http://urx3.nu/xUVy"}
問題なく実行できていることが確認できました。
以上でビルドは完了となります。
コンテナイメージの作成
ここからは先程ビルドしたjarを用いてコンテナイメージを作成していきます。
まずはイメージ作成用に以下のようなDockerfileをアプリケーションのフォルダ直下に作成します。
※ FROMのjdkのバージョンはビルドしたアプリケーションに合わせて記載ください
FROM openjdk:11
ARG JAR_FILE=target/*.jar
COPY ${JAR_FILE} app.jar
ENTRYPOINT ["java","-jar","/app.jar"]
作成したDockerfileでイメージを作成します。
※タグ名は後程コンテナリポジトリに合わせてタグ付けしなおします
sudo docker build -t {任意の名前} .
#出力
Successfully built 8b9de8bdb44b
Successfully tagged {前述で記載した名前}:latest
コンテナイメージが作成されたか確認します。
sudo docker images
# 出力
REPOSITORY TAG IMAGE ID CREATED SIZE
randomgreeting latest 8b9de8bdb44b 2 hours ago 691MB
無事に作成されていることが確認できました。
それでは作成されたイメージでコンテナを起動して、動作を見てみます。
※実行コマンド内の「randomgreeting」の箇所は設定したタグ名に変更ください。
# コンテナを起動
sudo docker run -p 80:8080 randomgreeting
# curlで動作確認
curl -X POST http://localhost/greeting/search
# 出力
{"greetingId":3,"greeting":"Good evening","imagePath":"http://urx3.nu/xUVy"}
問題なく実行できていることが確認できました。
以上でコンテナイメージの作成は完了となります。
コンテナリポジトリへ登録
ここから作成したコンテナイメージをコンテナリポジトリへ登録していきます。
なお本記事ではDocker hubをベースで説明します。
まずブラウザからDocker Hubへログインを行い、リポジトリの作成をしておきます。
Create repositoryの画面へ飛び、Nameを入力してCreateボタンを押します。
リポジトリの作成が完了しましたら、ユーザー名込みのリポジトリ名を確認しておきます。
以下図ですと storoveryjam/randomgreeting となります。
それでは先程作成したコンテナイメージをリポジトリへ上げる準備を進めます。
まず作成したリポジトリとコンテナイメージの名前を合わせておきます。
sudo docker tag {作成したコンテナイメージ名} {リポジトリ名}
# 本記事上のサンプル
# sudo docker tag randomgreeting storoveryjam/randomgreeting
イメージの一覧を確認すると、同じIDでもう1つイメージが出来ていることが確認できます。
sudo docker images
# 出力
REPOSITORY TAG IMAGE ID CREATED SIZE
randomgreeting latest 8b9de8bdb44b 2 hours ago 691MB
storoveryjam/randomgreeting latest 8b9de8bdb44b 2 hours ago 691MB
それでは利用しているDocker hubにログインを行い、Pushを実行します。
# dockerへログイン
# ユーザー名とパスワードを聞かれるため、入力してください
sudo docker login
# Docker hubへPush
sudo docker push storoveryjam/randomgreeting
Push完了後、ブラウザのDocker hubへ戻り、イメージが追加されていれば完了となります。
補足
今回手順としてDocker hub上でリポジトリを作成してからその名前に合わせてPushを実施しましたが、実際にはこの部分は省略可能です。
あらかじめコンテナイメージの名前を{リポジトリのユーザー名/イメージ名}のようにPush先のユーザー名が入っていれば、自動でDocker hub上にリポジトリも作成されます。
本記事上ではわかりやすくるために丁寧に行いましたが、省いていただいて問題ございません。
Kubernetesへデプロイ
それでは最後にKuberntesへのデプロイを行っていきます。
まずデプロイのために各マニフェストを作成します。
ここではkubectl createコマンドでイメージを指定してマニフェストを生成しています。
# Podのマニフェスト作成
kubectl create deployment {任意の名前} --image {コンテナリポジトリの名前} -o yaml --dry-run=client > deployment.yaml
# Serviceのマニフェスト作成
kubectl create service clusterip {Pod側で指定した任意の名前} --tcp 80:8080 -o yaml --dry-run=client > service.yaml
# 本記事上のサンプル
# kubectl create deployment randomgreeting --image storoveryjam/randomgreeting -o yaml --dry-run=client > deployment.yaml
# kubectl create service clusterip randomgreeting --tcp 80:8080 -o yaml --dry-run=client > service.yaml
それではマニフェストの用意が出来たので、それぞれデプロイします。
合わせてデプロイした内容を確認して無事にデプロイがされていれば問題ないです。
kubectl apply -f deployment.yaml
kubectl apply -f service.yaml
kubectl get svc,pods
# 出力
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/randomgreeting ClusterIP 10.106.228.69 <none> 80/TCP 2m21s
NAME READY STATUS RESTARTS AGE
pod/randomgreeting-849cb56466-s68dj 1/1 Running 0 2m22s
それではservice側に記載されている「CLUSTER-IP」へリクエストを投げて動作を見てみます。
# curlで動作確認
curl -X POST 10.106.228.69/greeting/search
# 出力
{"greetingId":2,"greeting":"Hello","imagePath":"http://urx3.nu/REm4"}
無事に動作していることが確認できました。
以上でKubernetsへのデプロイまで完了となります。
おまけ
私のサンプルアプリケーションは一応Web UIもあり、せっかくなのでLBを設定してブラウザから見てみようと思います。
※同じようにWeb UIがあるアプリケーションで実施されてましたら、よければお試しください。
今回はLBをあらかじめ使用できる環境にKubernetesがなっている前提とします。
参考として以下記事のリンク先箇所にてMetallbを使ったクラスタ外への公開の仕方をまとめております。
それでは実際に設定していきます。
といいつつやることは少なく単純で、先程デプロイしたservice.yamlの下の方の行のTypeをLoadBalancer変更して再デプロイをするだけとなります。
apiVersion: v1
kind: Service
metadata:
creationTimestamp: null
labels:
app: randomgreeting
name: randomgreeting
spec:
ports:
- name: 80-8080
port: 80
protocol: TCP
targetPort: 8080
selector:
app: randomgreeting
type: LoadBalancer
status:
loadBalancer: {}
変更したら再デプロイをして情報を確認します。
kubectl apply -f service.yaml
kubectl get svc
# 出力
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
randomgreeting LoadBalancer 10.98.92.199 172.22.18.216 80:30279/TCP 5s
EXTERNAL-IPに記載されたIPアドレスへ同じネットワーク内のブラウザからアクセスを行いますと、対象のアプリケーションのWeb UIが確認できました。
※URLの後ろのパスなどは各々のアプリケーションに合わせて追記ください
最後に
今回はSpring Bootで開発したアプリケーションをKubernetes上に展開するまでの一連の流れを記載しました。
一方Cloud Native Buildpacksを使うとビルドからイメージ作成までより簡単に実現できるらしいので、手軽さという観点ではそちらを触ってみるのもよいと考えております。
(また、Tanzu Application Platoformではgithub上のソースコードのURLでそのまま公開URLの掃き出しまで行えるらしいです)
ただし便利なツール群を使う前に実際はどのようなことを裏でやっているのかと知る上では、今回のように1つ1つ実施してみるのもよいかなと思っております。