KubernetesでSpringBootアプリケーションを動かす
March 11, 2019
Preparing
MacOS
にて Minikube
( + VirtualBox
) を利用して動かしてみる。
インストールしていない方は以下のコマンドを実行する。
brew install minikube
brew install virtualbox
minikube start
Application
Java 8
SpringBoot
Gradle
PostgreSQL
サンプルアプリケーション(GitHub)をKubernetes
で動かしてみる。
サンプルアプリケーションにはLombok
やFlyway
を入れているが、本質的ではないので割愛。
Build JAR File
./gradlew clean build
Build Image
<docker-hub-account>
には自分のDocker Hub
アカウントを入れる。
Build
$ docker build -t <docker-hub-account>/demo-api:v0.1.0 --build-arg VERSIONS='0.1.0' .
Push
$ docker push <docker-hub-account>/demo-api:v0.1.0
Docker Hub
のAccount
を持っていない方は予め作っておこう。
Deployment and Service for PostgreSQL
Deployment etc.
postgres-deployment.yaml
を作成する。
apiVersion: v1
kind: ConfigMap
metadata:
name: postgres-config
namespace: default
data:
postgres_user: admin
postgres_password: password
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: postgres-pv-claim
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 32Gi
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: postgres
spec:
template:
metadata:
labels:
app: postgres
spec:
volumes:
- name: postgres-storage
persistentVolumeClaim:
claimName: postgres-pv-claim
containers:
- image: postgres
name: postgres
env:
- name: POSTGRES_USER
valueFrom:
configMapKeyRef:
name: postgres-config
key: postgres_user
- name: POSTGRES_PASSWORD
valueFrom:
configMapKeyRef:
name: postgres-config
key: postgres_password
- name: PGDATA
value: /var/lib/postgresql/data/pgdata
ports:
- containerPort: 5432
name: postgres
volumeMounts:
- name: postgres-storage
mountPath: /var/lib/postgresql/data
kind: PersistentVolumeClaim
はデータ永続化のため。
以下を実行し、Deployment
を作成する。
$ kubectl create -f postgres-deployment.yaml
Service
postgres-service.yaml
を作成する。
apiVersion: v1
kind: Service
metadata:
name: postgres
spec:
type: ClusterIP
ports:
- port: 5432
selector:
app: postgres
以下を実行し、Service
を作成する。
$ kubectl create -f postgres-service.yaml
また、以下を実行し、PostgreSQL
のClusterIP
を取得し、ConfigMap
を作成する。
kubectl create configmap hostname-config --from-literal=postgres_host=$(kubectl get svc postgres -o jsonpath="{.spec.clusterIP}")
Deployment and Service for SpringBoot Application
Deployment
spring-boot-deployment.yaml
を作成する。
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: demo-api
namespace: default
spec:
replicas: 1
template:
metadata:
name: demo-api
labels:
app: demo-api
spec:
containers:
- name: demo-api
env:
- name: POSTGRES_USER
valueFrom:
configMapKeyRef:
name: postgres-config
key: postgres_user
- name: POSTGRES_PASSWORD
valueFrom:
configMapKeyRef:
name: postgres-config
key: postgres_password
- name: POSTGRES_HOST
valueFrom:
configMapKeyRef:
name: hostname-config
key: postgres_host
image: <docker-hub-account>/demo-api:v0.1.0
ports:
- containerPort: 80
以下を実行し、Deployment
を作成する。
$ kubectl create -f spring-boot-deployment.yaml
Service
spring-boot-service.yaml
を作成する。
apiVersion: v1
kind: Service
metadata:
name: demo-api-svc
spec:
type: NodePort
ports:
- protocol: TCP
port: 8080
targetPort: 80
selector:
app: demo-api
Minikube
の場合、type:LoadBalancer
に関してはminikube tunnel
というコマンドでIPを特定できる。
が、今回はNodePort
を指定する。
ここのあたり、様々な構成があると思うので、色々な構成を見るといいのかも。
以下を実行し、Service
を作成する。
$ kubectl create -f spring-boot-service.yaml
Checking
以下のコマンドでURL
を取得する。
minikube service demo-api-svc --url
また、以下のCURL
で実際にCRUD
が行えるか確認できる。(host
とport
は上記のURLを参考に入れる)
$ curl -X GET http://host:port/account
$ curl -X POST http://host:port/account -d '{"name":"demo", "age": 10}' -H "Content-Type: application/json"
$ curl -X PUT http://host:port/account -d '{"id": 1, "name":"demo", "age": 12}' -H "Content-Type: application/json"
$ curl -X DELETE http://host:port/account -d '{"id": 1, "name":"demo", "age": 12}' -H "Content-Type: application/json"
Deleting
$ kubectl delete -f spring-boot-deployment.yaml
$ kubectl delete -f postgres-deployment.yaml
$ kubectl delete -f spring-boot-service.yaml
$ kubectl delete -f postgres-service.yaml
$ kubectl delete cm hostname-config
まとめ
複数のService
を立てる場合はIngress
を用意し、そこでパスを振り分けると良い。
Kubernetes
で実際にアプリケーションを動かしてみると、レプリカを増やすなどそういったスケーリングがとても簡単にできて感動する。
実際にIngress
を立ててHTML
を返すService
とAPI
のService
を振り分けて実際のプロダクトに落とし込むところまでやってみよう。
Written by Ryo @neer_chan