Kubernetesディストリビューション — 自分で立てる
既定値が、できることを分ける
一言でいうと
軽量ディストリビューションの違いは機能ではなくデフォルト値にあり、そのデフォルト値が運用でできることを決めます。
なぜデフォルト値を知って選ぶ必要があるのか
k3sとk0sは、どちらも単一バイナリで配布される軽量Kubernetesです。見た目は似ていますが、デフォルト値が異なり、そのデフォルト値が運用でできることを決めます。
データストア
k3sのデフォルトのデータストアはsqliteです。kineという層がetcdのAPIを模倣し、その裏にsqliteを置いています。軽量で1台構成には十分ですが、etcdctlもメンバー管理も使えません。
k0sを--enable-workerで構築すると、本物のetcdになります。スナップショット、メンバー管理、復旧を実際に扱えます。CKAのetcdの問題や、実務のコントロールプレーン運用がここに当たります。
注意が必要なのはk0sの--singleモードです。手軽に見えますが、こちらはkine(sqlite)なので、k0s etcd member-listは次のように拒否されます。
Error: wrong storage type: kine
デフォルトのコンポーネント
k3sでは、traefikのIngressとlocal-pathプロビジョナーがデフォルトで入っています。開発環境では便利です。k0sは何も入れず、必要なものを自分で選ばせます。運用ではこちらのほうがよいです。デフォルトで入ってきたものを後から取り除くほうが手間がかかるからです。
CIDR範囲
k0sのデフォルトのCIDR範囲(Podは10.244.0.0/16、Serviceは10.96.0.0/12)は、標準のKubernetesと同じです。そのため、別のクラスターの中にネストして構築すると重なります。k3sの10.42と10.43は標準外の値なので、たまたま衝突を避けています。
どちらが正しいというより、自分の環境のCIDR範囲を把握して選ぶことが正解です。そして、たまたま避けられている状態に頼ると、ディストリビューションを変えた瞬間にまた落とし穴が現れます。
何を基準に選ぶのか
ディストリビューションの選択は好みではなく、どこに何を載せるのかで決まります。
| 状況 | 合うもの | 理由 |
|---|---|---|
| エッジ・IoT・シングルノード | k3s | バイナリが1つで、メモリは512MB台 |
| 開発用のローカル | kind, minikube | 作って捨てるのが速い |
| 標準をそのまま学びたい | kubeadm | 認定試験とドキュメントがこれを前提にしている |
| 複数のクラスターを自動で | k0s, Cluster API | 宣言的に量産できる |
| 管理の負担を減らしたい | マネージド(EKS・GKE) | コントロールプレーンを見なくてよい |
試験対策ならkubeadmです。k3sはetcdの代わりにSQLiteを使い、コントロールプレーンが1つのプロセスなので、試験で問われる「etcdのバックアップ」「静的Podの修正」「証明書の更新」がそのままでは通用しません。楽であることと、学べることは別です。
デフォルト値が生む違い
同じKubernetesでも、デフォルトで入っているものが異なり、それが実習と運用を分けます。
| kubeadm | k3s | k0s | |
|---|---|---|---|
| データ保存 | etcd | SQLite(デフォルト), etcdも可 | etcd(デフォルト), kineも可 |
| CNI | なし。自分でインストール | Flannel | Kube-router |
| Ingress | なし | Traefik | なし |
| LoadBalancer | なし | ServiceLB(klipper) | なし |
| StorageClass | なし | local-path | なし |
kubeadmで初めて構築すると、ノードがNotReadyのまま止まっています。故障ではなく、CNIがないからです。これを知らないと、最初のインストールで1時間を使います。
逆にk3sはすべて入っていて便利ですが、そのデフォルト値を外す方法を知っておく必要があります。
# Traefik 과 ServiceLB 를 빼고 직접 고른 것을 쓴다
curl -sfL https://get.k3s.io | INSTALL_K3S_EXEC="--disable=traefik --disable=servicelb" sh -
移行するとき何が引っかかるのか
ディストリビューションを変える機会は、思ったより頻繁にあります。引っかかるのは、たいてい次の3つです。
- StorageClassの名前:
local-pathとstandardのように名前が違うと、PVCがPendingのまま止まります。マニフェストに名前を書き込まず、デフォルトのクラスを使うか、値として注入します。 - LoadBalancerの実装: k3sのServiceLBはノードのIPをそのまま使います。MetalLBがある環境へ移すと、IPアドレス範囲の設定が必要になります。
- Ingressコントローラーの違い: TraefikとNGINXではアノテーションが異なります。Gateway APIを使えば、この移行コストが大きく減ります。
実務で本当に大切なこと
etcdを扱う必要があるなら、まずデータストアを確認します。kine(sqlite)の上では、etcdctlもメンバー管理もスナップショットからの復旧も使えません。k0sでも--singleモードはkineなので、コマンドがwrong storage type: kineで拒否されます。
ネストして構築するときは、CIDR範囲が重ならないか先に数えます。k0sのデフォルトのCIDR範囲は標準のKubernetesと同じなので、別のクラスターの中に構築すると衝突します。k3sでうまくいっていた理由は設計ではなく、標準外のCIDR範囲がたまたま避けられていただけなので、ディストリビューションを変えた瞬間にまた落とし穴が現れます。
デフォルトで入ってきたコンポーネントは、後から取り除くほうが手間がかかります。開発環境ではtraefikとlocal-pathが入っているほうが楽ですが、運用では必要なものだけを自分で選ぶほうがよいです。
次のラボでは、k0sを構築してバックアップと復旧を一巡させます。