Kubernetesクラスタを運用するうえで、Kubernetes Services向けのIPアドレスを十分に確保することは、インフラを拡張・維持していく際の重要なポイントになります。
Servicesは、一連のPod上で動作するアプリケーションを抽象化して公開する仕組みです。ClusterIP、NodePort、LoadBalancerといった各種Serviceは、ClusterIPと呼ばれるクラスタ全体で一意の仮想IPアドレスを利用します。
各ServiceのクラスタIPアドレスは、クラスタ内で一意でなければなりません。すでに割り当て済みのClusterIPでServiceを作成しようとするとエラーになります。デプロイ規模が拡大するにつれ、デフォルトのService IP範囲では足りなくなり、ネットワークリソースのボトルネックを引き起こすおそれがあります。
従来は、Serviceに割り当てるIP範囲をリサイズしたり拡張したりすることができず、ネットワークが重複したり、クラスタが利用可能なIPを使い切ってしまった際に問題となっていました。
しかし、MultiCIDRServiceAllocator feature gateとnetworking.k8s.io/v1alpha1 APIを有効化したkube-apiserverを使えば、Service向けに利用可能なIP数を動的に拡張できます。この機能はKubernetes 1.31でベータに昇格しました。本番環境で利用する前に、Stableへの昇格を待つことをおすすめします。実装の詳細についてはKEP-1880—Multiple Service CIDRsをご参照ください。
本記事では、Google Kubernetes Engine(GKE)クラスタでService IP範囲を拡張する方法を解説します。本機能は他のKubernetesディストリビューションでも試せますので、設定や制限の詳細については各ディストリビューションのリリースノートをご確認ください。
前提条件
バージョン1.31.1-gke.1361000以降のGKEクラスタが必要です。また、kubectlコマンドラインツールがクラスタと通信できるように設定されていることを確認してください。
Beta APIの有効化と確認
Kubernetes 1.24以降、新規GKEクラスタでは新しいbeta APIがデフォルトで無効になっています。1.24より前のバージョンで作成された既存クラスタでは、既存のbeta APIは有効のまま維持されます。
beta APIはクラスタ作成時、または作成後に有効化できます。必要なbeta APIを有効にするには、Use Kubernetes beta APIs with GKE clustersの手順に従ってください。
既存クラスタで必要なbeta APIを有効化するコマンドの例:
gcloud container clusters update <<GKE_CLUSTER_NAME>> \
--enable-kubernetes-unstable-apis=networking.k8s.io/v1beta1/ipaddresses,networking.k8s.io/v1beta1/servicecidrs
--region <<GKE_CLUSTER_REGION>> \
--project <<GCP_PROJECT_NAME>>
新たに有効化されたAPIにより、kubernetesというwell-knownな名前と、初期のサービスCIDRに基づくIPアドレス範囲を持つServiceCIDRオブジェクトが作成されます。
以下のコマンドを実行し、新しいServiceCIDRオブジェクトを確認します。
Chimbus-MacBook-Pro:~ chimbu$ kubectl get servicecidr
NAME CIDRS AGE
kubernetes 10.96.0.0/28 98m
Chimbus-MacBook-Pro:~ chimbu$
新しいServiceCIDRの追加
検証用に、Service向けのIPアドレスが14個しかない/28範囲のクラスタを作成しました。kubernetes.default Serviceは必ず作成されるため、この例で作成可能なServiceは13個までとなります。
検証用に、Service向けのIPアドレスが14個しかない/28範囲のクラスタを作成しました。kubernetes.default serviceは必ず作成されるため、作成可能なServiceは13個のみとなります。
追加のKubernetes Serviceを作成しようとすると、Service範囲のIPアドレスをすべて使い切った時点で、リクエストはinternal errorで失敗します。
Chimbus-MacBook-Pro:~ chimbu$ for i in $(seq 1 13); do kubectl create service clusterip "service-test-$i" --tcp 80 -o json | jq -r .spec.clusterIP; done
10.96.0.13
10.96.0.11
10.96.0.7
10.96.0.14
10.96.0.3
10.96.0.12
10.96.0.9
10.96.0.4
10.96.0.5
error: failed to create ClusterIP service: Internal error occurred: failed to allocate a serviceIP: range is full
error: failed to create ClusterIP service: Internal error occurred: failed to allocate a serviceIP: range is full
error: failed to create ClusterIP service: Internal error occurred: failed to allocate a serviceIP: range is full
error: failed to create ClusterIP service: Internal error occurred: failed to allocate a serviceIP: range is full
Chimbus-MacBook-Pro:~ chimbu$
新たなIPアドレス範囲を追加・拡張するServiceCIDRを作成すれば、Service向けに利用できるIPアドレス数を増やせます。
ベータ期間中、GKEではIPアドレス範囲の重複による問題を避けるため、予約済みIPアドレス範囲
34.118.224.0/20内でのみService CIDRを作成できます。
以下のマニフェストを適用して、新しいIPアドレス範囲を追加するServiceCIDRを作成します。
cat <<EOF | kubectl apply -f -
apiVersion: networking.k8s.io/v1beta1
kind: ServiceCIDR
metadata:
name: newcidr1
spec:
cidrs:
- 34.118.224.0/20
EOF
Chimbus-MacBook-Pro:~ chimbu$ kubectl get servicecidrs.networking.k8s.io
NAME CIDRS AGE
kubernetes 10.96.0.0/28 104m
newcidr1 34.118.224.0/20 5s
Chimbus-MacBook-Pro:~ chimbu$
新しいKubernetes Serviceを作成すると、クラスタIPアドレスはこの新しい範囲から割り当てられます。
Chimbus-MacBook-Pro:~ chimbu$ for i in $(seq 1 13); do kubectl create service clusterip "service-test-new-$i" --tcp 80 -o json | jq -r .spec.clusterIP; done
34.118.235.89
34.118.234.162
34.118.230.252
34.118.226.209
34.118.227.183
34.118.227.182
^C
Chimbus-MacBook-Pro:~ chimbu$ kubectl get service
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 105m
service-test-1 ClusterIP 10.96.0.13 <none> 80/TCP 3m41s
service-test-2 ClusterIP 10.96.0.11 <none> 80/TCP 3m39s
service-test-3 ClusterIP 10.96.0.7 <none> 80/TCP 3m39s
service-test-4 ClusterIP 10.96.0.14 <none> 80/TCP 3m38s
service-test-5 ClusterIP 10.96.0.3 <none> 80/TCP 3m37s
service-test-6 ClusterIP 10.96.0.12 <none> 80/TCP 3m36s
service-test-7 ClusterIP 10.96.0.9 <none> 80/TCP 3m35s
service-test-8 ClusterIP 10.96.0.4 <none> 80/TCP 3m34s
service-test-9 ClusterIP 10.96.0.5 <none> 80/TCP 3m33s
service-test-new-1 ClusterIP 34.118.235.89 <none> 80/TCP 8s
service-test-new-2 ClusterIP 34.118.234.162 <none> 80/TCP 8s
service-test-new-3 ClusterIP 34.118.230.252 <none> 80/TCP 7s
service-test-new-4 ClusterIP 34.118.226.209 <none> 80/TCP 6s
service-test-new-5 ClusterIP 34.118.227.183 <none> 80/TCP 5s
service-test-new-6 ClusterIP 34.118.227.182 <none> 80/TCP 4s
Chimbus-MacBook-Pro:~ chimbu$
ServiceCIDRの削除
ServiceCIDRは、Service ClusterIPが孤立するのを防ぐためfinalizerで保護されています。finalizerは、対象サブネットに属するいずれのServiceにもIPアドレスが割り当てられていない場合に限り削除されます。
そのため、まずはServiceCIDRのIPアドレスを使用しているKubernetes Serviceをすべて削除したうえで、ServiceCIDRオブジェクトを削除する必要があります。
まとめると、Kubernetesクラスタが拡大していくなかで、Service IP範囲の拡張はIP枯渇を回避し、スムーズなスケーラビリティを確保するうえで欠かせない要素です。今回の新機能により、リソースのボトルネックを招くことなく、時間とともにService IPアドレスを追加していく必要のある環境にも柔軟に対応できるようになります。
本記事が皆さまの参考になれば幸いです。さらに詳しく知りたい方や、当社のサービスにご関心をお持ちの方は、お気軽にお問い合わせください。お問い合わせはこちらから。