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

Как дать понять Kubernetes, что программа запущена и готова?

1.8 Middle🔥 252 комментариев
#Контейнеризация и DevOps#Микросервисы и архитектура

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

🐱
deepseek-v3.2PrepBro AI5 апр. 2026 г.(ред.)

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

Механизмы готовности (Readiness) в Kubernetes

В Kubernetes readiness probe (проверка готовности) — это механизм, который информирует kubelet о том, что контейнер внутри Pod готов начать принимать трафик. Если проверка готовности успешна, Endpoints-объект Service включает этот Pod в список целей для балансировки нагрузки. Если проверка не проходит или отсутствует, Pod временно исключается из балансировки.

Типы Readiness Probes

Kubernetes поддерживает три основных типа проверок готовности:

1. HTTP GET Probe

Наиболее распространённый способ. Kubelet выполняет HTTP GET-запрос по указанному пути и порту. Код ответа между 200 и 399 считается успехом.

readinessProbe:
  httpGet:
    path: /health/ready
    port: 8080
  initialDelaySeconds: 5
  periodSeconds: 10
  timeoutSeconds: 2
  successThreshold: 1
  failureThreshold: 3

2. TCP Socket Probe

Kubelet пытается установить TCP-соединение с указанным портом контейнера. Успех означает, что соединение установлено.

readinessProbe:
  tcpSocket:
    port: 8080
  initialDelaySeconds: 15
  periodSeconds: 10

3. Exec Probe

Kubelet выполняет заданную команду внутри контейнера. Код возврата 0 означает успех.

readinessProbe:
  exec:
    command:
    - /bin/sh
    - -c
    - curl -f http://localhost:8080/ready || exit 1
  initialDelaySeconds: 5
  periodSeconds: 5

Ключевые параметры конфигурации

  • initialDelaySeconds: Задержка перед первой проверкой после старта контейнера
  • periodSeconds: Периодичность выполнения проверок
  • timeoutSeconds: Таймаут для каждой попытки проверки
  • successThreshold: Количество последовательных успешных проверок для перехода в состояние "Ready"
  • failureThreshold: Количество неудачных проверок перед тем, как Pod будет считаться "Not Ready"

Практическая реализация на Go

Для Go-приложения типично создавать отдельный HTTP-эндпоинт для проверки готовности. Вот пример реализации:

package main

import (
    "net/http"
    "sync"
    "time"
)

type ReadinessChecker struct {
    mu       sync.RWMutex
    ready    bool
    startedAt time.Time
}

func (rc *ReadinessChecker) SetReady(ready bool) {
    rc.mu.Lock()
    defer rc.mu.Unlock()
    rc.ready = ready
}

func (rc *ReadinessChecker) IsReady() bool {
    rc.mu.RLock()
    defer rc.mu.RUnlock()
    return rc.ready
}

func (rc *ReadinessChecker) readinessHandler(w http.ResponseWriter, r *http.Request) {
    if rc.IsReady() {
        w.WriteHeader(http.StatusOK)
        w.Write([]byte("OK"))
    } else {
        w.WriteHeader(http.StatusServiceUnavailable)
        w.Write([]byte("NOT READY"))
    }
}

func main() {
    checker := &ReadinessChecker{
        startedAt: time.Now(),
    }
    
    // Имитация инициализации приложения
    go func() {
        time.Sleep(10 * time.Second) // Имитация долгой инициализации
        checker.SetReady(true)
    }()
    
    http.HandleFunc("/health/ready", checker.readinessHandler)
    http.ListenAndServe(":8080", nil)
}

Различия между Liveness и Readiness Probes

Важно понимать разницу между двумя типами проверок:

  • Liveness Probe определяет, нужно ли перезапустить контейнер
  • Readiness Probe определяет, готов ли контейнер принимать трафик
apiVersion: v1
kind: Pod
metadata:
  name: example-app
spec:
  containers:
  - name: app
    image: myapp:latest
    ports:
    - containerPort: 8080
    livenessProbe:
      httpGet:
        path: /health/live
        port: 8080
      initialDelaySeconds: 30
    readinessProbe:
      httpGet:
        path: /health/ready
        port: 8080
      initialDelaySeconds: 5
      periodSeconds: 5

Best Practices и рекомендации

  1. Начинайте с минимальной функциональности: Readiness probe должна проверять только критически важные зависимости
  2. Избегайте тяжелых операций: Проверка должна выполняться быстро, без нагрузочных запросов к БД или внешним сервисам
  3. Используйте разные эндпоинты для liveness и readiness проверок
  4. Настройте правильные тайминги: initialDelaySeconds должен учитывать время инициализации приложения
  5. Логируйте состояния: Добавляйте логирование при изменении состояния готовности
  6. Тестируйте отказоустойчивость: Убедитесь, что при временной недоступности зависимостей Pod корректно выводится из балансировки
  7. Используйте sidecar-контейнеры для сложных проверок в микросервисных архитектурах

Пример продвинутой реализации

Для сложных приложений можно реализовать многоуровневую проверку готовности:

type HealthStatus struct {
    Database bool `json:"database"`
    Cache    bool `json:"cache"`
    Storage  bool `json:"storage"`
}

func (rc *ReadinessChecker) advancedReadinessHandler(w http.ResponseWriter, r *http.Request) {
    status := HealthStatus{
        Database: rc.checkDatabase(),
        Cache:    rc.checkCache(),
        Storage:  rc.checkStorage(),
    }
    
    allHealthy := status.Database && status.Cache && status.Storage
    
    w.Header().Set("Content-Type", "application/json")
    if allHealthy {
        w.WriteHeader(http.StatusOK)
    } else {
        w.WriteHeader(http.StatusServiceUnavailable)
    }
    
    json.NewEncoder(w).Encode(status)
}

Правильно настроенная readiness probe позволяет Kubernetes интеллектуально управлять трафиком, обеспечивая нулевое время простоя при деплое и устойчивость к временным сбоям зависимостей. Это фундаментальный механизм для построения отказоустойчивых приложений в Kubernetes-окружении.