手当たり次第に書くんだ

飽きっぽいのは本能

MicroK8s で IPv6/IPv4 デュアルスタックが動かない時に見ること

MicroK8s 上で WordPress を運用していた時期に、最終的には IPv6/IPv4 デュアルスタックで動かしたいと考えていました。MicroK8s 自体はデュアルスタックに対応していますが、実際に検証すると、私の環境では期待通りに動きませんでした。

この記事は、その時の「うまく動かなかった」という短いメモを、Kubernetes のデュアルスタックでどこを見るべきかという観点で整理し直したものです。

発生した現象

検証時に確認できた現象は、単純な「IPv6 アドレスが付かない」ではありませんでした。Pod には IPv4 / IPv6 のアドレスが割り当てられているように見える一方で、コンテナ発の通信がうまくできませんでした。

  • Pod には IPv4 / IPv6 のアドレスが割り当てられる
  • 外部からの通信は成立する
  • コンテナ内から外部へ出る通信が安定しない
  • iptables / CNI / 経路制御のどこかで期待通りに処理されていないように見える

つまり、Kubernetes API 上はデュアルスタックらしく見えていても、Pod から外へ出る経路、NAT、ルーティング、DNS、Service の IP ファミリーまで含めると、実運用としては不十分な状態でした。

デュアルスタックはアドレスが付けば終わりではない

Kubernetes の IPv4/IPv6 デュアルスタックは、Pod と Service に両方のアドレスファミリーを持たせられる機能です。ただし、Pod に IPv6 アドレスが付くことと、Pod から IPv6 で外部通信できることは同じではありません。

  • Node 自体に IPv6 の到達性があるか
  • Pod CIDR と Service CIDR が IPv4 / IPv6 の両方で設計されているか
  • CNI が IPv4 / IPv6 の両方を正しく扱っているか
  • Service の ipFamilyPolicyipFamilies が意図通りか
  • Pod から外部へ出る経路や NAT が IPv4 / IPv6 で成立しているか

このどれかが崩れると、見た目はデュアルスタックでも、実際の通信では片方のスタックが機能しない状態になります。

MicroK8s では初期設計が特に重要

MicroK8s の現行ドキュメントでは、ネットワーク CIDR の設定はクラスタやノードの初期段階で行うことが重要だと説明されています。MicroK8s 1.28 以降では launch configuration で IPv4 / IPv6 の Pod CIDR と Service CIDR を指定できます。

---
version: 0.1.0
extraCNIEnv:
  IPv4_SUPPORT: true
  IPv4_CLUSTER_CIDR: 10.3.0.0/16
  IPv4_SERVICE_CIDR: 10.153.183.0/24
  IPv6_SUPPORT: true
  IPv6_CLUSTER_CIDR: fd02::/64
  IPv6_SERVICE_CIDR: fd99::/108
extraSANs:
  - 10.153.183.1

ここで重要なのは、後から既存クラスタを少し直してデュアルスタック化するというより、最初から Pod CIDR、Service CIDR、CNI、ノード間経路をデュアルスタック前提で組む必要がある点です。

確認するポイント

再検証するなら、まず Kubernetes 上で「デュアルスタックに見えているか」と、実際の Pod 内通信が一致しているかを分けて確認します。

kubectl get node -o wide
kubectl get pod -A -o wide
kubectl get svc -A -o wide

# Pod に割り当てられた IP を確認する
kubectl get pod POD_NAME -o jsonpath='{.status.podIPs}'

# Service の IP ファミリーを確認する
kubectl get svc SERVICE_NAME -o yaml | grep -E "clusterIP|clusterIPs|ipFamilies|ipFamilyPolicy"

次に、Pod の中から IPv4 / IPv6 の外部通信、DNS 名前解決、Service 宛て通信を個別に確認します。

kubectl run -it --rm netshoot --image=nicolaka/netshoot -- /bin/bash

# Pod 内で確認する例
ip addr
ip route
ip -6 route
curl -4 https://example.com/
curl -6 https://example.com/
nslookup kubernetes.default.svc.cluster.local

Service 側の設定も確認する

Kubernetes の Service は、ipFamilyPolicy によって単一スタック、優先デュアルスタック、必須デュアルスタックを指定できます。クラスタがデュアルスタックでも、Service が意図した IP ファミリーで作られているとは限りません。

apiVersion: v1
kind: Service
metadata:
  name: nginx-dualstack
spec:
  type: ClusterIP
  ipFamilyPolicy: RequireDualStack
  ipFamilies:
    - IPv4
    - IPv6
  selector:
    app: nginx
  ports:
    - port: 80
      targetPort: 80

特に、外部から入る通信だけを見ると問題が見えにくいです。Service、Pod、Node、外部経路のどこで IPv4 と IPv6 が分岐しているかを分けて見る必要があります。

当時の判断

当時は、WordPress を安定運用することが目的だったため、MicroK8s のデュアルスタックを深追いせず、VM 上で運用する判断をしました。IPv6 を優先したかったので、Kubernetes のネットワーク実験に運用環境を巻き込むより、構成を単純にした方がよいと考えました。

この判断は今でも妥当だったと思います。Kubernetes のデュアルスタックは機能としては安定してきていますが、実際に運用するには CNI、ノード間経路、外部公開、DNS、ロードバランサーまで含めて確認する必要があります。

まとめ

MicroK8s で IPv6/IPv4 デュアルスタックが動かない場合、単に「MicroK8s が未対応」と見るのではなく、Pod CIDR、Service CIDR、CNI、Service の IP ファミリー、Pod から外部への経路を分けて確認する必要があります。

私の環境では、Pod に IPv4 / IPv6 が割り当てられても、コンテナ発の通信が期待通りに成立しませんでした。そのため、当時は VM 運用へ戻しました。再挑戦するなら、既存クラスタの後付け変更ではなく、初期構築時点からデュアルスタック前提で MicroK8s を構成するところから始めるべきだと思います。

参考
書籍
参考書籍

Kubernetes完全ガイド 第2版

Kubernetes の仕組み、リソース、ネットワーク、運用観点を体系的に確認したい場合の参考書籍です。価格や在庫はリンク先で確認してください。

Amazon で見る

このリンクは Amazon アソシエイトリンクです。

参考

MicroK8s で IPv6/IPv4 デュアルスタックが動かない時に見ること

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)

トップへ戻る