This is a stable feature in Kubernetes, and has been since version v1.33. It was first available in the v1.27 release. You can no longer disable or opt out of this feature or behavior (it is locked); if you explicitly set a value for the associated feature gate MultiCIDRServiceAllocator, Kubernetes ignores it but does not report any error.
У цьому документі описано, як розширити наявний діапазон IP-адрес Service, призначений кластеру.
Вам треба мати кластер Kubernetes, а також інструмент командного рядка kubectl має бути налаштований для роботи з вашим кластером. Рекомендується виконувати ці настанови у кластері, що має щонайменше два вузли, які не виконують роль вузлів управління. Якщо у вас немає кластера, ви можете створити його, за допомогою minikube або використовувати одну з цих пісочниць:
Версія вашого Kubernetes сервера має бути не старішою ніж v1.29.Для перевірки версії введіть kubectl version.
Панель управління забезпечує наявність спеціального обʼєкта ServiceCIDR із загальновідомою назвою kubernetes, який визначає діапазон IP-адрес на основі значення аргументу командного рядка --service-cluster-ip-range для kube-apiserver.
kubectl get servicecidr
NAME CIDRS AGE
kubernetes 10.96.0.0/28 17d
Загальновідомий Service kubernetes, який відкриває Podʼам доступ до точки доступу kube-apiserver, обчислює першу IP-адресу зі стандартного діапазону ServiceCIDR і використовує її як свою кластерну 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 у цьому випадку використовує ClusterIP 10.96.0.1, що має відповідний обʼєкт IPAddress.
kubectl get ipaddress 10.96.0.1
NAME PARENTREF
10.96.0.1 services/default/kubernetes
ServiceCIDRs захищені завершувачами, щоб ClusterIP у Service не лишалися без батьківського обʼєкта; завершувач вилучається лише тоді, коли існує інша підмережа з наявними IPAddresses або немає IPAddresses, що належать до цієї підмережі.
Іноді користувачам потрібно збільшити кількість адрес, доступних для Services. Раніше збільшення діапазону Service було операцією з порушенням роботи, яка також могла спричинити втрату даних. Завдяки цій новій можливості користувачам достатньо додати новий ServiceCIDR, щоб збільшити кількість доступних адрес.
У кластері з діапазоном 10.96.0.0/28 для Services доступно лише 2^(32-28) - 2 = 14 IP-адрес. Service kubernetes.default створюється завжди; у цьому прикладі лишається лише 13 можливих Services.
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-адрес, доступних для Services, створивши новий ServiceCIDR, який розширює наявні або додає нові діапазони IP-адрес.
cat <<EOF | kubectl apply -f -
apiVersion: networking.k8s.io/v1
kind: ServiceCIDR
metadata:
name: newcidr1
spec:
cidrs:
- 10.96.0.0/24
EOF
servicecidr.networking.k8s.io/newcidr1 created
і це дозволить створювати нові Services з 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, якщо є IPAddresses, які залежать від цього ServiceCIDR.
kubectl delete servicecidr newcidr1
servicecidr.networking.k8s.io "newcidr1" deleted
Kubernetes використовує завершувач на ServiceCIDR, щоб відстежувати цю залежність.
kubectl get servicecidr newcidr1 -o yaml
apiVersion: networking.k8s.io/v1
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
Видаляючи Services з IP-адресами, які блокують видалення ServiceCIDR,
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
Адміністратори кластера можуть застосовувати політики для контролю створення й зміни ресурсів ServiceCIDR у кластері. Це дає змогу централізовано керувати діапазонами IP-адрес, які використовуються для Services, і запобігає ненавмисним або конфліктним конфігураціям. Kubernetes надає для застосування цих правил такі механізми, як валідаційні політики допуску (Validating Admission Policies).
Іноді адміністратори кластера хочуть обмежити дозволені діапазони або повністю заборонити будь-які зміни діапазонів IP-адрес Service кластера.
Стандартний ServiceCIDR "kubernetes" створюється kube-apiserver для забезпечення узгодженості в кластері й потрібен для роботи кластера, тому його завжди потрібно дозволяти. Щоб ValidatingAdmissionPolicy не обмежувала стандартний ServiceCIDR, додайте таку умову:
matchConditions:
- name: 'exclude-default-servicecidr'
expression: "object.metadata.name != 'kubernetes'"
як у наведених нижче прикладах.
Нижче наведено приклад ValidatingAdmissionPolicy, яка дозволяє створювати ServiceCIDR, лише якщо вони є піддіапазонами заданих діапазонів allowed. (Отже, ця політика дозволить ServiceCIDR з cidrs: ['10.96.1.0/24'] або cidrs: ['2001:db8:0:0:ffff::/80', '10.96.0.0/20'], але не дозволить ServiceCIDR з cidrs: ['172.20.0.0/16'].) Ви можете скопіювати цю політику й змінити значення allowed на відповідне для вашого кластера.
apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingAdmissionPolicy
metadata:
name: "servicecidrs.default"
spec:
failurePolicy: Fail
matchConstraints:
resourceRules:
- apiGroups: ["networking.k8s.io"]
apiVersions: ["v1"]
operations: ["CREATE", "UPDATE"]
resources: ["servicecidrs"]
matchConditions:
- name: 'exclude-default-servicecidr'
expression: "object.metadata.name != 'kubernetes'"
variables:
- name: allowed
expression: "['10.96.0.0/16','2001:db8::/64']"
validations:
- expression: "object.spec.cidrs.all(newCIDR, variables.allowed.exists(allowedCIDR, cidr(allowedCIDR).containsCIDR(newCIDR)))"
# For all CIDRs (newCIDR) listed in the spec.cidrs of the submitted ServiceCIDR
# object, check if there exists at least one CIDR (allowedCIDR) in the `allowed`
# list of the VAP such that the allowedCIDR fully contains the newCIDR.
---
apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingAdmissionPolicyBinding
metadata:
name: "servicecidrs-default-binding"
spec:
policyName: "servicecidrs.default"
validationActions: [Deny,Audit]
Щоб дізнатися більше про CEL і написати власний expression для валідації, дивіться документацію CEL.
Наведений нижче приклад показує, як використовувати ValidatingAdmissionPolicy та її привʼязку, щоб обмежити створення будь-яких нових діапазонів Service CIDR, окрім стандартного ServiceCIDR "kubernetes":
apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingAdmissionPolicy
metadata:
name: "servicecidrs.deny"
spec:
failurePolicy: Fail
matchConstraints:
resourceRules:
- apiGroups: ["networking.k8s.io"]
apiVersions: ["v1"]
operations: ["CREATE", "UPDATE"]
resources: ["servicecidrs"]
validations:
# Deny changes to all ServiceCIDRs except the default one
- expression: "object.metadata.name == 'kubernetes'"
message: "you can only create or update the default ServiceCIDR"
# Deny changes from all users except kube-apiserver
- expression: "request.userInfo.username == 'system:apiserver' && 'system:masters' in request.userInfo.groups"
message: "you can not create or update ServiceCIDR objects"
---
apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingAdmissionPolicyBinding
metadata:
name: "servicecidrs-deny-binding"
spec:
policyName: "servicecidrs.deny"
validationActions: [Deny,Audit]