【移行・設計】almalinuxへのkubernetes導入Tips（k3d編②）

※ 自分用メモのため、誤字脱字は後ほど修正します。
また、いくつか未完了部分は:construction: にしています。 ※

https://zenn.dev/worbridg/articles/80127fa76d0684

## 目的
* 下記記事で、AlmaLinux8.9の仮想サーバの新設とminikubeのインストールを行いましたが、ノートPC環境下（メモリ8GB、CPU4GB）において、オーバーヘッドが生じました。
    * [【移行・設計】centos7からalmalinuxへの移行Tips（k3d編①](https://qiita.com/t_kyn/items/01b799d0fdb1f3686f81)
* 影響として、下記事象が発生しています。
   * インターネット検索、ウイルススキャンといった動作が遅延する
   * ワーカノードの起動時間に10分ほどかかっている
   * リソース不足になると、kubectlコマンドのレスポンスが遅い
* スペックの高いPCに変更しない限り解消ができないため、別なkubernetesのディストリビューションを入れることを検討しました
* また、収支管理目的で構築したLAMPサーバ（Apache、Java、MySQL等）の新たなモダンアーキテクチャ構成も考えることとしました
    * 【移行・設計】centos7からalmalinuxへの移行Tips
    https://qiita.com/t_kyn/items/91f6dbb7c3ef938b9377
---

## 内容
* minikubeよりも軽量なKubernetesディストリビューション（k3s、k3d）を候補としました。
    * [k3s](https://k3s.io/)の場合、ワーカーノードを同一仮想マシンに構築できないという制約があるのに対し、[k3d](https://k3d.io/v5.4.6/)では、ワーカノードを同一仮想マシンに構築することが可能です。
    * k3dの実態は、ワーカノードをコンテナとして作成し、k3sのプロセスを起動し、コンテナ内部でPodを作成しています。
    * 反面、StatefulSetが実現できず、レプリカデータベース用のPodを作成することはできません。
    * データ永続化・冗長化の要件を実現したい場合、代替構成の検討が必要です。
    * deploymentを3つ構成し、マスタデータベースでの障害発生時、他のデータベースへ接続先を手動切替する方針で検討しました。
* 上記を踏まえて、k3dでの構築する方針としています。
    * 参考：https://qiita.com/suin/items/3c4df13ad3478ffe7b5d
---

## 構築の大まかな流れ
* minikubeをアンインストール
    * minikubeをアンインストールします
* k3dインストール
  * https://qiita.com/dennistanaka/items/78585b6bda374be98aad
  * https://qiita.com/tkek321/items/a3af3323ceee31919334
* Kubernatesのマニフェストファイルに沿って、起動する
* ミドルウェアをカスタマイズしていく（後述）

---

## 構築のイメージ図

* イメージ図は以下の通りです
* 仮想サーバ1台をノートPC上に作成しています。
* ディスク使用率を節約するため、コンテナイメージはalpineLinuxをベースとします

### k3dとしてのアーキテクチャ
* 1つの仮想サーバに下記のコンテナ（Loadbalancer、MasterNode、WorkerNode1、WorkerNode2）が搭載されています。
```mermaid
graph TD;
subgraph 'loadbalancer'
loadbalancer
end
subgraph 'MasterNode'
direction TB
api\nservice --- dns
dns --- metrics
nginx1 --- python1
python1 --- mysql1
end
subgraph 'WorkerNode1'
direction TB
nginx2 --- python2
python2 --- mysql2
end
subgraph 'WorkerNode2'
direction TB
nginx3 --- python3
python3 --- mysql3
end
direction TB
loadbalancer ---> 'MasterNode'
loadbalancer ---> 'WorkerNode1'
loadbalancer ---> 'WorkerNode2'
```
### k3dのアーキテクチャ（Pod含む）
* Deployment、Service、Pod、PersistenVolumeを含む構成としては下記の通りとなっております。
* SharedDiskの箇所は、仮想マシンの共有ディレクトリをマウントしています。
```mermaid
graph TD;
subgraph 'loadbalancer'
loadbalancer-->|https|nginxsvc;
end
subgraph 'WebServer_Nginx'
nginxsvc-->|https|nginx1;
nginxsvc-->|https|nginx2;
nginxsvc-->|https|nginx3;
end
subgraph 'APServer_Python'
nginx1-->|http|pythonsvc;
nginx2-->|http|pythonsvc;
nginx3-->|http|pythonsvc;
pythonsvc-->|http|python1;
pythonsvc-->|http|python2;
pythonsvc-->|http|python3;
end
subgraph 'DBServer_MySQL'
python1-->|tcp|mysql\nread\nsvc;
python1==>|tcp|mysql\nwrite\nsvc;
python2-->|tcp|mysql\nread\nsvc;
python3-->|tcp|mysql\nread\nsvc;
mysql\nread\nsvc-->|tcp|mysql1;
mysql\nwrite\nsvc==>|tcp|mysql1;
mysql\nread\nsvc-->|tcp|mysql2;
mysql\nread\nsvc-->|tcp|mysql3;
mysql1==>|''|mysqlpvc1;
mysql2-->|''|mysqlpvc2;
mysql3-->|''|mysqlpvc3;
end
subgraph 'SharedDisk'
mysqlpvc1==>|''|mysqlpv1;
mysqlpvc2-->|''|mysqlpv2;
mysqlpvc3-->|''|mysqlpv3;
end
```

---

### Webサーバ
* :white_check_mark:Webサーバ：ApacheからNginxに変更
    * 選定理由
        * Nginxはアクセスを振り分ける負荷分散やApacheよりも処理性能が高いため
    * 用途・役割
        * 外部アクセスをhttps通信で受付し、PythonPodへhttpリスエストするようプロキシします
        * nginxのPodからservice経由で、PythonのPodへ接続します。
            * serviceの名前解決を利用し、nginxからPythonへの接続設定を行います
        * パスベースで転送先を設定します

---

### APサーバ
* :white_check_mark:APサーバ：TomcatからPythonに変更
    * 選定理由
        * PCのオーバーヘッド防止
            * javaからpythonにすることで、メモリ消費量の削減を期待したため
            * Metabaseの内部結合処理で、JavaVMで使用するメモリを多く消費するため
        * Pythonでの実装はGoogle Colaboratryでスマートフォンでの動作検証も手軽に実施できるため
        * 将来性の期待
            * データ分析やAI、機械学習分野の知識習得も視野に入れたため
        * 参考
            * https://engineer-style.jp/articles/8766#JavaとPythonのデメリットとは
    * 用途・役割
        * Flask、SQLAlchemy、Pandasといったシンプルながらも拡張性・実装がしやすいモジュールを利用します
        * 自作アプリケーションを作成することも視野に入れます
    * 工夫点
        * 機能の細分化
            * アプリケーションの機能がわかるよう、フォルダ、ファイルを分けます
        * アプリケーション間の紐づけ
            * Web－APサーバ間：Flaskのblueprintを利用
            * AP－DBサーバ間：SQLAlchemyを利用
        * SQLalchemyを利用することで、pythonのソースコードにSQL文を実装しない設計にします
        * 操作の種類単位にクラスを作ります
        * テーブルとクラスを1対1で対応させ、Modelsを用います。
        * データフレームやピボット、プロットの作成が可能なpandas、plotlyを導入します

---

### DBサーバ（deploymentとserviceを構築）
* :white_check_mark:DBサーバ：MySQLで現状維持（バージョンアップは行う）
    * 選定理由
        * 既存SQLの作りこみもあり、他のDBMSへの移行が難しくなるため、MySQLを採用します
    * 用途・役割
        * データの保管・集計を行います
    * 工夫点
        * デフォルトではソケット通信が採用され、3306ポートがListenせず、localhostのみアクセスができません
        * そこで、下記を変更することで、MySQLコンテナ上で3306ポートをListenしています
            * MySQLのbind-address = 0.0.0.0に変更
            * MySQLのskip-network設定は除外
            * 3306ポート及びソケットファイルを定義
        * 更新・参照のServiceは別々とします（masterデータベースのみ書き込みできるようにするため）
            * データベース読込用と書込用とでServicePortを分ける
                * R/W用 Service　Port:3306→TargetPort:3306
                  （Selectorでマスターデータベースのみに接続制限）
                * R/O用 Service　Port:3307→TargetPort:3306
        * データ更新
            * 下記で扱ったダンプファイルをエクスポートし、MySQLマスターデータベースに対して、インポートしています。
                * 【移行・設計】centos7からalmalinuxへの移行Tips
                https://qiita.com/t_kyn/items/91f6dbb7c3ef938b9377

---

### DBサーバのストレージ
* PersistentVolume、PerisitentVolumeClaimを個々のMySQLpodに1つ割り当てます
* MySQL-1、MySQL-2、MySQL-3に分け、ストレージもmysqlpv1、mysqlpv2、mysqlpv3と分けていきます

---

### Pythonの実装方針
* Flask、Pandas、SQLAlchemy、plotlyをpip installし導入します。
* 作成するアプリケーションは下記の通り
    * <b>flaskAPI</b>
        * :white_check_mark: flaskをベースとしたアプリケーションにする
        * :white_check_mark: ページの動的作成
    * <b>BIツール専用データベース管理</b>
        * :white_check_mark: 給与
        * :white_check_mark: ライフライン
        * :white_check_mark: 支出
        * :white_check_mark: 収入
        * :white_check_mark: 健康管理
        * :white_check_mark: 株価
        * :white_check_mark: サーバ稼働情報
        * :white_check_mark: ログ保管
        * :white_check_mark: 待機系データベース状態確認
    * <b>AP-DB間のマッピング</b>
        * :white_check_mark: SQLはキーワードごとにまとめて、マッピングファイル化する
        * :white_check_mark: マッピングはFlaskのBlueprintで実装
        * イメージ図は下記の通り
        * :white_check_mark:MySQL1、MySQL2、MySQL3はpod。障害発生時、Pod（Kubernetes）の仕様により再起動し、既存のデータベースに再接続が可能
            ```plantuml
            @startuml
            node "MySQL1" as MySQL1
            node "MySQL2" as MySQL2
            node "MySQL3" as MySQL3
            node "Python" as python
            
            python ==> MySQL1: 書込処理\n3306⇒3306
            python --> MySQL1: 読込処理\n3307⇒3306
            python --> MySQL2: 読込処理\n3307⇒3306
            python --> MySQL3: 読込処理\n3307⇒3306
    
            artifact "3306Port⇒3306Port(書込処理)\n3306Port⇒3306Port(読込処理)"
            
            @enduml
            ```

    * :white_check_mark:BIツール（フォーマット可変）
        * :white_check_mark: Plotlyによるデータベース可視化ツール作成
        * :white_check_mark: グラフの拡大・縮小
    * :construction: wordpress風のドキュメント作成ツール（markdownか、他で検討中）
    * <b>Web-AP間のマッピング</b>
        * :white_check_mark: APIの実装（各URLより、適切なテーブル・グラフを表示）
    * :construction: 外部から接続できるようにする
        * :white_check_mark: ロードバランサーでhttpsで待ち受けて、httpで受付する。
        * :white_check_mark: 証明書は以前から使っているSSL証明書を流用する
        * :construction: 外部接続をするために踏み台をもう一つ作る

---

## 構築方法
構築方法の流れをまとめました。

### レジストリを登録
k3dでカスタムイメージを作成する場合、
コンテナベースのレジストリを登録する必要があるので作成します。

* ディレクトリ作成
`
mkdir -pv /datamnt/data ~/.k3d_t_kyn
`
* ボリューム作成
`
docker volume create local_registry
docker volume ls | grep local_registrylocal
`
* レジストリ用のコンテナ作成
`
docker container run -d --name tkynregistry.local -v local_registry:/datamnt/imgs  --restart always -p 5000:5000 registry:2.8.3
`

---

### k3dクラスタ作成
k3dでクラスタ作成を行います。クラスタ作成時に下記も同時に作成します。
共有ボリュームと共有レジストリは、ワーカノードとホストマシンのディレクトリやファイルをマッピングします。
最上位のディレクトリを共有マウントとして利用します。
まとめると下記図表になります。

|内容|構成|
|---|---|
|コントロールプレーン|1台構成|
|ワーカノード|2台構成|
|ロードバランサ|1台構成|
|共有ボリューム|/datamnt/data＝/datamnt/data|
|ローカルレジストリ|~/.k3d_t_kyn/t_kyn_config.tmplate＝/var/lib/rancher/k3s/agent/etc/containerd/config.toml.tmpl|

```mermaid
graph TD;
subgraph 'loadbalancer'
loadbalancer
end
subgraph 'MasterNode'
direction TB
api\nservice --- dns
dns --- metrics
nginx1 --- python1
python1 --- mysql1
end
subgraph 'WorkerNode1'
direction TB
nginx2 --- python2
python2 --- mysql2
end
subgraph 'WorkerNode2'
direction TB
nginx3 --- python3
python3 --- mysql3
end
subgraph 'hostosdisk'
direction TB
'/datamnt/data'
'config.toml.tmpl'
end
direction TB
loadbalancer ---> 'MasterNode'
loadbalancer ---> 'WorkerNode1'
loadbalancer ---> 'WorkerNode2'
'MasterNode' <---> 'hostosdisk'
'WorkerNode1' <---> 'hostosdisk'
'WorkerNode2' <---> 'hostosdisk'
```

上記の設定で、下記コマンドでクラスタ作成します。
* クラスタ作成
    ```bash
    k3d cluster create --agents 2 --port "8080:30000@loadbalancer" --wait 0 --volume ~/.k3d_t_kyn/t_kyn_config.tmplate:/var/lib/rancher/k3s/agent/etc/containerd/config.toml.tmpl --volume /datamnt/data:/datamnt/data
    ```

* コンテナレジストリを作成し、起動・ホストOS上で名前解決できるようにします。
これを行うことで、k3dのワーカノード上にカスタムイメージを利用したPodを、ワーカノード上に作成することが可能になります。
    ```bash
    # コンテナのネットワークを確認する＋クラスタの名前を確認する
    docker network ls
    kubectl config get-contexts
    
    # クラスタをコンテナとネットワークを接続する
    docker network connect k3d-0 tkynregistry.local
    
    # コンテナレジストリへの起動確認
    curl -kv http://tkynregistry.local:5000
    
    # ホストへの登録をします。
    cat /etc/hosts | grep tkynregistry.local
    ```
---

### コンテナのイメージ登録
* コンテナのイメージを登録します。

#### NGINXのPod、Deployment、Service作成

* Nginxのデフォルトコンテナイメージをpullします
    ```
    docker pull nginx:alpine3.18
    ```
* Dockerfile及び、default.confをカスタマイズします
    * 詳細はGithubの下記参照(プライベート用リポジトリ）
        * https://github.com/t-kyn-git/alma_t_kyn003_k3d_infrastructures-
        * https://github.com/t-kyn-git/alma_t_kyn003_k3d_infrastructures-/blob/main/podmultinode/imagenginx/Dockerfile
        * https://github.com/t-kyn-git/alma_t_kyn003_k3d_infrastructures-/blob/main/podmultinode/imagenginx/conf/default.conf

* Dockerfileをもとにデプロイします
    ```bash
    # Dockerfileをもとにデプロイ
    cd /home/kubeuser/podmultinode/imagenginx;docker build -t imagenginx:v1.0.0 .;cd ~
    
    # ビルドしたイメージの登録（タグ付け）
    docker tag imagenginx:v1.0.0 tkynregistry.local:5000/nginx:v1.0.0
    
    # ローカルレジストリへpush
    docker push tkynregistry.local:5000/nginx:v1.0.0
    ```

* deploymentのnginxpodを3つ、serviceを作成します
    ```bash
    kubectl get pod
    kubectl apply -f /home/kubeuser/podmultinode/podnginx.yml
    kubectl get pod
    ```
#### PythonのPod、Deployment、Service作成
* pythonのデフォルトコンテナイメージをpullします
    ```
    docker pull python:alpine3.18
    ```
* Dockerfile及び、pythonファイルをカスタマイズします。
    ```bash
    ls -lrt /home/kubeuser/podmultinode/imagepython/Dockerfile
    vi /home/kubeuser/podmultinode/imagepython/Dockerfile
    →5000番はregistryでつかうので、5520に変更。
    →pip installするモジュールを選定し、必要なパッケージを入れてください。
    ```
* Dockerfileをもとにデプロイします。
    ```bash
    # Dockerfileをもとにデプロイ
    cd /home/kubeuser/podmultinode/imagepython;docker build -t imagepython:v1.0.0 .;cd ~
    # ビルドしたイメージの登録（タグ付け）
    docker tag imagepython:v1.0.0 tkynregistry.local:5000/imagepython:v1.0.0
    # ローカルレジストリへpush
    docker push tkynregistry.local:5000/imagepython:v1.0.0
    ```

* コンテナの動作確認をします
    ```bash
    docker images
    docker run -d --name testpythoncontaner imagepython:v1.0.0
    docker exec -it testpythoncontaner hostname -i
    curl http://CONTENANOIP:5520
    ```

* pythonPod、Deploymentを起動します。
    ```bash
    ###事前にtestapp.pyを配置
    cp -pv /home/kubeuser/podmultinode/imagepython/testapp.py /datamnt/data/pyscripts/
    kubectl get pod
    kubectl apply -f /home/kubeuser/podmultinode/podpython.yml
    kubectl get pod
    ```
* ※テスト確認
    ```bash
    kubectl describe service
    kubectl get pod,svc -o wide
    kubectl exec -it python-app-pod /bin/sh
    apk add curl
    hostname -i
    curl http://localhost:5520
    ```
参考：https://docs.docker.jp/engine/reference/commandline/build.html

#### Nginx→Pythonへの疎通確認

* それぞれ下記コマンドで疎通確認可能です
    ```
    # コンテナ内部から
    curl http://nginx:30000/t_kyn_py_test/
    # コンテナホストから
    curl http://172.23.0.3:30000/t_kyn_py_test/
    ```

#### MySQLのPod、Deployment、Service作成
* MySQLで、デフォルトコンテナイメージがないため、alpine:3.18をpullします
    ```bash
    docker pull alpine:3.18
    ```
* Dockerfile、entrypoint.sh、my.cnfをカスタマイズします。
（詳細は下記Github参考）
    * https://github.com/t-kyn-git/alma_t_kyn003_k3d_infrastructures-/blob/main/podmultinode/imagemysql/Dockerfile
    * https://github.com/t-kyn-git/alma_t_kyn003_k3d_infrastructures-/blob/main/podmultinode/imagemysql/entrypoint.sh
    * https://github.com/t-kyn-git/alma_t_kyn003_k3d_infrastructures-/blob/main/podmultinode/imagemysql/conf/my.cnf
* Dockerfileをもとにデプロイします。
    ```bash
    # Dockerfileをもとにデプロイ
    cd /home/kubeuser/podmultinode/imagemysql;docker build -t imagemysql:v1.0.0 .;cd ~
    # ビルドしたイメージの登録（タグ付け）
    docker tag imagemysql:v1.0.0 tkynregistry.local:5000/imagemysql:v1.0.0
    # ローカルレジストリへpush
    docker push tkynregistry.local:5000/imagemysql:v1.0.0
    ```
* MySQLPodをデプロイした際の工夫点
    * DeploymentでMySQLPod3つを起動
    * StatefulSetが使えないので、DeploymentでPodを3つ作成
    * :construction: データベースの冗長化について
        * 仮想マシンのcronで定期的に下記を実行するスクリプトを開発中です
            * Masterデータベースからデータベースエクスポート
            * Slaveデータベースへインポート
    * データベースの永続化
        * PersistentVolumeとPersistentVolumeClaimも作成します。
        * StorageClassはSlowにします。
* MySQLPodを起動します。
    ```bash
    kubectl get pod
    kubectl apply -f /home/kubeuser/podmultinode/podmysql.yml
    kubectl get pod
    ```

#### MySQLの性能を念のため確認
* テスト用のテーブルを作成します
* データを1万行挿入するプロシージャを作成し、繰り返し実行できる関数を作成します。

```
mysql -u root -p mysql
create table unko(id text);

DELIMITER //
CREATE PROCEDURE loop_insert()
BEGIN
DECLARE i INT DEFAULT 0;
DECLARE max_count INT DEFAULT 10000;

WHILE i < max_count DO
INSERT INTO unko VALUES ('aaaaaaaaaa');
SET i = i + 1;
END WHILE;
END //

DELIMITER //
BEGIN
DECLARE i INT DEFAULT 0;
WHILE i < 1000 DO
CALL loop_insert();
SET i = i + 1;
END WHILE;
END //

CALL loop_insert(); CALL loop_insert(); CALL loop_insert(); CALL loop_insert(); CALL loop_insert(); CALL loop_insert(); CALL loop_insert(); CALL loop_insert(); CALL loop_insert(); CALL loop_insert(); CALL loop_insert(); CALL loop_insert(); CALL loop_insert(); CALL loop_insert(); CALL loop_insert();//
```
* 結果としては、45万件の挿入は全く問題ありませんでした。

#### Loadbalancerについて
* ロードバランサはk3dクラスタ作成時に
「 --port "8080:30000@loadbalancer"」を指定して作成されるので、
8080ポートでワーカノードの30000ポートに接続できるようにしていますので
追加で行うことは特にしないです。
* SSHポートフォワーディングすれば、ブラウザからの接続が可能になります。

#### :construction: ForwardProxy用サーバから接続する
* nginxPodにhttps→http（ノードIPに接続）接続できるよう設定追加します
* 自己証明書（SSL証明書）を利用します。
    * 旧LAMPサーバから利用しているSSL証明書を利用
* 通信経路
    * 一般ユーザ（User）は、許可されたネットワーク機器からのみ接続可能
    * AdminUserはhttpsで直接接続する
    * AdminUser（PC)ではポートフォワーディング設定後、接続（非推奨）
        ```plantuml
        @startuml
        
        node "Authorized \nnetwork \nequipment" as external
        "AdminUser" as admin
        "User" as user
        "AdminUser(PC)" as adminFW
        
        node "k3d(internal)" {
            rectangle "nginx1" as nginx1
            rectangle "python1" as python1
            rectangle "nginx1" as nginx1
        }
        
        admin ===> nginx1 :https \n Connection
        user ===> external :https \n Connection
        adminFW ---> nginx1 :ssh \n port Forwarding (★Not recommended）
        external ----right----> nginx1 :https
        nginx1 ----right----> python1 :http
        
        
        @enduml
        ```

---

#### カスタムイメージの更新
* k3dではイメージがプッシュできないことがあります
    * 削除APIでregistry上のイメージ削除が不可能。
    * コンテナRegistry上のイメージファイルを削除・再pushしてもワーカノード経反映されない（k3dのバグかと思います）
    * k3dクラスタを削除→再作成すると、正しいコンテナイメージでデプロイが可能です。
    https://gist.github.com/takenoco82/b9559a1abd57eb0845a77041860cd26e
    https://qiita.com/tororoMeshi/items/98eac9b202adaa266d61
* 下記の方法でクラスタ再作成をします。
    ```
    kubectl delete -f /home/kubeuser/podmultinode/podnginx.yml
    kubectl delete -f /home/kubeuser/podmultinode/podpython.yml
    kubectl delete -f /home/kubeuser/podmultinode/podmysql.yml
    k3d stop cluster 0
    k3d cluster delete
    k3d create(同じコマンド)
    カスタムイメージのtag付け及びpush
    kubectl apply -f /home/kubeuser/podmultinode/podmysql.yml
    kubectl apply -f /home/kubeuser/podmultinode/podpython.yml
    kubectl apply -f /home/kubeuser/podmultinode/podnginx.yml
    ```
* system pruneはイメージファイル含めて削除する可能性が高いため非推奨です。
    `docker system prune -f`

---

#### k3dクラスタの再起動
* クラスタ再作成せず、継続利用する場合、下記コマンドでクラスタ再起動が可能です。
    ```
    # k3dクラスタの停止
    k3d cluster stop 0
    # k3dクラスタの起動
    k3d cluster start 0
    ```

---

#### PythonからMySQLへの接続確認
* 事前に、pip install mysql.connector
を行った後、下記コマンドでデータベース検索を行います。
* つながらない場合はリスナーが起動していないと思われますので、下記対応
    * MySQLの設定ファイルより、bind-addressの設定を0.0.0.0にする
    * Python側で設定しているMySQL接続パスワードが正しいか確認する
        ```python
        import mysql.connector
        
        # MySQLサーバーの接続情報を設定
        config = {
          'user': '★秘密★',
          'password': '★秘密★',
          'host': '★秘密★',
          'database': '★秘密★',
          'port': ★秘密★  # ポート番号を指定
        }
        
        # MySQLサーバーに接続
        try:
            conn = mysql.connector.connect(**config)
        
            if conn.is_connected():
                print('MySQLに接続しました')
        
                # クエリを実行するためのカーソルを作成
                cursor = conn.cursor()
        
                # クエリを実行
                cursor.execute('SELECT count(*) FROM user_tables;')
        
                # 結果を取得
                rows = cursor.fetchall()
                print('取得した行数:', len(rows))
                for row in rows:
                    print(row)
        
        except mysql.connector.Error as err:
            print('MySQLに接続でエラーが発生しました:', err)
        
        finally:
            # 接続をクローズ
            if 'conn' in locals() and conn.is_connected():
                cursor.close()
                conn.close()
                print('MySQL接続をクローズしました')
        ```


---
### トラブルシューティング

#### k3dクラスタもコンテナ全削除を削除するとき
* k3d cluster delete 0
* docker network disconnect k3d-0 t_kyn_registry_host
* docker network rm k3d-0
* それでも消えなかったら「docker system prune -f」する

---

#### k3dの様々なバグ
様々な不具合が出たので、検討のうえ対策を施しました。
一部は恒久的に難しい課題があるため、暫定対応で対処しています（:exclamation:で記載）

##### :white_check_mark:１．k3dのコンテナイメージが正しく登録できない。削除もできない（課題）
* imageがRegistryに最新imageが登録されているのにもかかわらず、ワーカノード上で参照するイメージが最新化できない。
* <b>暫定としては、k3dクラスタ再作成で今後も運用していきます</b>
* それでも解決しない場合、「docker system prune -f」で削除してから再登録

##### :white_check_mark:２．MySQLコンテナ起動時、CPUが高騰する
* <b>イメージファイルでのentrypoint.shでncコマンドでwhileループをかけている。その処理は不要にして削除しています。</b>
* ENTRYPOINT ["/entrypoint.sh"]
CMD ["mysqld", "--user=mysql", "--datadir=/var/lib/mysql"]
から、
command: ["sh", "/entrypoint.sh"]    とするように修正することで解決しています

##### :x:３．CPU Limits設定できない。
* k3dのバグだと思われる。<b>解決はできてないです。</b>
* 負荷をかけないようにする以外に解決策がないため、pod、node、仮想マシンのCPU使用率を1分間隔で取得し、結果を解析するようにしたいと思います（実装中です）
  
##### :x:４．k3dで使用できるカスタムイメージの削除APIが使えない。
* 下記はサポートされてなかったので使えない。解決不可。
* <b>暫定としては、「docker system prune -f」で削除</b>
    ```bash
      curl -X GET -H "Accept: application/vnd.docker.distribution.manifest.v2+json" -s -D - http://tkynregistry.local:5000/v2/imagemysql/manifests/v1.0.0| grep Docker-Content-Digest:
      curl -X DELETE -D - http://localhost:5000/v2/imagemysql/manifests/sha256:3d1243e60f980f5510c3642c60b596aa9750b846c15ee2ca957614fc9b32d00c
    ```

##### :white_check_mark:５．MySQLはデフォルトで外部接続設定は許可されてない。ポートもListenしない。
* 少なくともMariaDBは許可されてない。
* https://helpcenter.gmocloud.com/altus/s/article/ch-4024
* https://tutorialcrawler.com/database/mysql%E3%81%B8%E3%81%AE%E3%83%AA%E3%83%A2%E3%83%BC%E3%83%88%E6%8E%A5%E7%B6%9A%E3%82%92%E8%A8%B1%E5%8F%AF%E3%81%99%E3%82%8B%E6%96%B9%E6%B3%95/
* <b>my.cnfのskip-networkの設定を無効にした。</b>

##### :white_check_mark:６．MySQLのデータベースで、AccessDenyで接続できない
* Service名とPort指定で接続できた
* MySQLのデータベースのPrivilageの設定を実施

##### :question: ７．MySQLのPod起動時、ymlに指定するPersistenVolumeが適切なPodへマウントできない（例）MySQL1⇒PV3にマウントされる）
* Podの起動順序があっていない
* 対処方法としては、下記2案で検討中ですが<b>案1を採用</b>し、スクリプト開発済みです。
    * :white_check_mark:案1：◎マウント状態確認(kubectl describe pv,pvc)し、紐づいていなければpodのデプロイをやり直しするスクリプトを開発
    * :x:案2：△1⇒2⇒3の順に起動できるようにマニフェストファイルに待機時間を入れる
---

### Pythonでの実装検討（次回予告）
* 「Pythonの実装方針」に記載はしている点と重複しますが、次章で下記内容を記載します
* どの画面からどの画面（URL）に遷移するのかの図も整理していこうと思います
    * <b>FlaskAPI</b></font>
        * :white_check_mark:データ表示、データモデルの定義
        * :white_check_mark:クライアントからのリクエストを適切なテーブルへ割り振り
        * :construction:アプリケーションの認証機能
    * <b>SQLAlchemy</b></font>
        * :white_check_mark:SQL実行、データマッピング
    * <font color="red"><b>Pandas</b></font>
        * :white_check_mark:データフレーム・レイアウトの定義
    * <font color="red"><b>Plotly</b></font>
        * :white_check_mark:グラフ作成

---

### 参考
* k3dでPrivateRepositoryを使う
   https://qiita.com/yuta_vamdemic/items/5ee72f8182310272360c
   
* k3dとLocal Registry
   https://qiita.com/oruharo/items/6aea30ae69c0fb8009ed

* 【Docker】MySQLで複数database環境を構築する
   https://qiita.com/piggydev/items/2096258dc45a6bbe2a19

* 【LearnTechnoBios /rest-api-mysql-k3d 
　　https://github.com/LearnTechnoBios/rest-api-mysql-k3d/blob/main/Dockerfile