ResourceQuota і LimitRange: ізоляція ресурсів тенантів у Kubernetes
Зауважимо: коли в мультитенантному кластері один тенант запускає resource-intensive batch job, інші сервіси деградують — ефект noisy-neighbor. Без квот на ресурси ви не контролюєте споживання. У кластері з 30+ тенантами 10% вузлів можуть використовувати 200% CPU під кешами, залишаючи сусідів без процесора. Єдиний спосіб гарантувати стабільність — налаштувати ResourceQuota та LimitRange для кожного namespace. Наші інженери з понад 5-річним досвідом у Kubernetes та 100+ проектами з ізоляції ресурсів роблять це під ключ: від аудиту до моніторингу. Оцінка проекту займає 2 дні, повна реалізація — від 2 до 5 днів. Середня економія після впровадження квот становить 150 000 грн на місяць на кластер із 30 вузлів. Вартість зайвих ресурсів за відсутності квот може сягати 300 000 грн на місяць.
ResourceQuota сама по собі запобігає близько 70% випадків шумного сусідства, а комбінація з LimitRange та моніторингом збільшує ефективність до 95% — це в 3 рази краще, ніж без LimitRange. Наші клієнти економлять до 40% хмарних ресурсів завдяки ефективному розподілу квот. Правильно налаштовані квоти та ліміти скорочують витрати на інстанси на 30-50%.
Як ResourceQuota та LimitRange вирішують проблему noisy-neighbor?
ResourceQuota обмежує сумарне споживання ресурсів у namespace. Kubernetes відхилятиме створення нових Pod, якщо їх додавання порушить квоту:
---
apiVersion: v1
kind: ResourceQuota
metadata:
name: tenant-standard
namespace: tenant-acme
spec:
hard:
requests.cpu: "4"
requests.memory: "8Gi"
limits.cpu: "8"
limits.memory: "16Gi"
pods: "40"
services.loadbalancers: "2"
services.nodeports: "0"
count/deployments.apps: "20"
count/jobs.batch: "10"
persistentvolumeclaims: "15"
requests.storage: "100Gi"
gold.storageclass.storage.k8s.io/requests.storage: "50Gi"
---
services.nodeports: "0" — заборона NodePort сервісів для тенантів. Це часта політика безпеки в мультитенантних кластерах.
gold.storageclass.storage.k8s.io/requests.storage: "50Gi" — ліміт на конкретний StorageClass. Тенант може використовувати дешевий standard-storage без обмежень (до загального ліміту), але дорогого SSD не більше 50 Gi.
Після створення ResourceQuota Kubernetes вимагає явних requests і limits у кожному Pod. Якщо Pod не має requests — він не буде створений (must specify requests for cpu). Це неочікувана поведінка, яка ламає деплої команд, не звиклих вказувати ресурси. Наш досвід показує, що це одна з частих проблем при впровадженні квот.
Чому LimitRange необхідний для роботи ResourceQuota?
LimitRange працює на рівні окремого Pod/Container. Встановлює:
- дефолтні
requestsіlimits, якщо не вказані явно - мінімальні та максимальні значення
- максимальне співвідношення limit/request (LimitRequestRatio)
---
apiVersion: v1
kind: LimitRange
metadata:
name: tenant-limits
namespace: tenant-acme
spec:
limits:
- type: Container
default:
cpu: "500m"
memory: "256Mi"
defaultRequest:
cpu: "100m"
memory: "64Mi"
max:
cpu: "2"
memory: "2Gi"
min:
cpu: "50m"
memory: "32Mi"
- type: PersistentVolumeClaim
max:
storage: "20Gi"
min:
storage: "1Gi"
default — якщо Pod створений без limits, LimitRange підставить їх автоматично. Це вирішує проблему з ResourceQuota, яка вимагає явних лімітів: навіть якщо розробник забув написати resources: — Pod створиться з дефолтними значеннями з LimitRange.
LimitRequestRatio — обмеження на burst. max.cpu / defaultRequest.cpu тут дорівнює 20 — контейнер може запитувати 100m CPU і отримувати burst до 2000m. Якщо потрібно обмежити burst:
- type: Container maxLimitRequestRatio: cpu: "4" Тепер якщо request = 100m, limit не може бути більше 400m.
Як налаштувати ResourceQuota та LimitRange для мультитенантного кластера?
Реальний SaaS зазвичай має кілька планів з різними лімітами. Зручно керувати через кастомний оператор або шаблони Helm, але структура проста. Порівняйте плани в таблиці:
| план | CPU request/limit | Memory request/limit | Pods | Storage |
|---|---|---|---|---|
| Free | 0.5 / 1 | 512Mi / 1Gi | 10 | 10Gi |
| Starter | 2 / 4 | 2Gi / 4Gi | 20 | 50Gi |
| Professional | 8 / 16 | 8Gi / 16Gi | 60 | 200Gi |
| Enterprise | без ліміту | без ліміту | 200 | без ліміту |
При апгрейді плану — оновлюємо ResourceQuota та LimitRange в namespace тенанта через Helm upgrade або Kubernetes API.
Покрокова інструкція впровадження квот
- Визначте рівні обслуговування та відповідні ліміти (таблиця вище).
- Створіть ResourceQuota для кожного namespace з урахуванням
podsтаcountресурсів. - Створіть LimitRange, щоб всі Pod мали мінімальні requests та явні limits.
- Протестуйте: спробуйте створити Pod, що перевищує ліміти — він має бути відхилений.
- Налаштуйте моніторинг (kube-state-metrics) та алерт при 80% використання квоти.
Типові проблеми при впровадженні квот
| Проблема | Причина | Рішення |
|---|---|---|
| Pod не створюється з помилкою 'must specify requests' | Відсутні ресурси в Pod | Встановіть LimitRange з default requests |
| Тенант вичерпав квоту CPU | Завищені ліміти додатків | Налаштуйте HorizontalPodAutoscaler з використанням CPU |
| Неочікувані відмови API при деплої | ResourceQuota не дозволяє створити Pod | Додайте моніторинг і збільште квоту по алерту |
Дії при вичерпанні квоти
Перше — налаштувати моніторинг використання квот. Ключові метрики через kube-state-metrics:
# Використання CPU-квоти тенантом
kube_resourcequota{namespace="tenant-acme", resource="requests.cpu", type="used"} / kube_resourcequota{namespace="tenant-acme", resource="requests.cpu", type="hard"}Алерт при використанні квоти вище 80% — тенант скоро впреться в ліміт, потрібно повідомити або запропонувати апгрейд. У Enterprise плані ми гарантуємо, що ліміти не стануть проблемою, і надаємо runbook для оперативного розширення.
API Throttling
Обмеження ресурсів Kubernetes не зачіпають API вашого додатку — це потрібно вирішувати окремо. Для rate limiting використовуйте Istio EnvoyFilter або Kong/Nginx:
---
# Istio EnvoyFilter для rate limiting
apiVersion: networking.istio.io/v1alpha3
kind: EnvoyFilter
metadata:
name: filter-ratelimit
namespace: tenant-acme
spec:
workloadSelector:
labels:
app: api-gateway
configPatches:
- applyTo: HTTP_FILTER
match:
context: SIDECAR_INBOUND
patch:
operation: INSERT_BEFORE
value:
name: envoy.filters.http.local_ratelimit
typed_config:
"@type": type.googleapis.com/udpa.type.v1.TypedStruct
token_bucket:
max_tokens: 1000
tokens_per_fill: 1000
fill_interval: 60s
Що входить у налаштування квот під ключ
Ми надаємо:
- Аудит поточної інфраструктури та виявлення noisy-neighbor
- Проектування ResourceQuota та LimitRange під ваші плани
- Реалізація за допомогою Terraform, Ansible або Helm
- Налаштування моніторингу та алертів за квотами
- Документація та навчання вашої команди
- Гарантія стабільної роботи — пост-релізна підтримка 2 тижні
Орієнтовний термін налаштування — від двох до п'яти днів залежно від складності. Вартість розраховується після аудиту. Для більш детального ознайомлення з ResourceQuota та LimitRange рекомендуємо звернутися до офіційної документації: Kubernetes Documentation, Resource Quotas.
Якщо ви хочете уникнути проблем з продуктивністю в мультитенантному кластері, запишіться на аудит. Наші інженери допоможуть налаштувати ідеальну ізоляцію. Замовте аудит та налаштування квот для вашого мультитенантного кластера — отримайте консультацію вже сьогодні.







