LoginSignup
9
3

More than 1 year has passed since last update.

Kubernetes: Service の静的 IP 用レンジを分割する (ServiceIPStaticSubrange)

Last updated at Posted at 2022-05-12

Service の静的 IP アドレス用のレンジを分割する ServiceIPStaticSubrange というフィーチャーゲートが、Kubernetes v1.24 でアルファ機能として導入されました。これは、Service の動的 IP アドレスと、静的 IP アドレスの衝突リスクを減らすための機能です。この記事では Kubernetes v1.24.0 時点で、この機能について調べた内容を記載しています。

Kubernetes v1.24 時点ではこの機能はアルファのため、本番環境での利用はベータ以上を待ったほうが良いでしょう。

背景

Service の IP アドレス(Cluster IP) は、動的・静的どちらの割り当ても可能です。通常は、.spec.clusterIP を省略し、動的な割り当てを使うことが多いと思います。しかし、クラスタ DNS の Service 1のように、静的な割り当てが必要なケースも稀ながら存在します。

動的・静的どちらの割り当ても、API サーバーが管理する Cluster IP のレンジから IP アドレスを選択します。動的な IP アドレスはこのレンジ内からランダムに選択されます 2。そのため、静的な Cluster IP は、動的に割り当てられた Cluster IP とアドレスが衝突する可能性がありました。

クラスタ DNS の場合、他の Service よりも早く作成しておくことで衝突を回避できます。しかし、汎用的な解決策ではなく、Service 再作成時など衝突の可能性が残っていました。

静的な Cluster IP 範囲の分割する (ServiceIPStaticSubrange)

この問題の解決のため実装されたのが、ServiceIPStaticSubrange という機能です。Kubernetes v1.24 ではアルファ機能のため、利用するにはフィーチャーゲートで有効にする必要があります。

service ip static subrange

この機能は、API サーバーの引数 --service-cluster-ip-range で指定された Cluster IP のレンジを、前半を静的割り当て用の優先レンジ、後半を動的割り当て用の優先レンジとして分割して管理する機能です。静的割り当て用のレンジは CIDR の大きさに応じて 16〜256 個の範囲で分割されます。

例えば、Cluster IP のレンジが 192.168.0.0/16 のとき、以下のように分割されます。

IP アドレス IP 数 用途
192.168.0.0 1 ネットワークアドレス
192.168.0.1 - 192.168.1.0 256 静的割り当て優先レンジ
192.168.1.1 - 192.168.255.254 65278 動的割り当て優先レンジ
192.168.255.255 1 ブロードキャストアドレス

このレンジはあくまで優先して使われるレンジであり、動的割り当て用レンジが枯渇した場合、静的割り当て用レンジからも動的に割り当てられる点にご注意ください。KEP-3070 によると、後方互換性を保つための仕様のようです。この仕様は公式ドキュメント にも記載されています。

Dynamic IP allocations will be preferentially chosen from the upper band, reducing risks of conflicts with the IPs assigned from the lower band.

Kubernetes v1.24.0 の実装では、動的用レンジの枯渇時に IP アドレスが重複するバグがあります。これは Fix ServiceIPStaticSubrange assigns duplicate IP addresses #109928 で修正されています。

CIDR サイズによる静的割り当て用のサイズ

静的割り当て用の優先レンジは、CIDR の大きさに応じて 16〜256 個の範囲で分割されます。この値は以下の計算式で求められます。

min(max(16, cidrSize / 16), 256)

動的割り当て用の優先レンジのサイズは以下で計算で求められます。(引いている 2 はネットワークアドレスとブロードキャストアドレス)

cidrSize - staticSize - 2
CIDR range 全 IP 数 static 用 dynamic 用
/26 64 16 46
/25 128 16 110
/24 256 16 238
/23 512 32 478
/22 1,024 64 958
/21 2,048 128 1,918
/20 4,096 256 3,838
/19 8,192 256 7,934
/18 16,384 256 16,126
/17 32,768 256 32,510
/16 65,536 256 65,278

minikube で ServiceIPStaticSubrange 試す

minikube を使うと、ServiceIPStaticSubrange を簡単に試すことができます。ここでは、意図的に小さい Cluster IP レンジ (/26) を指定しています。

minikube start \
  --kubernetes-version v1.24.0 \
  --extra-config=apiserver.service-cluster-ip-range=10.96.0.0/26 \
  --feature-gates=ServiceIPStaticSubrange=true

