Kubernetes 環境の Spring Boot WEBサービスのリバースプロキシ構成

# Kubernetes 環境の Spring Boot WEBサービスのリバースプロキシ構成

## 目的

[Kubernetes 環境で起動した Spring Boot WEBサービス](https://qiita.com/hiroxpepe/items/48cec2f3b87811411b61)にリバースプロキシを設定して理解を深めます。  

## 実現すること

ローカル (Ubuntu) の Kubernetes 環境 (Docker Desktop) に Nginx と Spring Boot WEBアプリの Docker イメージをデプロイ・起動します。

## 開発環境

+ Windows 11 Home 22H2 を使用しています。  
+ [WSL](https://learn.microsoft.com/ja-jp/windows/wsl/about) の Ubuntu を操作していきますので macOS の方も参考にして頂けます。  

<details>

WSL (Microsoft Store アプリ版)

```sh
> wsl --version
WSL バージョン: 1.0.3.0
カーネル バージョン: 5.15.79.1
WSLg バージョン: 1.0.47
```

Ubuntu

```sh
$ lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description:    Ubuntu 22.04.1 LTS
Release:        22.04
```

Java JDK [※ 最小構成 Java JDK の導入と Hello World!](https://qiita.com/hiroxpepe/items/8650664e466906a57996)

```sh
$ java -version
openjdk version "11.0.17" 2022-10-18
OpenJDK Runtime Environment (build 11.0.17+8-post-Ubuntu-1ubuntu222.04)
OpenJDK 64-Bit Server VM (build 11.0.17+8-post-Ubuntu-1ubuntu222.04, mixed mode, sharing)
```

Maven [※ 最小構成 Maven の導入と Hello World!](https://qiita.com/hiroxpepe/items/40f7f199b9be7f9e3b5b)

```sh
$ 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
```

Docker Desktop

```sh
Version 4.16.3 (96739)
```

```sh
$ docker --version
Docker version 20.10.22, build 3a2c30b
```

```sh
$ docker-compose --version
Docker Compose version v2.15.1
```

```sh
$ kubectl version --short
Client Version: v1.25.4
Kustomize Version: v4.5.7
Server Version: v1.25.4
```

</details>

※ この記事では基本的に Ubuntu のターミナルで操作を行います。

## "Hello World" を表示する手順

### Spring Boot WEBサービスの作成

[最小構成 Spring Boot WEBサービスの Hello World!](https://qiita.com/hiroxpepe/items/4a0f5e077155ce41e7ac) を参照してください。  

プロジェクトフォルダに移動  
※ ~/tmp/hello-spring-boot をプロジェクトフォルダとします。

```sh
$ cd ~/tmp/hello-spring-boot
```

### Docker イメージを作成

[Spring Boot WEBサービスを Docker 環境で起動する](https://qiita.com/hiroxpepe/items/41dd8b4e18213aab1775#docker-%E3%82%A4%E3%83%A1%E3%83%BC%E3%82%B8%E3%82%92%E4%BD%9C%E6%88%90) を参照してください。  

### Kubernetes 環境の準備

#### Docker Desktop  

[Settings] → [Kubernetes]  

+ [x] Enable Kubernetes

### Kubernetes のマニュフェストファイルを修正

```sh
$ vim kube-all-in-one.yaml
```

ファイルの内容

```yaml
apiVersion: v1
kind: Service
metadata:
  name: app-service
spec:
  selector:
    app: app
  ports:
  - name: http
    port: 8080
    targetPort: 8080
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: app-deployment
spec:
  replicas: 1
  selector:
    matchLabels:
      app: app
  template:
    metadata:
      labels:
        app: app
    spec:
      containers:
      - name: app
        image: app-hello-spring-boot
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 8080
---
apiVersion: v1
kind: Service
metadata:
  name: web-service
spec:
  type: NodePort
  selector:
    app: web
  ports:
  - name: http
    port: 80
    targetPort: 80
    nodePort: 30000
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: web-deployment
spec:
  replicas: 1
  selector:
    matchLabels:
      app: web
  template:
    metadata:
      labels:
        app: web
    spec:
      containers:
      - name: web
        image: nginx:latest
        ports:
        - containerPort: 80
        volumeMounts:
        - name: web-config
          mountPath: /etc/nginx/nginx.conf
          subPath: nginx.conf
      volumes:
      - name: web-config
        configMap:
          name: web-config
---
apiVersion: v1
kind: ConfigMap
metadata:
  name: web-config
data:
  nginx.conf: |
    events {
    }

    http {
      server {
        listen 80;
        location / {
          proxy_pass http://app-service:8080;
          proxy_set_header Host $host;
          proxy_set_header X-Real-IP $remote_addr;
        }
      }
    }
```

### ディレクトリ・ファイル構成

```sh
$ tree -I test -I target
.
├── Dockerfile
├── HELP.md
├── docker-compose.yml
├── kube-all-in-one.yaml
├── mvnw
├── mvnw.cmd
├── nginx.conf
├── pom.xml
└── src
    └── main
        ├── java
        │   └── com
        │       └── example
        │           └── springboot
        │               ├── SpringbootApplication.java
        │               └── controller
        │                   └── DataController.java
        └── resources
            ├── application.properties
            ├── static
            └── templates
```

### Kubernetes 環境

接続先を確認

```sh
$ kubectl config current-context
docker-desktop
```

※ 接続先をローカル (docker-desktop) に戻す場合

```sh
$ kubectl config use-context docker-desktop
```

デプロイ

```sh
$ kubectl apply -f kube-all-in-one.yaml
service/app-service created
deployment.apps/app-deployment created
service/web-service created
deployment.apps/web-deployment created
configmap/web-config created
```

状態確認

```sh
$ kubectl get pods,services,deployments
NAME                                  READY   STATUS    RESTARTS   AGE
pod/app-deployment-cdc7dcbf9-2f9wm    1/1     Running   0          19s
pod/web-deployment-86b95b4b97-4mdc5   1/1     Running   0          19s

NAME                  TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)        AGE
service/app-service   ClusterIP   10.96.102.36     <none>        8080/TCP       19s
service/kubernetes    ClusterIP   10.96.0.1        <none>        443/TCP        3m16s
service/web-service   NodePort    10.102.128.228   <none>        80:30000/TCP   19s

NAME                             READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/app-deployment   1/1     1            1           19s
deployment.apps/web-deployment   1/1     1            1           19s
```

※ Docker Desktop を確認するとコンテナとして起動しています。  

WEBブラウザで確認  

```sh
http://localhost:30000/api/data
```

WEBブラウザに {"message":"Hello World!"} と表示され、JSON データを取得することが出来ました。  

※ もしくは別ターミナルのコマンドで確認

```sh
$ curl -X GET http://localhost:30000/api/data
{"message":"Hello World!"}
```

### リバースプロキシ動作の確認

Nginx POD のログを確認

```sh
$ kubectl get pods | grep web
$ kubectl logs web-deployment-86b95b4b97-rghsn
192.168.65.4 - - [16/Feb/2023:09:10:06 +0000] "GET /api/data HTTP/1.1" 200 37 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.0.0 Safari/537.36"
```

Nginx 経由で Spring Boot WEBアプリにアクセスしています。  

## まとめ

+ Ubuntu の 最小構成の Java 開発環境で Spring Boot WEBサービスとリバースプロキシを Kubernetes 環境にてコンテナとして起動させることが出来ました。