ローカル環境でkubernetesのスケーリングまでサックリ試す【minikube】

# はじめに
「kubernetesってローカルで検証できなくないっすか？」と先生に聞いたら
こんなんあるでとminikubeを教えていただいたので使って見たいと思います。
k8sといったらスケーリングだと勝手に思っているのでローカル環境でスケーリングを確認できるまでを書きます。
細かい用語を書いていくと長大になりそうなので、ハンズオン的にコピペで試せるようにします。

https://minikube.sigs.k8s.io/docs/

マニフェストファイルを用意してapplyしていく形で進行します。

# 対象
1. k8sを業務で使っているけど、よくわかっていないのでコマンド叩くのが恐い人
1. Dockerの基本的なことは理解している（Dockerfileを記述できるくらい）


# 環境
macOS Sonoma
**Dockerが入っていること**
スペックの要件があるので注意です。

:::note info
2CPU以上
2GBの空きメモリ
20GBの空きディスク容量
インターネット接続
コンテナーまたは仮想マシン マネージャー (例: Docker、QEMU、Hyperkit、Hyper-V、KVM、Parallels、Podman、VirtualBox、またはVMware Fusion/Workstation)
:::

# インストール
minikube自体はbrewで入れるのが楽です。
```minikube start``` はクラスタを作成するコマンドですが、ドライバーが入っていない場合このタイミングで入れてくれます。

```zsh
$ brew install minikube
$ minikube start
```

wslで試しているときはこのタイミングでkuberctlのインストールが必要でしたので、環境によってはインストール。

https://kubernetes.io/docs/tasks/tools/

# podの作成
kubernetes-bootcampというコンテナを使います。

https://kubernetesbootcamp.github.io/kubernetes-bootcamp/index.html

Deploymentするためのyamlを用意します。

```zsh
echo 'apiVersion: apps/v1
kind: Deployment
metadata:
  name: kubernetes-bootcamp
spec:
  replicas: 1
  selector:
    matchLabels:
      app: kubernetes-bootcamp
  template:
    metadata:
      labels:
        app: kubernetes-bootcamp
    spec:
      containers:
      - name: kubernetes-bootcamp
        image: gcr.io/google-samples/kubernetes-bootcamp:v1
        ports:
        - containerPort: 8080' > deployment.yaml
```

yamlからpodを作ります。
起動に時間がかかるのでしばらく待ちます。

```zsh
$ kubectl apply -f deployment.yaml
$ kubectl get pods
NAME                                  READY   STATUS              RESTARTS   AGE
kubernetes-bootcamp-978dd9cbc-k9n9h   1/1     ContainerCreating   0          17s
```
# Serviceの作成
podだけあっても外部からアクセスすることができません。
Serviceを作ってエンドポイントを外部に公開してあげます。

```zsh
echo 'apiVersion: v1
kind: Service
metadata:
  name: kubernetes-bootcamp
spec:
  type: NodePort
  ports:
  - port: 8080
    targetPort: 8080
    nodePort: 9000  # 任意のPort
  selector:
    app: kubernetes-bootcamp' > service.yaml
```

```zsh
$ kubectl get services
NAME                  TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)          AGE
kubernetes            ClusterIP   10.96.0.1       <none>        443/TCP          33m
kubernetes-bootcamp   NodePort    10.110.164.47   <none>        8080:9000/TCP   15m
```

Serviceが作成できました。
実行して指示されているURLにリクエストを投げてあげましょう。

```zsh
$ minikube service kubernetes-bootcamp
|-----------|---------------------|-------------|---------------------------|
| NAMESPACE |        NAME         | TARGET PORT |            URL            |
|-----------|---------------------|-------------|---------------------------|
| default   | kubernetes-bootcamp |        8080 | http://192.168.64.3:9000 |
|-----------|---------------------|-------------|---------------------------|
🎉  デフォルトブラウザーで default/kubernetes-bootcamp サービスを開いています...
```

