Information in this document may be out of date

This document has an older update date than the original, so the information it contains may be out of date. If you're able to read English, see the English version for the most up-to-date information: Extend Service IP Ranges

扩展 Service IP 范围

特性状态: Kubernetes v1.29 [alpha]

本文将介绍如何扩展分配给集群的现有 Service IP 范围。

准备开始

你必须拥有一个 Kubernetes 的集群,同时你必须配置 kubectl 命令行工具与你的集群通信。 建议在至少有两个不作为控制平面主机的节点的集群上运行本教程。 如果你还没有集群,你可以通过 Minikube 构建一个你自己的集群,或者你可以使用下面的 Kubernetes 练习环境之一:

你的 Kubernetes 服务器版本必须不低于版本 v1.29. 要获知版本信息,请输入 kubectl version.

API

如果 Kubernetes 集群的 kube-apiserver 启用了 MultiCIDRServiceAllocator 特性门控networking.k8s.io/v1alpha1 API,集群将创建一个新的 ServiceCIDR 对象, 该对象采用 kubernetes 这个众所周知的名称并基于 kube-apiserver 的 --service-cluster-ip-range 命令行参数的值来使用 IP 地址范围。

kubectl get servicecidr
NAME         CIDRS          AGE
kubernetes   10.96.0.0/28   17d

公认的 kubernetes Service 将 kube-apiserver 的端点暴露给 Pod, 计算出默认 ServiceCIDR 范围中的第一个 IP 地址,并将该 IP 地址用作其集群 IP 地址。

kubectl get service kubernetes
NAME         TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
kubernetes   ClusterIP   10.96.0.1    <none>        443/TCP   17d

在本例中,默认 Service 使用具有对应 IPAddress 对象的 ClusterIP 10.96.0.1。

kubectl get ipaddress 10.96.0.1
NAME        PARENTREF
10.96.0.1   services/default/kubernetes

ServiceCIDR 受到 终结器 的保护, 以避免留下孤立的 Service ClusterIP;只有在存在包含现有 IPAddress 的另一个子网或者没有属于此子网的 IPAddress 时,才会移除终结器。

扩展 Service 可用的 IP 数量

有时候用户需要增加可供 Service 使用的 IP 地址数量。 以前,增加 Service 范围是一个可能导致数据丢失的破坏性操作。 有了这个新的特性后,用户只需添加一个新的 ServiceCIDR 对象,便能增加可用地址的数量。

添加新的 ServiceCIDR

对于 Service 范围为 10.96.0.0/28 的集群,只有 2^(32-28) - 2 = 14 个可用的 IP 地址。 kubernetes.default Service 始终会被创建;在这个例子中,你只剩下了 13 个可能的 Service。

for i in $(seq 1 13); do kubectl create service clusterip "test-$i" --tcp 80 -o json | jq -r .spec.clusterIP; done
10.96.0.11
10.96.0.5
10.96.0.12
10.96.0.13
10.96.0.14
10.96.0.2
10.96.0.3
10.96.0.4
10.96.0.6
10.96.0.7
10.96.0.8
10.96.0.9
error: failed to create ClusterIP service: Internal error occurred: failed to allocate a serviceIP: range is full

通过创建一个扩展或新增 IP 地址范围的新 ServiceCIDR,你可以提高 Service 可用的 IP 地址数量。

cat <EOF | kubectl apply -f -
apiVersion: networking.k8s.io/v1alpha1
kind: ServiceCIDR
metadata:
  name: newcidr1
spec:
  cidrs:
  - 10.96.0.0/24
EOF
servicecidr.networking.k8s.io/newcidr1 created

这将允许你创建新的 Service,其 ClusterIP 将从这个新的范围中选取。

for i in $(seq 13 16); do kubectl create service clusterip "test-$i" --tcp 80 -o json | jq -r .spec.clusterIP; done
10.96.0.48
10.96.0.200
10.96.0.121
10.96.0.144

删除 ServiceCIDR

如果存在依赖于 ServiceCIDR 的 IPAddress,你将无法删除 ServiceCIDR。

kubectl delete servicecidr newcidr1
servicecidr.networking.k8s.io "newcidr1" deleted

Kubernetes 在 ServiceCIDR 上使用一个终结器来跟踪这种依赖关系。

kubectl get servicecidr newcidr1 -o yaml
apiVersion: networking.k8s.io/v1alpha1
kind: ServiceCIDR
metadata:
  creationTimestamp: "2023-10-12T15:11:07Z"
  deletionGracePeriodSeconds: 0
  deletionTimestamp: "2023-10-12T15:12:45Z"
  finalizers:
    - networking.k8s.io/service-cidr-finalizer
  name: newcidr1
  resourceVersion: "1133"
  uid: 5ffd8afe-c78f-4e60-ae76-cec448a8af40
spec:
  cidrs:
    - 10.96.0.0/24
status:
  conditions:
    - lastTransitionTime: "2023-10-12T15:12:45Z"
      message:
        There are still IPAddresses referencing the ServiceCIDR, please remove
        them or create a new ServiceCIDR
      reason: OrphanIPAddress
      status: "False"
      type: Ready

移除一些 Service,这些 Service 包含阻止删除 ServiceCIDR 的 IP 地址:

for i in $(seq 13 16); do kubectl delete service "test-$i" ; done
service "test-13" deleted
service "test-14" deleted
service "test-15" deleted
service "test-16" deleted

控制平面会注意到这种移除操作。控制平面随后会移除其终结器,以便真正移除待删除的 ServiceCIDR。

kubectl get servicecidr newcidr1
Error from server (NotFound): servicecidrs.networking.k8s.io "newcidr1" not found
最后修改 December 14, 2023 at 9:46 AM PST: [zh] Localize extend-service-ip-ranges.md (57d11ada6b)