minikube 直後は、静的割り当てされた kubernetes 3 と、kube-dns の 2 Service が存在しています。

$ kubectl get svc --all-namespaces
NAMESPACE     NAME         TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)                  AGE
default       kubernetes   ClusterIP   10.96.0.1    <none>        443/TCP                  3m8s
kube-system   kube-dns     ClusterIP   10.96.0.10   <none>        53/UDP,53/TCP,9153/TCP   3m7s

Service を作成する前にダミーの Pod を作成しておきます。

kubectl create deploy nginx --image nginx --port 80

動的割り当ての Service を作ります。動的割り当て優先レンジの個数ピッタリの 46 個作成します。

for i in $(seq 1 46); do
  kubectl expose --name "svc$i" deploy/nginx --port 80
done

作成された Service を IP アドレスでソートして見てみます。動的割り当て優先レンジである 10.96.0.1710.96.0.62 の範囲で Service (svc*) が作らていることが確認できます。:tada:

$ kubectl get svc --all-namespaces | sort -k4 -V
default       kubernetes   ClusterIP   10.96.0.1    <none>        443/TCP                  3m53s
kube-system   kube-dns     ClusterIP   10.96.0.10   <none>        53/UDP,53/TCP,9153/TCP   3m52s
default       svc43        ClusterIP   10.96.0.17   <none>        80/TCP                   16s
default       svc40        ClusterIP   10.96.0.18   <none>        80/TCP                   16s
default       svc11        ClusterIP   10.96.0.19   <none>        80/TCP                   18s
default       svc10        ClusterIP   10.96.0.20   <none>        80/TCP                   18s
#....
default       svc7         ClusterIP   10.96.0.60   <none>        80/TCP                   18s
default       svc29        ClusterIP   10.96.0.61   <none>        80/TCP                   17s
default       svc28        ClusterIP   10.96.0.62   <none>        80/TCP                   17s
NAMESPACE     NAME         TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)                  AGE

本来、この次に動的割り当ての Service 作成すると、静的割り当て優先レンジの範囲から IP アドレスが割り当てられます。しかし、前述の通り Kubernetes v1.24.0 の実装では、動的用レンジの枯渇時に IP アドレスが重複するバグ のため正しく動作しませんでした。

ServiceIPStaticSubrange 無効の場合

前項の手順を ServiceIPStaticSubrange だけ無効にした場合、作成された Service は以下のようになりました。静的割り当ての Service (kubernetes, kube-dns) と動的割り当ての Service の IP アドレスが並んで割り当てられていることが確認できます。

$ kubectl get svc --all-namespaces | sort -k4 -V | head
default       kubernetes   ClusterIP   10.96.0.1    <none>        443/TCP                  6m40s
default       svc6         ClusterIP   10.96.0.2    <none>        80/TCP                   76s
default       svc25        ClusterIP   10.96.0.3    <none>        80/TCP                   75s
default       svc37        ClusterIP   10.96.0.4    <none>        80/TCP                   74s
default       svc39        ClusterIP   10.96.0.5    <none>        80/TCP                   74s
default       svc36        ClusterIP   10.96.0.6    <none>        80/TCP                   74s
default       svc41        ClusterIP   10.96.0.7    <none>        80/TCP                   74s
default       svc43        ClusterIP   10.96.0.8    <none>        80/TCP                   74s
default       svc46        ClusterIP   10.96.0.9    <none>        80/TCP                   74s
kube-system   kube-dns     ClusterIP   10.96.0.10   <none>        53/UDP,53/TCP,9153/TCP   6m38s

まとめ

ServiceIPStaticSubrange 機能を使って、Service の静的 IP アドレス用のレンジを分割して管理できることが確認できました。現在はアルファのため本番環境の使用には適しませんが、将来的に静的な IP アドレスの割り当て時の IP アドレスの衝突のリスクを大きく減らすことができそうです。

参考

  1. クラスタ DNS の IP アドレスは、kubelet の引数 --cluster-dns に事前に指定しておく必要があるため、静的な IP アドレスが必要です。

  2. 現在の動的割り当ての実装は Current Services ClusterIPs allocation model が参考になります。

  3. default ネームスペースの kubernetes は Kubernetes API サーバー用の特別な Service です。

9
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
3