Kubernetes 環境を手軽に構築できる microk8s。
今回は、その microk8s を IPv4 / IPv6 デュアルスタック で構築しようとして、設計ミスにより完全に詰んだ事例をまとめます。
やりたかったこと
やりたかったこと自体はシンプルでした。
- microk8s を使った Kubernetes クラスタ構築
- IPv4 / IPv6 のデュアルスタック対応
- MetalLB による IPv6 アドレスの払い出し
- 外部から IPv6 で Service に接続できる構成
IPv6 前提のネットワーク環境も増えてきており、
将来を見据えてデュアルスタック構成で構築することにしました。
構築時の手順
以下のような一般的な流れで構築を進めました。
- microk8s のインストール
- クラスタ初期化
- node join
- MetalLB の有効化
- IPv6 アドレスレンジの設定
作業中、特にエラーは発生せず、
一見すると問題なく構築できているように見えました。
しかし、デュアルスタックになっていない
構築後に状態を確認すると、以下のような状況でした。
- Pod は IPv4 アドレスのみを持つ
- Service も IPv4 のみ
- IPv6 での外部接続は不可
一方で、
- MetalLB では IPv6 アドレスが割り当てられている
- Kubernetes 上ではエラーが出ていない
という、非常に分かりづらい状態となっていました。
決定的な違和感
特に違和感を覚えたのは以下の点です。
- Service に IPv6 アドレスが割り当てられている
- しかし外部から接続できない
- ノード上で
ip aを確認しても
その IPv6 アドレスが存在しない
つまり、
- Kubernetes のリソース上では IPv6 が存在する
- しかし OS レベルでは IPv6 が存在しない
という矛盾した状態でした。
原因:microk8s は後から DualStack にできない
原因は明確でした。
microk8s では、デュアルスタック対応は初期構築時に設定しておく必要があるようです。
今回の構築では、
- microk8s 初期化前の config 設定
- IPv6 有効化に関する設定
- CNI を DualStack 前提で初期化する設定
これらが初期段階で行われていませんでした。
microk8s は、クラスタ作成後に IPv6 / DualStack を有効化することができません。
MetalLB で IPv6 が付いても意味がなかった理由
MetalLB 自体は、IPv6 アドレスを正しく払い出していました。
しかし、
- ノード自体が IPv6 を保持していない
- CNI が IPv6 を扱えない状態で初期化されている
- ルーティングが存在しない
この状態では、IPv6 アドレスが割り当てられている「ように見えるだけ」 で、実際の通信は成立しません。
結果:すべて作り直し
最終的な対応は以下の通りです。
- microk8s を完全に削除
- クラスタを再構築
- 初期化前に DualStack 用 config を設定
- 再度 node join
- 再度アプリケーションを deploy
ノード数やデプロイ数が多い環境では、
この手戻りはかなりの負担になります。
学び
今回の件から得られた教訓です。
- microk8s の DualStack は事前設定が必須
- 後付けで IPv6 を有効化することはできない
- MetalLB が IPv6 を配っても、ノード側が対応していなければ意味がない
- Kubernetes は初期設計が非常に重要
まとめ
- microk8s は後から DualStack に変更できない
- 表面上 IPv6 が存在するように見える状態が最も危険
- DualStack 構成を目指す場合は、初期構築前にすべて設計する必要がある
- Kubernetes では「最初がすべて」
同じ問題で詰まる人が一人でも減れば幸いです。