1. Введение
В этом руководстве мы поговорим о зондах Kubernetes и
продемонстрируем, как мы можем использовать HealthIndicator Actuator для
получения
точного представления о состоянии нашего приложения. **** **[
](https://docs.spring.io/spring-boot/docs/current/api/org/springframework/boot/actuate/health/HealthIndicator.html)**
Для целей этого руководства мы предполагаем, что у нас уже есть опыт работы с Spring
Boot
Actuator
, Kubernetes
и Docker
.
2. Зонды Kubernetes
Kubernetes
определяет два разных зонда, которые мы можем использовать для периодической проверки, все ли работает должным образом: живость
и готовность
.
2.1. Живучесть и готовность
Благодаря зондам Liveness
и Readiness
Kubelet
может действовать, как только обнаружит, что что-то не так, и свести к минимуму время простоя нашего приложения.
Оба настроены одинаково, но имеют разную семантику, и Kubelet
выполняет разные действия в зависимости от того, какое из них срабатывает:
Готовность
—Готовность
проверяет , готов ли наш модуль начать получать трафик.
НашPod
готов
, когда готовы все его контейнеры.Живучесть
— в отличие отготовности
,живость
проверяет, следует ли перезапустить нашпод .
Он может выбрать варианты использования, когда наше приложение работает, но находится в состоянии, когда оно не может развиваться; например, он в тупике
Мы настраиваем оба типа зонда на уровне контейнера:
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 секундаfailureThreshold
— попробуйтеn
раз, прежде чем сдаться . В случаеготовности
наш под будет помечен как не готовый, тогда как отказ в случаеживости
означает перезапускпода
. По умолчанию здесь 3 сбоя, минимум 1.SuccessThreshold
— это минимальное количество последовательных успешных попыток проверки, которые считаются успешными после неудачной попытки . По умолчанию он равен 1 успеху, и его минимум также равен 1.
В данном случае мы выбрали TCP
- зонд, однако мы можем использовать и другие типы зондов.
2.2. Типы зондов
В зависимости от нашего варианта использования один тип зонда может оказаться более полезным, чем другой. Например, если наш контейнер представляет собой веб-сервер, использование пробы http
может быть более надежным, чем проба tcp .
К счастью, в Kubernetes
есть три разных типа зондов, которые мы можем использовать:
exec
— выполняет инструкцииbash
в нашем контейнере . Например, проверьте, существует ли определенный файл. Если инструкция возвращает код ошибки, зонд не работает.tcpSocket
— пытается установитьtcp
-соединение с контейнером, используя указанный порт . Если не удается установить соединение, зонд не работает.httpGet
— отправляет HTTP-запрос GET на сервер , работающий в контейнере и прослушивающий указанный порт. Любой код больше или равен 200 и меньше 400 указывает на успех
Важно отметить, что HTTP
- запросы имеют дополнительные поля, помимо тех, о которых мы упоминали ранее:
host
— имя хоста для подключения, по умолчанию IP-адрес нашего модуля.схема
— схема, которая должна использоваться для подключения,HTTP
илиHTTPS
, по умолчанию —HTTP .
path
— путь доступа на веб-сервереhttpHeaders
— настраиваемые заголовки для установки в запросе.port
— имя или номер порта для доступа в контейнере
3. Spring Actuator и возможности самовосстановления Kubernetes
Теперь, когда у нас есть общее представление о том, как Kubernetes может определить, находится ли наше приложение в неисправном
состоянии , давайте посмотрим, как мы можем использовать Actuator Spring, чтобы
внимательно следить не только за нашим приложением, но и за его зависимостями! ** ** `` ****
В этих примерах мы будем полагаться на Minikube
.
3.1. Актуатор и его индикаторы работоспособности
Учитывая, что Spring имеет ряд готовых к использованию HealthIndicator
, отражение состояния некоторых зависимостей нашего приложения от зондов Kubernetes
так же просто, как добавление зависимости Actuator
в наш pom.xml:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
3.2. Пример живости
Начнем с приложения, которое загрузится нормально и через 30 секунд перейдет в неисправное состояние . ** ** ** **
Мы собираемся эмулировать неисправное состояние, создав HealthIndicator
, который проверяет, является ли логическая
переменная истинной
. Мы инициализируем переменную значением true
, а затем запланируем задачу, чтобы изменить ее на значение false
через 30 секунд:
@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();
}
}
Имея HealthIndicator
, нам нужно докеризовать наше приложение:
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
:
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
Мы используем зонд httpGet
, указывающий на конечную точку работоспособности Actuator
. Любое изменение состояния нашего приложения (и его зависимостей) будет отражаться на работоспособности нашего развертывания.
После развертывания нашего приложения в Kubernetes
мы сможем увидеть оба зонда в действии: примерно через 30 секунд наш Pod
будет помечен как неготовый и снят с ротации; через несколько секунд Pod
перезапускается.
Мы можем видеть, как события нашего модуля,
выполняющего kubectl ,
описывают
pod
liveness-example
:
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 ...
3.3. Пример готовности
В предыдущем примере мы увидели, как можно использовать HealthIndicator
для отражения состояния нашего приложения в отношении работоспособности развертывания Kubernetes
.
Давайте использовать его в другом случае: предположим, что нашему приложению требуется некоторое время , прежде чем оно сможет получать трафик . Например, ему нужно загрузить файл в память и проверить его содержимое. ** ** ** ** ** ** ****
Это хороший пример того, когда мы можем воспользоваться проверкой готовности
.
Давайте изменим шаблон HealthIndicator
и Kubernetes
из предыдущего примера и адаптируем их к этому варианту использования:
@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();
}
}
Мы инициализируем переменную значением false
, и через 40 секунд будет выполнена задача, установившая для нее значение true.
Затем мы докеризуем и развертываем наше приложение, используя следующий шаблон:
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
Несмотря на схожесть, в конфигурации датчиков есть несколько изменений, на которые следует обратить внимание:
- Поскольку мы знаем, что нашему приложению требуется около 40 секунд, чтобы подготовиться к приему трафика, мы увеличили
initialDelaySeconds
нашего тестаготовности
до 40 секунд . - Точно так же мы увеличили
initialDelaySeconds
нашеготеста живучести
до 100 секунд, чтобы избежать преждевременного уничтоженияKubernetes .
``
Если он все еще не закончился через 40 секунд, у него еще есть около 60 секунд, чтобы закончить. После этого наш зонд живости
сработает и перезапустит под.
4. Вывод
В этой статье мы говорили о зондах Kubernetes
и о том, как мы можем использовать Spring Actuator
для улучшения мониторинга работоспособности нашего приложения.
Полную реализацию этих примеров можно найти на Github .