minikube(kubernetes) でコンテナを動かしてみる

# はじめに

記載情報は CI/CD に関連します。  
実務上関わった環境・機能を身近な情報としてお届けしたく、投稿をはじめました。  
各学習上、お金のかからない方法を選択していきます。

以下の手順を実施することで、アプリケーション開発者が minikube(kubernetes) でコンテナを動かしてみる工程を模倣します。

## 対象者と関連環境・機能

この記事は下記のような人を対象にしています。

- CI/CD 初学者
- プログラミング初学者
- 駆け出しエンジニア

記載している環境・機能は以下です。

- Java
- Spring Boot
- Spring Web
- minikube(kubernetes)

## リリース環境の検討

ここまでは Azure Devops の利用にて無料で繰り返し利用可能な内容でこれたのですが、コンテナレジストリに登録したイメージをもって kubernetes 環境へリリースしていく上では方法が限定的となってきます。  
ここでは無償で利用可能な minikube を活用することとし、また実際のところ実務で困り次第、家で真っ先に触るのが minikube でしたのでぜひともご紹介させて頂きます。

## 前提作業

- Docker hub にイメージを登録済の前提で記載しております。詳細は以下をご参照ください。

  - [アプリを Docker 、Docker Compose でコンテナを動かしてみる](https://qiita.com/wf-kenji-ikeda/items/e6604ea6ae257f3925a7)

- minikube、kuectl のインストール

  - [minikube Get Started!](https://minikube.sigs.k8s.io/docs/start/)
  - [Linux へ kubectl をインストールする](https://kubernetes.io/ja/docs/tasks/tools/install-kubectl/#install-kubectl-on-linux)

- サンプルアプリケーションの配置

  - [manifest-files 追加](https://github.com/oad3/application-springboot/tree/feature/add-manifest-files)

  最新はこちらとなりますが、clone 後に初期状態を遡って確認頂けます。

  - [サンプルアプリ の最新](https://github.com/oad3/application-springboot)

## 必要作業

minikube を起動します。

```minikube start
$ minikube start
* Ubuntu 20.04 上の minikube v1.22.0
* minikube 1.25.2 が利用可能です! 以下のURLでダウンロードできます。 https://github.com/kubernetes/minikube/releases/tag/v1.25.2
* To disable this notice, run: 'minikube config set WantUpdateNotification false'

* プロフィールを元に、 docker ドライバを使用します
* コントロールプレーンのノード minikube を minikube 上で起動しています
* イメージを Pull しています...
* 既存の docker container を "minikube" のために再起動しています...
* Docker 20.10.7 で Kubernetes v1.21.2 を準備しています...
* Kubernetes コンポーネントを検証しています...
  - イメージ kubernetesui/dashboard:v2.1.0 を使用しています
  - イメージ gcr.io/k8s-minikube/storage-provisioner:v5 を使用しています
  - イメージ kubernetesui/metrics-scraper:v1.0.4 を使用しています
* 有効なアドオン: storage-provisioner, default-storageclass, dashboard

! /usr/local/bin/kubectl is version 1.23.5, which may have incompatibilites with Kubernetes 1.21.2.
  - Want kubectl v1.21.2? Try 'minikube kubectl -- get pods -A'
* 完了しました！ kubectl が「"minikube"」クラスタと「"default"」ネームスペースを使用するよう構成されました

$ minikube status
minikube
type: Control Plane
host: Running
kubelet: Running
apiserver: Running
kubeconfig: Configured
```

service、deployment を作成します。

- app-deployment.yml

```app-deployment.yml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: springbootapp-deployment
spec:
  replicas: 1
  selector:
    matchLabels:
      app: springbootapp
  template:
    metadata:
      labels:
        app: springbootapp
    spec:
      containers:
        - image: oad3jp999/application-springboot:0.0.1
          name: springbootapp
          ports:
            - containerPort: 8080
      restartPolicy: Always
```

- app-service.yml

```app-service.yml
apiVersion: v1
kind: Service
metadata:
  name: springbootapp-service
spec:
  type: NodePort
  ports:
    - name: "http"
      port: 49161
      targetPort: 8080
      nodePort: 30001
  selector:
    app: springbootapp
```

kubectl apply を実行して、作成したマニフェストを元にリソースの作成を行います。

```
$ kubectl apply -f app-deployment.yml
deployment.apps/springbootapp created
$ kubectl apply -f app-service.yml
service/springbootapp created
```

Node の情報と、Service の情報を出力することで接続情報が得られます。
ホストの ubuntu から以下の順で接続が可能です。

- minikube Node ： 192.168.58.2 へのアクセスは可能
- 今回、NodePort を利用しているため Node-Ip(192.168.58.2)、nodePort(30001) を指定することで、minikube 内でコンテナへ転送。(49161)
- ホストの ubuntu からではなく、minikube コンテナからであれば CLUSTER-IP(10.105.152.126)へアクセスが可能で、その際に PORT：49161 を指定。

```
$ kubectl get nodes -o wide
NAME       STATUS   ROLES                  AGE    VERSION   INTERNAL-IP    EXTERNAL-IP   OS-IMAGE             KERNEL-VERSION      CONTAINER-RUNTIME
minikube   Ready    control-plane,master   273d   v1.21.2   192.168.58.2   <none>        Ubuntu 20.04.2 LTS   5.13.0-40-generic   docker://20.10.7

$ kubectl get services -o wide
NAME                    TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)           AGE     SELECTOR
kubernetes              ClusterIP   10.96.0.1        <none>        443/TCP           273d    <none>
springbootapp-service   NodePort    10.105.152.126   <none>        49161:30001/TCP   9m42s   app=springbootapp
```

minikube service xxx --url にて接続可能な URL を出力が可能です。
先ほどの想定通り、Node-Ip(192.168.58.2)、nodePort(30001) で URL が得られ、接続結果も良好。

```
$ minikube service springbootapp-service --url
http://192.168.58.2:30001

$ curl http://192.168.58.2:30001
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Hello SpringBoot Web Page</title>
</head>
<body>
    <H1>Hello SpringBoot Web Page</H1>
    </br>
    <form method="post" action="/result">
        Please input name<br>
        <input type="text" name="inputvalue"/>
        <input type="submit" value="submit" />
    </form>
</body>

$ kubectl get pods
NAME                                        READY   STATUS    RESTARTS   AGE
springbootapp-deployment-6bf7b645c9-rj95s   1/1     Running   0          43m

$ kubectl logs springbootapp-deployment-6bf7b645c9-rj95s
 =========================================
 Hello LibraryJar!
 =========================================


  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::                (v2.6.7)

2022-05-08 04:43:28.521  INFO 1 --- [           main] com.example.demo.DemoApplication         : Starting DemoApplication using Java 11.0.12 on springbootapp-deployment-6bf7b645c9-rj95s with PID 1 (/usr/src/myapp/application-springboot-0.0.1-SNAPSHOT.jar started by root in /usr/src/myapp)
2022-05-08 04:43:28.524  INFO 1 --- [           main] com.example.demo.DemoApplication         : No active profile set, falling back to 1 default profile: "default"
2022-05-08 04:43:30.571  INFO 1 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat initialized with port(s): 8080 (http)
2022-05-08 04:43:30.585  INFO 1 --- [           main] o.apache.catalina.core.StandardService   : Starting service [Tomcat]
2022-05-08 04:43:30.586  INFO 1 --- [           main] org.apache.catalina.core.StandardEngine  : Starting Servlet engine: [Apache Tomcat/9.0.62]
2022-05-08 04:43:30.805  INFO 1 --- [           main] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
2022-05-08 04:43:30.806  INFO 1 --- [           main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 2155 ms
2022-05-08 04:43:31.671  INFO 1 --- [           main] o.s.b.a.w.s.WelcomePageHandlerMapping    : Adding welcome page template: index
2022-05-08 04:43:31.878  INFO 1 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8080 (http) with context path ''
2022-05-08 04:43:31.895  INFO 1 --- [           main] com.example.demo.DemoApplication         : Started DemoApplication in 4.695 seconds (JVM running for 5.661)
2022-05-08 04:46:11.598  INFO 1 --- [nio-8080-exec-1] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring DispatcherServlet 'dispatcherServlet'
2022-05-08 04:46:11.598  INFO 1 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : Initializing Servlet 'dispatcherServlet'
2022-05-08 04:46:11.599  INFO 1 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : Completed initialization in 1 ms
```

minikube 起動後にはホスト上で minikube コンテナが稼働しているので、クラスタ経由の接続も行ってみます。

```
$ docker ps
CONTAINER ID   IMAGE                                 COMMAND                  CREATED      STATUS             PORTS             NAMES
827b4c57966c   gcr.io/k8s-minikube/kicbase:v0.0.25   "/usr/local/bin/entr…"   3 days ago   Up About an hour  省略              minikube

$ docker exec -it minikube /bin/bash
root@minikube:/# curl http://10.105.152.126:49161
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Hello SpringBoot Web Page</title>
</head>
<body>
    <H1>Hello SpringBoot Web Page</H1>
    </br>
    <form method="post" action="/result">
        Please input name<br>
        <input type="text" name="inputvalue"/>
        <input type="submit" value="submit" />
    </form>
</body>
</html>root@minikube:/#
```

Web UI (Dashboard) 操作も可能

```
$ minikube dashboard --url
樂  ダッシュボードの状態を確認しています...
  プロキシを起動しています...
樂  プロキシの状態を確認しています...
http://127.0.0.1:32777/api/v1/namespaces/kubernetes-dashboard/services/http:kubernetes-dashboard:/proxy/
```

## 関連記事

- [CI/CD とは?](https://qiita.com/wf-kenji-ikeda/items/bfb6d5e21b33d0cca83b)
- [Azure Devops (Artifacts) を無償、無料で使う](https://qiita.com/wf-kenji-ikeda/items/9c21859d8b5b6a63246e)
- [Spring Tool Suite 4 インストール、Spring Initializr 、gradlew の利用](https://qiita.com/wf-kenji-ikeda/items/d00766da8a4076ec43ed)
- [Spring Boot Web アプリケーションを作る](https://qiita.com/wf-kenji-ikeda/items/1e64e44094ce8a1d997f)
- [Jar の Library を作り、Azure Artifacts を利用して成果物を配布する](https://qiita.com/wf-kenji-ikeda/items/696bda335a8933abfcb3)
- [ライブラリ開発者より指定されたバージョンを利用してアプリを作る](https://qiita.com/wf-kenji-ikeda/items/5bf06ce19c52e73a5463)
- [アプリを Docker 、Docker Compose でコンテナを動かしてみる](https://qiita.com/wf-kenji-ikeda/items/e6604ea6ae257f3925a7)
- [Azure Devops (PileLines) を無償、無料で使う](https://qiita.com/wf-kenji-ikeda/items/451838da3b4ac45a8d65)
- [Azure Devops (PileLines) でテスト、ビルド、イメージプッシュをする](https://qiita.com/wf-kenji-ikeda/items/5ddf6158bb98c4174db9)
- [minikube(kubernetes) でコンテナを動かしてみる](https://qiita.com/wf-kenji-ikeda/items/95604d83850a17b91c46)
- [nginx のコンテナを Docker や minikube(kubernetes) で動かし、静的コンテンツ公開工程を模倣](https://qiita.com/wf-kenji-ikeda/items/bf6cb1b7a047f562d309)