```zsh
$ curl http://192.168.64.3:9000/
Hello Kubernetes bootcamp! | Running on: kubernetes-bootcamp-978dd9cbc-k9n9h | v=1
```

# スケーリングする
先ほど作成したdeployment.yamlのreplicasを２以上の任意の値にします。
**増やしすぎると多大な負荷がかかると思うのでほどほどに**

```yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: kubernetes-bootcamp
spec:
  replicas: 3 # ここを任意の値にする
  selector:
    matchLabels:
      app: kubernetes-bootcamp
  template:
    metadata:
      labels:
        app: kubernetes-bootcamp
    spec:
      containers:
      - name: kubernetes-bootcamp
        image: gcr.io/google-samples/kubernetes-bootcamp:v1
        ports:
        - containerPort: 8080
```

もう一度applyしてpodが増えていることを確認します。

```zsh
$ kubectl apply -f deployment.yaml
deployment.apps/kubernetes-bootcamp configured
$ kubectl get pods
NAME                                  READY   STATUS    RESTARTS   AGE
kubernetes-bootcamp-978dd9cbc-64wzc   1/1     Running   0          2s
kubernetes-bootcamp-978dd9cbc-hznfd   1/1     Running   0          2s
kubernetes-bootcamp-978dd9cbc-rtdjs   1/1     Running   0          26s
```

増えていることを確認できたらリクエストを投げてみましょう。

```zsh
$ curl http://192.168.64.3:9000/
Hello Kubernetes bootcamp! | Running on: kubernetes-bootcamp-978dd9cbc-hznfd | v=1
$ curl http://192.168.64.3:9000/
Hello Kubernetes bootcamp! | Running on: kubernetes-bootcamp-978dd9cbc-64wzc | v=1
$ curl http://192.168.64.3:9000/
Hello Kubernetes bootcamp! | Running on: kubernetes-bootcamp-978dd9cbc-rtdjs | v=1
```

都度使用されるpodが変わっていることが確認できましたね。
スケーリングができています。

終わったらクラスタを削除しておきましょう。
```zsh
minikube delete --all
```

# その他
## podが立ち上がらない
podがrunning状態になるまで時間がかかります。
しかし、あまりにも起動しなかったらyamlが間違えている可能性があるので実行時のログを確認します。

```zsh
$ kubectl describe pod {get podsで表示されているpod名}
```
こちらで表示されるEventsタグが実行時のログです。
最初nginxのコンテナで試していたのですが、古いバージョンを使っていたせいで起動しませんでした。
その際ここにDocker Hubからpullできなかった旨のエラーが吐かれていました。

## port-forwardだと一つのpodしか使われない
外部にエンドポイントを公開するとき以下のようにport-forwardオプションで公開することもできます。

```zsh
$ kubectl port-forward service/kubernetes-bootcamp 9000:8080
```

しかしこの方法だと一つのpodしか使われませんでした。
こちらで公開するとpodが固定化されるようです。

https://mome-n.com/posts/minikube-service-fixed-port/#kubectlのport-forwardコマンドを使用する

```get pods```コマンドに```-o wide```オプションをつけると割り当てられてるIPが見れるのですが、このIPに固定されているのだと思います。（本当にただポートフォワードしているだけのイメージ）

```zsh
$ kubectl get pods -o wide
NAME                                  READY   STATUS    RESTARTS   AGE     IP           NODE       NOMINATED NODE   READINESS GATES
kubernetes-bootcamp-978dd9cbc-6cbxd   1/1     Running   0          2m21s   10.244.0.5   minikube   <none>           <none>
kubernetes-bootcamp-978dd9cbc-7vp7w   1/1     Running   0          2m21s   10.244.0.4   minikube   <none>           <none>
kubernetes-bootcamp-978dd9cbc-x6chk   1/1     Running   0          2m21s   10.244.0.3   minikube   <none>           <none>
```

## 参考
https://zenn.dev/cozy07/articles/b7ba77bb766783

https://zenn.dev/sakana1115/scraps/34917d4a56f6e9