年の瀬は、ローカル開発環境を見直そう

こちらは、[TUNA-JPアドベントカレンダー 2023](https://qiita.com/advent-calendar/2023/tuna-jp) の25日目の記事です。

ついにアドベントカレンダーも最終日ですね！

最初に謝らなければいけないことがございます・・・m(_ _)m

当初は、[Private AI](https://qiita.com/hirosat/items/f309c9f9da2d75544e59)の後編をやろうと思ってましたが、個人的事情により、別のネタを紹介させていただきます！


# 今どきの開発環境の要件

ずばり、**コンテナ開発**ができて、**ローカルでK8s検証**できる、ことが重要になってくるはずなので、以下の2点を考えていきます。

1. どの**コンテナ環境ツール**を用意するか？
2. どの**ローカルK8s環境**を用意するか？




# 1. コンテナ環境ツール

もの凄く大事な前提として、一般的なコンテナは、**Linux環境**で動きます。(※. Windowsコンテナは違いますが、普通は使わないので、気にしなくて良いです。)

で、WindowsやMacでコンテナを動かすには、**Linux VM**の用意が必要です。実はそういったLinux VMなどの用意を裏でしてくれるのが、**Docker Desktop**など製品です。

つまり、ここ言っている**コンテナ環境ツール**とは、**WindowsやMacのPC**を対象にして、**コンテナの動作・管理**を行うためのツールを紹介します。

## ポイント1. 有料製品を使えるかどうか？

まず、最も有名なのが、[Docker Desktop](https://www.docker.com/ja-jp/products/docker-desktop/)という製品です。

長らく、無料で使えるクライアント向けコンテナ環境ツールの**デファクトスタンダード**でした。
しかし、ご存知の方も多いとは思いますが、2021年8月31日、Docker社は、**企業ユーザ**に対して、**Docker Desktopの有料化**を発表しました。
> [Pricingページ](https://www.docker.com/pricing/)より<br>
> Docker Desktop is free to use as part of the Docker Personal subscription for individuals, non-commercial open source developers, students and educators, and small businesses of fewer than than 250 employees AND less than $10 million in revenue. Commercial use of Docker Desktop at a company of more than 250 employees OR more than $10 million in annual revenue requires a paid subscription (Pro, Team, or Business).<br>
> (日本語訳)<br>
> Docker Desktopは、Docker Personalサブスクリプションの一部として、個人、非商用のオープンソース開発者、学生、教育者、従業員250人未満かつ年間売上1000万ドル未満の中小企業向けに無料でご利用いただけます。**従業員250人以上、または年間売上1000万ドル以上の企業**でDocker Desktopを商用利用するには、**有償のサブスクリプション**（Pro、Team、Business）が必要です。

これには、業界内に衝撃が走りました。企業によっては、各クライアントに有償製品を導入すること自体が難しい場合が多いため、**Docker Desktop代替**を探す動きが活発化しました。

その動きの中で、いくつかのDocker Desktop代替製品が登場しましたが、今年になって、[OrbStack](https://orbstack.dev/)が、独自の機能を多数用意したことで、**特に話題**となりました。

しかしこちらも、2023年9月21日、**OrbStack 1.0**のリリースを皮切りに、同じく**有料プラン**が登場しました。

[ライセンス](https://docs.orbstack.dev/licensing)ページに以下のようなことが書いてあります。
> From the [Terms of Service](https://docs.orbstack.dev/legal/terms):
> 
> If you are using OrbStack professionally as a freelancer, for a commercial or non-profit entity, or for a government entity, or if you generate more than Ten Thousand Dollars ($10,000.00 USD) per year in connection with all work related to your use of OrbStack, you must purchase a License for OrbStack under the [Master Software License Agreement](https://docs.orbstack.dev/legal/msa) by choosing your subscription plan here and executing an Order.
> 
> (日本語訳)
> OrbStackをフリーランサー、営利団体、非営利団体、政府機関のためにプロフェッショナルとして使用する場合、または**OrbStackの使用に関連するすべての業務**に関連して**年間1万ドル**（10,000.00米ドル）以上の収益を上げる場合は、ここでサブスクリプションプランを選択し、注文を実行することにより、マスターソフトウェアライセンス契約に基づいてOrbStackの**ライセンスを購入する必要があります**。

つまり、条件面にだけ見ると、OrbStackの方がより厳しい位です。

よって、あなたが最初にすることは、あなたの会社の**企業概要ページ**をみて、**従業員数**と**収益**を調べましょう。条件に引っかかっている場合、目安として、**会社の資産として配布されたPC**を使っていれば、有料版の対象となると思っていた方が良いでしょう。（※. 私から厳密には指摘できないので、自社の法務と相談して下さい・・）

## ポイント2. dockerを使いたいかとうか？

実は、docker以外にもコンテナを利用可能であり、代表的なものが、**containerd**です。正確に言うと、dockerもcontainerdを使用していますが、**containerd単体でも利用できます**。

containerdだけを利用することで、**少ないリソース量**でコンテナを動かせるので、**低スペックなマシンでも動作させやすい**という利点があります。実際、K3sやK0sといった軽量K8sディストリビューションでは、containerdが採用されています。

dockerを入れることで主に変わるものは、**docker CLI**が使えるかどうかどうかです。

私の場合、マシンスペックがそこそこあり、慣れ親しんだdocker CLIが捨てがたいので、dockerを利用できる製品から選んでます。

## ポイント3. 無料ツールを利用する場合

以下のツールあたりが比較対象となってくるはずです（他にもあるかも）。

- [Rancher Desktop](https://docs.rancherdesktop.io/)
- [Podman Desktop](https://podman-desktop.io/)
- [Container Desktop](https://container-desktop.io/v1.1.13/)
- [Colima](https://github.com/abiosoft/colima)

どれも細かいところは異なりますが、私はこの中だと**Rancher Desktop**を選びました。

dockerが使えてDocker Desktopに使用感が近く、頻繁にアップデートが行われているため、開発に力を入れている感じがします。


## ３大コンテナツールの徹底比較

という訳で、dockerが使える以下の3ツールの比較表を作りましたので、紹介します。

製品名 | Docker Desktop | Rancher Desktop | OrbStack |
---------|----------|--------- |---------
料金 | (制限に引っかかる場合) Pro plan(**月$5/user**)以上が必要 | 無料 (Apache-2.0 licenseのOSS) | (制限に引っかかる場合) Pro plan(**月$8/user**)以上が必要
対応OS | Win/Mac/Linux | Win/Mac/Linux | Mac
必要スペック |[Windows](https://docs.docker.jp/docker-for-windows/install.html#win-system-requirements)<br>- Windows 10 64 bit build 15063 以降 / Pro以上<br>- Hyper-V と Windows コンテナ機能を有効<br>- 64 bit SLAT対応CPU<br>- 4GBメモリ<br>- BIOSでハードウェア仮想化を有効<br><br>[Mac](https://docs.docker.jp/desktop/install/mac-install.html#mac-system-requirements)<br>- MacOS 10.15以降<br>- 4GBメモリ| 共通<br>- 4CPU推奨<br>- 8GBメモリ推奨<br><br>[Windows](https://docs.rancherdesktop.io/getting-started/installation/#requirements-1)<br>- Windows 10 build 1909以降 / Home以上<br>- [仮想化要件](https://learn.microsoft.com/en-us/windows/wsl/troubleshooting#error-0x80370102-the-virtual-machine-could-not-be-started-because-a-required-feature-is-not-installed)を満たす事<br><br>[Mac](https://docs.rancherdesktop.io/getting-started/installation/#requirements)<br>- MacOS 10.15以降 | 不明(低リソースが売りなので低いはず)
Linux VM | [Windows](https://docs.docker.jp/desktop/install/windows-install.html#id2)<br>- Hyper-V または WSL2<br>Mac<br>- [HyperKit](https://github.com/moby/hyperkit)| Windows<br>- WSL2<br>Mac<br>- [Lima](https://github.com/lima-vm/lima) | Mac<br>- [独自の軽量Linux VM](https://docs.orbstack.dev/architecture) ([15のdistroを利用可](https://docs.orbstack.dev/machines/distros))
ネットワーク | 仮想ネットワークが構成される | 仮想ネットワークが構成される | [ローカルと透過的なアクセスが可能な仮想ネットワーク](https://docs.orbstack.dev/architecture#network)
コンテナエンジン  | dockerd | containerd または dockerd | dockerd
K8s連携 | kind | k3s | [独自の軽量シングルノードk8s](https://docs.orbstack.dev/kubernetes/)
リソース効率 | 不明 | 不明 | [低リソース](https://docs.orbstack.dev/efficiency)、[高パフォーマンス](https://docs.orbstack.dev/benchmarks)
VSCode連携 | あり | あり | なし（多分）
エクステンション | あり | あり | なし

まとめると、以下のような選定基準となってくるかなと思っています。
- OrbStackが非常に優れているので、**お金を払ってでも利用したい**。ただし、**Macにしか対応していない**。
- **Windows**の人で、**お金が払える**なら、Docker Desktopが実績があって良い。
- それ以外の人は、**Rancher Desktop**を使えばよい。Docker Desktopと比べても、そんなには遜色ない。



# 2. ローカルK8s環境

こちらにも重要な大前提があります。ローカルK8s環境の正体は、**K8sノードの機能を有したコンテナ**だということです。

これが何を意味するかと言うと、ローカルK8s環境を使うためには、先程の**コンテナ環境ツールを起動**し続けておく必要があります。そして、実際に**PCリソースを圧迫**するのは、コンテナ環境ツールの設定で**予め確保しているVMリソース量**に依存してきます。
<img src="https://suse-rancher-media.s3.amazonaws.com/desktop/v1.11/preferences/macOS_virtualMachine_tabHardware.png" width="50%">

ただし、**K3s**や**K0s**といった**軽量K8sディストロ**を使う場合は、この限りではありません。これらは**自前のcontainerd**を持っているので、Docker環境のインストールを前提としません。

私の場合は、先程もいいましたが、スペックではなく**機能性**で選んだ結果、**kind**を使用しています。

## kindについて
kindは、Dockerデスクトップにも同梱されており、GUIからボタン1つで簡単に利用できるようになります。でも実はこれは **罠なので、使用しないで下さい**ｗ

オススメの方法として、**kindコンフィグ**を使ったクラスタの構築方法を紹介します。kindの本来の良さは、クラスタ設定をカスタマイズできることなのですが、Docker Desktopで有効にする手段だと、**カスタマイズ**することができません。

よって、**kind CLIを別途インストール**しましょう。基本的には、ダウンロードして実行権を与えてパスの通ったディレクトリに設置するだけです。以下はMacの例ですが、[他のOSもほぼ同じ手順](https://kind.sigs.k8s.io/docs/user/quick-start/#installing-from-release-binaries)でいけます。

```
# ダウンロード
curl -Lo ./kind https://kind.sigs.k8s.io/dl/v0.19.0/kind-darwin-arm64

# 実行権を付与
chmod +x ./kind

# PATHの通った場所に移動
mv ./kind /usr/local/bin/kind
```

## 基本形
以下の様なマニフェストを用意して・・・、

```
cat <<EOF > kind-config.yaml
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
- role: control-plane
EOF
```

クラスタを作成するだけです。

```
kind create cluster --config kind-config.yaml
```

(**kindクラスタ**が既にある場合)
削除して、作成するだけです。

```
kind delete cluster
kind create cluster --config kind-config.yaml
```


## マルチノード構成にするには？

答え：**-role: xxx**を追加するだけです。

```
cat <<EOF > kind-config.yaml
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
- role: control-plane
- role: worker
EOF
```

VM側のリソースを多めに取っておけば、本番構成(CP3台、worker3台)も可能です。

```
cat <<EOF > kind-config.yaml
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
- role: control-plane
- role: control-plane
- role: control-plane
- role: worker
- role: worker
- role: worker
EOF
```

## Win/Macで、Service type: LoadBalancerを使用するには？

答え： **OrbStack**なら可能であり、**Docker/Rancher Desktop**では利用できません。(kindコンフィグに依存しません。。)

正確には、MetalLB等を用いてLBサービスの作成は可能ですが、LBの**External IPがDockerネットワーク上**のものとなるので、**そこにアクセスする手段がない**のです。OrbStackならば、**ローカルネットワークのIPが使われるLB**がビルトインで用意されます。また、Linuxがクライアントの場合、変なネットワークを挟まないため、問題なくLBサービスを利用できます。

さらに別解として、[K3d](https://k3d.io/v5.6.0/usage/exposing_services/)を使うという方法もあります。

## Win/Macで、Service type: NodePortを使用するには？

答え： 基本的には、↑のLBの状況と同じですが、kindには**extraPortMappings:** を使用することで、**ローカルネットワークへのPortフォワード**が可能です。

```
cat << EOF > kind-config.yaml
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
- role: control-plane
- role: worker
  extraPortMappings:
  - containerPort: 30080
    hostPort: 30080
EOF
```

- **containerPort** : **NodePort側**に使用する**30000-32767レンジ内のport**
- **hostPort** : **ローカルPC**が使用する**任意のport**。 ※. ローカル側で使用中のportを指定しないよう注意

その後、**NodePort**を上記の**containerPort**としたServiceを作成することで、ローカルPC側で**hostPort**からアクセス可能です。

```
cat << EOF > service-my-app2.yaml
apiVersion: v1
kind: Service
(中略)
spec:
  type: NodePort
  ports:
  - port: 80
    nodePort: 30080
(省略)
EOF
```

あ、もちろん、OrbStackまたはLinuxクライアントであれば、こんなことしなくてもOKです。

## Win/Macで、Ingressを使用するには？

答え： ↑の話を理解していれば、Ingressもいけます。

1. kindコンフィグを用意して適用。

```
cat << EOF > kind-config.yaml
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
- role: control-plane
- role: worker
  extraPortMappings:
  - containerPort: 30080
    hostPort: 30080
  - containerPort: 30443
    hostPort: 30443
EOF

kind delete cluster
kind create cluster --config kind-config.yaml
```

2. Ingressを適用。今回はContourを使用します。

```
kubectl apply -f https://projectcontour.io/quickstart/contour.yaml
```

3. 1のportを使用するよう、patchを適用
```
kubectl patch -n projectcontour service envoy --type='json' -p \
'[{"op":"replace","path":"/spec/type","value":"NodePort"}, 
{"op":"replace","path":"/spec/ports/0/nodePort","value":30080},
{"op":"replace","path":"/spec/ports/1/nodePort","value":30443}]'
```

これで、HTTPの場合は`localhost:30080`、HTTPSの場合は`localhost:30443`にアクセスすれば、Ingressを利用できます。

LBサービスが使えなくても、ローカル環境で使うにはこれで充分なはずです。

## 別のCNIを使うには？

答え： `disableDefaultCNI: true`とすればOKです。kindはデフォルトで[kindnet](https://github.com/aojea/kindnet)というCNIがビルトインされているので、CNIを抜くことで、他のCNIのを入れられます。


```
cat << EOF > kind-config.yaml
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
networking:
  disableDefaultCNI: true
nodes:
- role: control-plane
- role: worker
EOF

kind delete cluster
kind create cluster --config kind-config.yaml
```

私の場合、その後[Cilium](https://docs.cilium.io/en/stable/gettingstarted/k8s-install-default/)を試しましたが、特に問題なく動作しました。

このように、kindコンフィグを用意したデプロイ手法であれば、色々なケースに対応できるのでオススメです。

# まとめ
調べた結果、選択肢が多すぎて、色々と抜け漏れがありそうで、まとめきれていなさそうな気もしますが・・・、割と頑張ったほうだと思いますｗ

TL;DR としては、スペックのあるマシンで有料ライセンスを使える方は、**OrbStack**と**kind**の組み合わせをオススメします。