«1. Введение

В этом руководстве мы поговорим о зондах Kubernetes и продемонстрируем, как мы можем использовать HealthIndicator Actuator, чтобы получить точное представление о состоянии нашего приложения.

Для целей этого руководства мы предполагаем, что у нас уже есть опыт работы с Spring Boot Actuator, Kubernetes и Docker.

2. Зонды Kubernetes

Kubernetes определяет два разных зонда, которые мы можем использовать для периодической проверки того, все ли работает должным образом: живость и готовность.

2.1. Liveness and Readiness

С помощью тестов Liveness и Readiness Kubelet может действовать, как только обнаружит, что что-то не так, и свести к минимуму время простоя нашего приложения.

Оба настроены одинаково, но имеют разную семантику, и Kubelet выполняет разные действия в зависимости от того, какое из них срабатывает:

    Готовность — Готовность проверяет, готов ли наш под начать получать трафик. Наш под готов, когда готовы все его контейнеры. Живучесть — в отличие от готовности, живость проверяет, следует ли перезапустить наш под. Он может выбрать варианты использования, когда наше приложение работает, но находится в состоянии, когда оно не может развиваться; например, он находится в тупике

Мы настраиваем оба типа зондов на уровне контейнера:

apiVersion: v1
kind: Pod
metadata:
  name: goproxy
  labels:
    app: goproxy
spec:
  containers:
  - name: goproxy
    image: k8s.gcr.io/goproxy:0.1
    ports:
    - containerPort: 8080
    readinessProbe:
      tcpSocket:
        port: 8080
      initialDelaySeconds: 5
      periodSeconds: 10
      timeoutSeconds: 2
      failureThreshold: 1
      successThreshold: 1
    livenessProbe:
      tcpSocket:
        port: 8080
      initialDelaySeconds: 15
      periodSeconds: 20
      timeoutSeconds: 2
      failureThreshold: 1
      successThreshold: 1

Существует ряд полей, которые мы можем настроить для более точного управления поведением наших зондов:

    initialDelaySeconds â – После создания контейнера подождите n секунд перед запуском зонда. periodSeconds – как часто следует запускать этот зонд, по умолчанию 10 секунд; минимальное значение равно 1 секунде. timeoutSeconds — сколько мы ждем перед истечением времени проверки, по умолчанию 1 секунда; минимум снова равен 1 секунде. Порог отказа — попробуйте n раз, прежде чем сдаться. В случае готовности наш под будет помечен как не готовый, тогда как отказ в случае живости означает перезапуск пода. Значение по умолчанию здесь равно 3 сбоям, минимальное значение равно 1 SuccessThreshold. Это минимальное количество последовательных успешных попыток, при котором зонд считается успешным после сбоя. По умолчанию он равен 1 успеху, и его минимум также равен 1

В этом случае мы выбрали tcp-зонд, однако есть и другие типы зондов, которые мы можем использовать.

2.2. Типы зондов

В зависимости от нашего варианта использования один тип зонда может оказаться более полезным, чем другой. Например, если наш контейнер представляет собой веб-сервер, использование пробы http может быть более надежным, чем проба tcp.

К счастью, в Kubernetes есть три различных типа зондов, которые мы можем использовать:

    exec — выполняет инструкции bash в нашем контейнере. Например, проверьте, существует ли определенный файл. Если инструкция возвращает код ошибки, зонд терпит неудачу. tcpSocket — пытается установить tcp-соединение с контейнером, используя указанный порт. Если не удается установить соединение, зонд завершается ошибкой httpGet — отправляет HTTP-запрос GET на сервер, работающий в контейнере и прослушивающий указанный порт. Любой код больше или равен 200 и меньше 400 указывает на успех

Важно отметить, что HTTP-запросы имеют дополнительные поля, помимо упомянутых ранее:

    хост — имя хоста для подключения, по умолчанию используется наш IP-схема модуля — схема, которая должна использоваться для подключения, HTTP или HTTPS, по умолчанию — HTTP-путь — путь доступа к веб-серверу httpHeaders — настраиваемые заголовки для установки в порте запроса — Имя или номер порта для доступа в контейнере

3. Spring Actuator и возможности самовосстановления Kubernetes

Теперь, когда у нас есть общее представление о том, как Kubernetes может определить, находится ли наше приложение в неисправном состоянии, давайте посмотрим, как мы можем использовать Spring Actuator, чтобы внимательно следить не только за нашим приложением, но и за его зависимостями!

В этих примерах мы будем полагаться на Minikube.

3.1. Актуатор и его индикаторы работоспособности

«Учитывая, что Spring имеет ряд готовых к использованию индикаторов HealthIndicators, отражение состояния некоторых зависимостей нашего приложения от зондов Kubernetes так же просто, как добавление зависимости Actuator в наш pom.xml:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

3.2. Пример живучести

Начнем с приложения, которое загружается нормально и через 30 секунд переходит в неисправное состояние.

