Какие знаешь каскадные операции в Kubernetes?
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Каскадные операции в Kubernetes
Каскадные операции в Kubernetes — это механизм автоматического управления зависимостями между ресурсами. Когда удаляется родительский ресурс, каскадное удаление позволяет контролировать, что происходит с его дочерними ресурсами (Pod, Service и т.д.).
Концепция каскадного удаления
в Kubernetes есть три режима удаления ресурсов:
1. Foreground (передний план)
Зависимые ресурсы удаляются ДО удаления родительского ресурса.
# Deployment с foreground каскадным удалением
apiVersion: apps/v1
kind: Deployment
metadata:
name: app-deployment
spec:
replicas: 3
selector:
matchLabels:
app: myapp
template:
metadata:
labels:
app: myapp
spec:
containers:
- name: app
image: myapp:latest
Удаление с foreground:
kubectl delete deployment app-deployment --cascade=foreground
Процесс:
- Deployment переходит в состояние удаления (deletionTimestamp устанавливается)
- Kubernetes удаляет все Pod, связанные с этим Deployment
- Когда все Pod удалены, удаляется сам Deployment
Очрёдность:
- Родитель → Дети → Удаление родителя
2. Background (фон)
Родительский ресурс удаляется СРАЗУ, дочерние удаляются в фоне.
kubectl delete deployment app-deployment --cascade=background
Процесс:
- Deployment немедленно удаляется
- Pod продолжают работать некоторое время
- После завершения процесса утилизации Pod тоже удаляются
Очрёдность:
- Удаление родителя → Дети удаляются параллельно
3. Orphan (сирота)
Родитель удаляется, но дочерние ресурсы остаются без владельца (orphan).
kubectl delete deployment app-deployment --cascade=none
# Или
kubectl delete deployment app-deployment --cascade=orphan
Процесс:
- Deployment удаляется
- Pod продолжают работать независимо
- Pod больше не управляются никаким контроллером
Владение ресурсами (Owner References)
Владение ресурсов определяется через ownerReferences:
apiVersion: v1
kind: Pod
metadata:
name: example-pod
ownerReferences:
- apiVersion: apps/v1
kind: Deployment
name: app-deployment
uid: 1234abcd-5678-9012-efgh-ijklmnopqrst
controller: true
blockOwnerDeletion: true
spec:
containers:
- name: app
image: myapp:latest
Поля ownerReferences:
- apiVersion: версия API владельца
- kind: тип ресурса-владельца
- name: имя владельца
- uid: уникальный идентификатор владельца
- controller: является ли это контроллером
- blockOwnerDeletion: блокирует удаление владельца, пока этот ресурс существует
Каскадные операции для разных типов ресурсов
Deployment и ReplicaSet
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp
spec:
replicas: 3
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 1
selector:
matchLabels:
app: myapp
template:
metadata:
labels:
app: myapp
spec:
containers:
- name: myapp
image: myapp:1.0
Иерархия владения:
Deployment
└─ ReplicaSet (управляемый deployment)
└─ Pod (управляемые replicaset)
При удалении Deployment:
- foreground: Pod → ReplicaSet → Deployment
- background: Deployment (быстро), ReplicaSet и Pod удаляются позже
- orphan: ReplicaSet и Pod остаются как orphan
StatefulSet
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: mysql-statefulset
spec:
serviceName: mysql
replicas: 3
selector:
matchLabels:
app: mysql
template:
metadata:
labels:
app: mysql
spec:
containers:
- name: mysql
image: mysql:8.0
volumeMounts:
- name: data
mountPath: /var/lib/mysql
volumeClaimTemplates:
- metadata:
name: data
spec:
accessModes: [ "ReadWriteOnce" ]
resources:
requests:
storage: 10Gi
Особенность StatefulSet: PersistentVolumeClaim НЕ удаляются автоматически!
# Удаление со статей
kubectl delete statefulset mysql-statefulset
# PVC останутся!!
# Нужно удалить вручную
kubectl delete pvc data-mysql-statefulset-0 data-mysql-statefulset-1 ...
Job и Pod
apiVersion: batch/v1
kind: Job
metadata:
name: backup-job
spec:
parallelism: 2
completions: 4
backoffLimit: 3
template:
spec:
containers:
- name: backup
image: backup-tool:latest
restartPolicy: Never
Удаление Job:
# foreground (ждёт удаления Pod)
kubectl delete job backup-job --cascade=foreground
# background (быстро, Pod удаляются позже)
kubectl delete job backup-job --cascade=background
# orphan (Pod остаются работать)
kubectl delete job backup-job --cascade=orphan
Управление каскадным удалением через API
На Java с Fabric8 Kubernetes Client
import io.fabric8.kubernetes.client.KubernetesClient;
import io.fabric8.kubernetes.client.KubernetesClientBuilder;
import io.fabric8.kubernetes.api.model.apps.Deployment;
import io.fabric8.kubernetes.api.model.DeletionPropagation;
public class KubernetesOperations {
private KubernetesClient client;
public KubernetesOperations() {
this.client = new KubernetesClientBuilder().build();
}
// Foreground: ждёт удаления зависимостей
public void deleteDeploymentForeground(String namespace, String name) {
client.apps().deployments()
.inNamespace(namespace)
.withName(name)
.delete(); // По умолчанию foreground
}
// Background: быстрое удаление
public void deleteDeploymentBackground(String namespace, String name) {
client.apps().deployments()
.inNamespace(namespace)
.withName(name)
.withPropagationPolicy(DeletionPropagation.BACKGROUND)
.delete();
}
// Orphan: оставить Pod
public void deleteDeploymentOrphan(String namespace, String name) {
client.apps().deployments()
.inNamespace(namespace)
.withName(name)
.withPropagationPolicy(DeletionPropagation.ORPHAN)
.delete();
}
}
Программное удаление с контролем
public class CascadingDeletionController {
private KubernetesClient client;
// Удаление с ожиданием
public void deleteAndWait(String namespace, String deploymentName)
throws InterruptedException {
Deployment deployment = client.apps()
.deployments()
.inNamespace(namespace)
.withName(deploymentName)
.get();
if (deployment != null) {
// Запускаем удаление
client.apps()
.deployments()
.inNamespace(namespace)
.withName(deploymentName)
.delete();
// Ждём, пока удалится
boolean deleted = client.apps()
.deployments()
.inNamespace(namespace)
.withName(deploymentName)
.waitUntilCondition(d -> d == null, 5, TimeUnit.MINUTES);
if (deleted) {
System.out.println("Deployment успешно удалён");
}
}
}
// Graceful shutdown (корректное выключение)
public void gracefulShutdown(String namespace, String deploymentName,
long gracePeriodSeconds) {
client.apps()
.deployments()
.inNamespace(namespace)
.withName(deploymentName)
.withGracePeriod(gracePeriodSeconds)
.delete();
}
}
Практические сценарии
Сценарий 1: Перезагрузка Deployment
# Обновление образа (новое развёртывание)
kubectl set image deployment/myapp \
myapp=myapp:2.0 \
--record
# Kubernetes автоматически:
# - Создаёт новый ReplicaSet
# - Подключает Pod к новому RS (foreground)
# - Удаляет старый RS и его Pod
Сценарий 2: Миграция данных StatefulSet
# 1. Создаём новый StatefulSet с новой конфигурацией
kubectl apply -f new-statefulset.yaml
# 2. Мигрируем данные (вручную или через Job)
kubectl exec -it mysql-statefulset-0 -- backup.sh
# 3. Удаляем старый StatefulSet, сохраняя PVC
kubectl delete statefulset old-mysql --cascade=orphan
# 4. Проверяем, что PVC ещё на месте
kubectl get pvc
# 5. Связываем PVC с новым StatefulSet (если нужно)
# Обновляем volumeClaimTemplates в новом StatefulSet
Сценарий 3: Maintenance Mode
# Масштабируем Deployment на 0 (но не удаляем)
kubectl scale deployment myapp --replicas=0
# Выполняем работы
# ...
# Возвращаем в норму
kubectl scale deployment myapp --replicas=3
# Никакого каскадного удаления, Pod просто заморожены
Рекомендации
- Используй foreground (по умолчанию) для большинства случаев
- Используй background для быстрого удаления некритичных ресурсов
- Используй orphan перед миграцией или изменением владельца
- Всегда проверяй blockOwnerDeletion перед удалением
- Для StatefulSet помни о PVC, которые не удаляются
- Используй gracePeriod для корректного завершения приложений
- Документируй зависимости между ресурсами в своём кластере
Понимание каскадных операций критично для безопасного управления Kubernetes кластерами и предотвращения непредвиденной потери данных.