Nullable<T>

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で動かしてみる。 サンプルアプリケーションにはLombokFlywayを入れているが、本質的ではないので割愛。

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 HubAccountを持っていない方は予め作っておこう。

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

また、以下を実行し、PostgreSQLClusterIPを取得し、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が行えるか確認できる。(hostportは上記の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を返すServiceAPIServiceを振り分けて実際のプロダクトに落とし込むところまでやってみよう。

関連: IntelliJでSpringBootを始める


Written by Ryo @neer_chan

© 2018-2020 Nullable<T>