Мы собираемся эмулировать неисправное состояние, создав HealthIndicator, который проверяет, является ли логическая переменная истинной. Мы инициализируем переменную значением true, а затем запланируем задачу, чтобы через 30 секунд изменить ее значение на false: ~ Затем мы создаем наш шаблон Kubernetes:

@Component
public class CustomHealthIndicator implements HealthIndicator {

    private boolean isHealthy = true;

    public CustomHealthIndicator() {
        ScheduledExecutorService scheduled =
          Executors.newSingleThreadScheduledExecutor();
        scheduled.schedule(() -> {
            isHealthy = false;
        }, 30, TimeUnit.SECONDS);
    }

    @Override
    public Health health() {
        return isHealthy ? Health.up().build() : Health.down().build();
    }
}

Мы используем зонд httpGet, указывающий на конечную точку работоспособности Actuator. Любое изменение состояния нашего приложения (и его зависимостей) будет отражаться на работоспособности нашего развертывания.

FROM openjdk:8-jdk-alpine
RUN mkdir -p /usr/opt/service
COPY target/*.jar /usr/opt/service/service.jar
EXPOSE 8080
ENTRYPOINT exec java -jar /usr/opt/service/service.jar

После развертывания нашего приложения в Kubernetes мы сможем увидеть оба зонда в действии: примерно через 30 секунд наш под будет помечен как неготовый и удален из ротации; через несколько секунд Pod перезапускается.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: liveness-example
spec:
  ...
    spec:
      containers:
      - name: liveness-example
        image: dbdock/liveness-example:1.0.0
        ...
        readinessProbe:
          httpGet:
            path: /health
            port: 8080
          initialDelaySeconds: 10
          timeoutSeconds: 2
          periodSeconds: 3
          failureThreshold: 1
        livenessProbe:
          httpGet:
            path: /health
            port: 8080
          initialDelaySeconds: 20
          timeoutSeconds: 2
          periodSeconds: 8
          failureThreshold: 1

Мы можем видеть, как события нашего модуля, выполняющего kubectl, описывают живость модуля: пример:

3.3. Пример готовности

В предыдущем примере мы видели, как можно использовать HealthIndicator для отражения состояния нашего приложения в отношении работоспособности развертывания Kubernetes.

Warning  Unhealthy 3s (x2 over 7s)   kubelet, minikube  Readiness probe failed: HTTP probe failed ...
Warning  Unhealthy 1s                kubelet, minikube  Liveness probe failed: HTTP probe failed ...
Normal   Killing   0s                kubelet, minikube  Killing container with id ...

Давайте использовать его в другом случае: предположим, что нашему приложению требуется некоторое время, прежде чем оно сможет получать трафик. Например, ему нужно загрузить файл в память и проверить его содержимое.

Это хороший пример того, когда мы можем воспользоваться проверкой готовности.

Давайте изменим шаблон HealthIndicator и Kubernetes из предыдущего примера и адаптируем их к этому варианту использования:

Мы инициализируем переменную значением false, и через 40 секунд будет выполнена задача, установившая для нее значение true.

Затем мы докеризуем и развертываем наше приложение, используя следующий шаблон:

@Component
public class CustomHealthIndicator implements HealthIndicator {

    private boolean isHealthy = false;

    public CustomHealthIndicator() {
        ScheduledExecutorService scheduled =
          Executors.newSingleThreadScheduledExecutor();
        scheduled.schedule(() -> {
            isHealthy = true;
        }, 40, TimeUnit.SECONDS);
    }

    @Override
    public Health health() {
        return isHealthy ? Health.up().build() : Health.down().build();
    }
}

Несмотря на то, что это похоже, есть несколько изменений в конфигурации зондов, на которые нам нужно указать:

Поскольку мы знаем, что наше приложение требуется около 40 секунд, чтобы стать готовым к приему трафика, мы увеличили initialDelaySeconds нашего зонда готовности до 40 секунд. Точно так же мы увеличили initialDelaySeconds нашего зонда живучести до 100 секунд, чтобы избежать преждевременного уничтожения Kubernetes

apiVersion: apps/v1
kind: Deployment
metadata:
  name: readiness-example
spec:
  ...
    spec:
      containers:
      - name: readiness-example
        image: dbdock/readiness-example:1.0.0
        ...
        readinessProbe:
          httpGet:
            path: /health
            port: 8080
          initialDelaySeconds: 40
          timeoutSeconds: 2
          periodSeconds: 3
          failureThreshold: 2
        livenessProbe:
          httpGet:
            path: /health
            port: 8080
          initialDelaySeconds: 100
          timeoutSeconds: 2
          periodSeconds: 8
          failureThreshold: 1

Если он все еще не t закончился через 40 секунд, у него еще есть около 60 секунд, чтобы закончить. После этого наш зонд живости сработает и перезапустит под.

    4. Заключение

В этой статье мы говорили о зондах Kubernetes и о том, как мы можем использовать Spring Actuator для улучшения мониторинга работоспособности нашего приложения.

Полную реализацию этих примеров можно найти на Github.

«

The full implementation of these examples can be found over on Github.