Как дать понять Kubernetes, что программа запущена и готова?
Комментарии (2)
Ответ сгенерирован нейросетью и может содержать ошибки
Механизмы готовности (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 и рекомендации
- Начинайте с минимальной функциональности: Readiness probe должна проверять только критически важные зависимости
- Избегайте тяжелых операций: Проверка должна выполняться быстро, без нагрузочных запросов к БД или внешним сервисам
- Используйте разные эндпоинты для liveness и readiness проверок
- Настройте правильные тайминги: initialDelaySeconds должен учитывать время инициализации приложения
- Логируйте состояния: Добавляйте логирование при изменении состояния готовности
- Тестируйте отказоустойчивость: Убедитесь, что при временной недоступности зависимостей Pod корректно выводится из балансировки
- Используйте 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-окружении.