← Назад к вопросам

Какие знаешь каскадные операции в Kubernetes?

3.0 Senior🔥 131 комментариев
#Docker, Kubernetes и DevOps

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Каскадные операции в 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

Процесс:

  1. Deployment переходит в состояние удаления (deletionTimestamp устанавливается)
  2. Kubernetes удаляет все Pod, связанные с этим Deployment
  3. Когда все Pod удалены, удаляется сам Deployment

Очрёдность:

  • Родитель → Дети → Удаление родителя

2. Background (фон)

Родительский ресурс удаляется СРАЗУ, дочерние удаляются в фоне.

kubectl delete deployment app-deployment --cascade=background

Процесс:

  1. Deployment немедленно удаляется
  2. Pod продолжают работать некоторое время
  3. После завершения процесса утилизации Pod тоже удаляются

Очрёдность:

  • Удаление родителя → Дети удаляются параллельно

3. Orphan (сирота)

Родитель удаляется, но дочерние ресурсы остаются без владельца (orphan).

kubectl delete deployment app-deployment --cascade=none
# Или
kubectl delete deployment app-deployment --cascade=orphan

Процесс:

  1. Deployment удаляется
  2. Pod продолжают работать независимо
  3. 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 просто заморожены

Рекомендации

  1. Используй foreground (по умолчанию) для большинства случаев
  2. Используй background для быстрого удаления некритичных ресурсов
  3. Используй orphan перед миграцией или изменением владельца
  4. Всегда проверяй blockOwnerDeletion перед удалением
  5. Для StatefulSet помни о PVC, которые не удаляются
  6. Используй gracePeriod для корректного завершения приложений
  7. Документируй зависимости между ресурсами в своём кластере

Понимание каскадных операций критично для безопасного управления Kubernetes кластерами и предотвращения непредвиденной потери данных.

Какие знаешь каскадные операции в Kubernetes? | PrepBro