Книга Облачная экосистема - читать онлайн бесплатно, автор Евгений Сергеевич Штольц. Cтраница 7
bannerbanner
Вы не авторизовались
Войти
Зарегистрироваться
Облачная экосистема
Облачная экосистема
Добавить В библиотекуАвторизуйтесь, чтобы добавить
Оценить:

Рейтинг: 0

Добавить отзывДобавить цитату

Облачная экосистема

– context:

cluster: gke_essch_europe-north1-a_bitrix

user: gke_essch_europe-north1-a_bitrix

name: gke_essch_europe-north1-a_bitrix

Посмотреть можно примерно подобным образом:

esschtolts@cloudshell:~/bitrix (essch)$ kubectl config view -o jsonpath='{.contexts[4]}'

{gke_essch_europe-north1-a_bitrix {gke_essch_europe-north1-a_bitrix gke_essch_europe-north1-a_bitrix []}}

Создадим новый контекст для данного пользователя и кластера:

esschtolts@cloudshell:~ (essch)$ kubectl config set-context dev \

> –namespace=development \

> –cluster=gke_essch_europe-north1-a_bitrix \

> –user=gke_essch_europe-north1-a_bitrix

Context "dev" modified.


esschtolts@cloudshell:~/bitrix (essch)$ kubectl config set-context dev \

> –namespace=development \

> –cluster=gke_essch_europe-north1-a_bitrix \

> –user=gke_essch_europe-north1-a_bitrix

Context "dev" modified.

В результате был добавлен:

– context:

cluster: gke_essch_europe-north1-a_bitrix

namespace: development

user: gke_essch_europe-north1-a_bitrix

name: dev

Теперь осталось переключиться на него:

esschtolts@cloudshell:~ (essch)$ kubectl config use-context dev

Switched to context "dev".


esschtolts@cloudshell:~ (essch)$ kubectl config current-context

dev


esschtolts@cloudshell:~ (essch)$ kubectl get pods

No resources found.


esschtolts@cloudshell:~ (essch)$ kubectl get pods –namespace=default

NAMEREADY STATUS RESTARTS AGE

Nginxlamp-b5dcb7546-krkm2 1/1 Running 0 10h

Можно было добавить в существующий контекст пространство имён:

esschtolts@cloudshell:~/bitrix (essch)$ kubectl config set-context $(kubectl config current-context) –namespace=development

Context "gke_essch_europe-north1-a_bitrix" modified.

Теперь создадим кластер в новой области видимости dev(она теперь по умолчанию и её можно не указывать –namespace=dev) и удалим из области видимости по умолчанию default (она теперь не по умолчанию для нашего кластера и её нужно указывать –namespace =default):

esschtolts@cloudshell:~ (essch)$ cd bitrix/


esschtolts@cloudshell:~/bitrix (essch)$ kubectl create -f deploymnet.yaml -f loadbalancer.yaml

deployment.apps "Nginxlamp" created

service "frontend" created


esschtolts@cloudshell:~/bitrix (essch)$ kubectl delete -f deploymnet.yaml -f loadbalancer.yaml –namespace=default

deployment.apps "Nginxlamp" deleted

service "frontend" deleted


esschtolts@cloudshell:~/bitrix (essch)$ kubectl get pods

NAMEREADY STATUS RESTARTS AGE

Nginxlamp-b5dcb7546-8sl2f 1/1 Running 0 1m

Теперь посмотрим внешний IP-адресс и откроем страницу:

esschtolts@cloudshell:~/bitrix (essch)$ curl $(kubectl get -f loadbalancer.yaml -o json

| jq -r .status.loadBalancer.ingress[0].ip) 2>/dev/null | grep '< h2 >'

< h2>Welcome to github.com/mattrayner/docker-lamp" target="_blank">Docker-Lamp a.k.a mattrayner/lamp< /h2>

Кастомизация

Теперь нам нужно изменить стандартное решение под наши нужды, а именно добавить конфиги и наше приложение. Для простоты мы пометим (изменим стандартный) в корень нашего приложения файл .htaccess, сведя к простому помещения нашего приложения в папку /app. Первое, что напрашивается сделать, это создать POD и потом скопировать с хоста в контейнер наше приложение (я взял Bitrix):

Хотя это решение и работает, оно имеет ряд существенных недостатков. Первое, что то, что нам нужно дожидаться из вне, постоянным опросом POD, когда он поднимет контейнер и мы в него скопируем приложение и не должен этого делать, если контейнер не поднялся, а также обрабатывать ситуацию когда он сломает наш POD, внешние сервисы, могут опираться на статус POD, хоты сам POD будет ещё не готов, пока не будет выполнен скрипт. Вторым недостатком является то, что у нас появляется какой то внешний скрипт, который нужно логически не отделим от POD, но при этом его нужно вручную запускать из вне, где хранить и где-то должна быть инструкция по его использованию. И напоследок, этих POD у нас может быть множество. На первый взгляд, логичным решением поместить код в Dockerfile:

esschtolts@cloudshell:~/bitrix (essch)$ cat Dockerfile

FROM mattrayner/lamp:latest-1604-php5

MAINTAINER ESSch ESSchtolts@yandex.ru>

RUN cd /app/ && ( \

wget https://www.1c-bitrix.ru/download/small_business_encode.tar.gz \

&& tar -xf small_business_encode.tar.gz \

&& sed -i '5i php_value short_open_tag 1' .htaccess \

&& chmod -R 0777 . \

&& sed -i 's/#php_value display_errors 1/php_value display_errors 1/' .htaccess \

&& sed -i '5i php_value opcache.revalidate_freq 0' .htaccess \

&& sed -i 's/#php_flag default_charset UTF-8/php_flag default_charset UTF-8/' .htaccess \

) && cd ..;

EXPOSE 80 3306

CMD ["/run.sh"]


esschtolts@cloudshell:~/bitrix (essch)$ docker build -t essch/app:0.12 . | grep Successfully

Successfully built f76e656dac53

Successfully tagged essch/app:0.12


esschtolts@cloudshell:~/bitrix (essch)$ docker image push essch/app | grep digest

0.12: digest: sha256:75c92396afacefdd5a3fb2024634a4c06e584e2a1674a866fa72f8430b19ff69 size: 11309


esschtolts@cloudshell:~/bitrix (essch)$ cat deploymnet.yaml

apiVersion: apps/v1

kind: Deployment

metadata:

name: Nginxlamp

namespace: development

spec:

selector:

matchLabels:

app: lamp

replicas: 1

template:

metadata:

labels:

app: lamp

spec:

containers:

– name: lamp

image: essch/app:0.12

ports:

– containerPort: 80


esschtolts@cloudshell:~/bitrix (essch)$ IMAGE=essch/app:0.12 kubectl create -f deploymnet.yaml

deployment.apps "Nginxlamp" created


esschtolts@cloudshell:~/bitrix (essch)$ kubectl get pods -l app=lamp

NAME READY STATUS RESTARTS AGE

Nginxlamp-55f8cd8dbc-mk9nk 1/1 Running 0 5m


esschtolts@cloudshell:~/bitrix (essch)$ kubectl exec Nginxlamp-55f8cd8dbc-mk9nk – ls /app/

index.php

Это происходит потому, что разработчик образов, что правильно и написано в его документации, ожидал, что образ будет примонтирован к хосту и в скрипте запускаемого в сам конце удаляется папка app. Также в таком подходе мы столкнёмся с проблемой постоянных обновлений образов, конфигом (мы не сможем задать номер образа переменной, так как он будет исполняться на нодах кластера) и обновлений контейнеров, также мы не сможем обновлять папку, так как при пересоздании контейнера изменения будут возвращены в изначальное состояние.

Правильным решением будет примонтировать папку и включение в состав жизненно цикла POD запуск контейнера, который стартует перед основным контейнером и производит подготовительные операции окружения, часто это скачивание приложения с репозитория, сборка, прогон тестов, создания пользователей и выставление прав. Под каждую операцию правильно запускать отдельный init контейнер, в котором эта операция является базовым процессом, которые выполняются последовательно – цепочкой, которая будет разорвана, если одна из операций будет выполнена с ошибкой (вернёт не нулевой код завершения процесса). Для такого контейнера предусмотрено отдельное описание в POD – InitContainer, перечисляя их последовательно они будет выстраивать цепочку запусков init контейнеров в том же порядке. В нашем случае мы создали неименованный volume и с помощью InitContainer доставили в него установочные файлы. После успешного завершения InitContainer, которых может быть несколько, стартует основной. Основной контейнер уже монтируется в наш том, в котором уже есть установочные файлы, нам остаётся лишь перейти в браузер и выполнить установку:

esschtolts@cloudshell:~/bitrix (essch)$ cat deploymnet.yaml

kind: Deployment

metadata:

name: Nginxlamp

namespace: development

spec:

selector:

matchLabels:

app: lamp

replicas: 1

template:

metadata:

labels:

app: lamp

spec:

initContainers:

– name: init

image: ubuntu

command:

– /bin/bash

– -c

– |

cd /app

apt-get update && apt-get install -y wget

wget https://www.1c-bitrix.ru/download/small_business_encode.tar.gz

tar -xf small_business_encode.tar.gz

sed -i '5i php_value short_open_tag 1' .htaccess

chmod -R 0777 .

sed -i 's/#php_value display_errors 1/php_value display_errors 1/' .htaccess

sed -i '5i php_value opcache.revalidate_freq 0' .htaccess

sed -i 's/#php_flag default_charset UTF-8/php_flag default_charset UTF-8/' .htaccess

volumeMounts:

– name: app

mountPath: /app

containers:

– name: lamp

image: essch/app:0.12

ports:

– containerPort: 80

volumeMounts:

– name: app

mountPath: /app

volumes:

– name: app

emptyDir: {}

Посмотреть события во время создания POD можно командой watch kubectl get events, а логи kubectl logs {ID_CONTAINER} -c init или более универсально:

kubectl logs $(kubectl get PODs -l app=lamp -o JSON | jq ".items[0].metadata.name" | sed 's/"//g') -c init

Целесообразно выбирать для единичных задач маленькие образа, например, alpine:3.5:

esschtolts@cloudshell:~ (essch)$ docker pull alpine 1>\dev\null

esschtolts@cloudshell:~ (essch)$ docker pull ubuntu 1>\dev\null

esschtolts@cloudshell:~ (essch)$ docker images

REPOSITORY TAGIMAGE ID CREATED SIZE

ubuntu latest 93fd78260bd1 4 weeks ago 86.2MB

alpine latest 196d12cf6ab1 3 months ago 4.41MB

Немного изменив код существенно сэкономили на размере образа:

image: alpine:3.5

command:

– /bin/bash

– -c

– |

cd /app

apk –update add wget && rm -rf /var/cache/apk/*

tar -xf small_business_encode.tar.gz

rm -f small_business_encode.tar.gz

sed -i '5i php_value short_open_tag 1' .htaccess

sed -i 's/#php_value display_errors 1/php_value display_errors 1/' .htaccess

sed -i '5i php_value opcache.revalidate_freq 0' .htaccess

sed -i 's/#php_flag default_charset UTF-8/php_flag default_charset UTF-8/' .htaccess

chmod -R 0777 .

volumeMounts:

Существуют также минималистичные образа с предустановленными пакетами, такие как APIne с git: axeclbr/git и golang:1-alpine.

Способы обеспечения устойчивости к сбоям

Любой процесс может упасть. В случае с контейнером, если падает основной процесс, то падает и контейнер, содержащий его. Это нормально, если падение случилось в процессе корректного завершения работы. К примеру, наше приложение в контейнере делает бэкап базы данных, таком случае после выполнения контейнера мы получаем сделанную работу. Для демонстрации, возьмём команду sleep:

vagrant@ubuntu:~$ sudo docker pull ubuntu > /dev/null

vagrant@ubuntu:~$ sudo docker run -d ubuntu sleep 60

0bd80651c6f97167b27f4e8df675780a14bd9e0a5c3f8e5e8340a98fc351bc64


vagrant@ubuntu:~$ sudo docker ps

CONTAINER ID IMAGE COMMAND CREATED STATUS NAMES

0bd80651c6f9 ubuntu "sleep 60" 15 seconds ago Up 12 seconds distracted_kalam


vagrant@ubuntu:~$ sleep 60


vagrant@ubuntu:~$ sudo docker ps

CONTAINER ID IMAGE COMMAND CREATED STATUS NAMES


vagrant@ubuntu:~$ sudo docker ps -a | grep ubuntu

0bd80651c6f9 ubuntu "sleep 60" 4 minutes ago Exited (0) 3 minutes ago distracted_kalam

В случае с бэкапам – это норма, а в случае с приложениями, которые не должны завершаться – нет. Типичный прием – веб-сервер. Самое простое в таком случае заново рестартовать его:

vagrant@ubuntu:~$ sudo docker run -d –restart=always ubuntu sleep 10

c3bc2d2e37a68636080898417f5b7468adc73a022588ae073bdb3a5bba270165


vagrant@ubuntu:~$ sleep 30


vagrant@ubuntu:~$ sudo docker ps

CONTAINER ID IMAGE COMMAND CREATED STATUS

c3bc2d2e37a6 ubuntu sleep 10" 46 seconds ago Up 1 second

Мы видим, что, когда контейнер падает – он рестартует. Как результат – у нас всегда приложение в двух состояниях – поднимается или поднято. Если веб-сервер падает от какой-то редкой ошибки – это норма, но, скорее всего, ошибка в обработке запросов, и он будет падать на каждом таком запросе, а в мониторинге мы увидим поднятый контейнер. Такой веб-сервер лучше мёртвый, чем наполовину живой. Но, при этом нормальный веб-сервер может не стартануть из-за редких ошибок, например, из-за отсутствия подключения к базе данных из-за нестабильности сети. В таком случает, приложение должно уметь обрабатывать ошибки и завершаться. А в случае падения из-за ошибок кода – не перезапускать, чтобы увидеть неработоспособность и отправить на починку разработчикам. В случает же плавающей ошибки можно попробовать несколько раз:

vagrant@ubuntu:~$ sudo docker run -d –restart=on-failure:3 ubuntu sleep 10

056c4fc6986a13936e5270585e0dc1782a9246f01d6243dd247cb03b7789de1c

vagrant@ubuntu:~$ sleep 10

vagrant@ubuntu:~$ sudo docker ps

CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES

c3bc2d2e37a6 ubuntu "sleep 10" 9 minutes ago Up 2 seconds keen_sinoussi

vagrant@ubuntu:~$ sleep 10

vagrant@ubuntu:~$ sleep 10

vagrant@ubuntu:~$ sudo docker ps

CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES

c3bc2d2e37a6 ubuntu "sleep 10" 10 minutes ago Up 9 seconds keen_sinoussi

vagrant@ubuntu:~$ sleep 10

vagrant@ubuntu:~$ sudo docker ps

CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES

c3bc2d2e37a6 ubuntu "sleep 10" 10 minutes ago Up 2 seconds keen_sinoussi

Другим аспектом является то, когда считать контейнер умершим. По умолчанию – это падание процесса. Но, далеко, не всегда приложение само падает в случае ошибки, чтобы дать контейнеру его перезапустить. Например, сервер может быть разработан неправильно и пытаться во время своего запуска скачать необходимые библиотеки, при этом этой возможности у него нет, например, из-за блокировки запросов файрволлом. В таком сценарии сервер может долго ожидать, если не прописан адекватный таймаут. В таком случае, нам нужно проверить работоспособность. Для веб-сервера это ответ на определённый url, например:

docker run –rm -d \

–-name=elasticsearch \

–-health-cmd="curl –silent –fail localhost:9200/_cluster/health || exit 1" \

–-health-interval=5s \

–-health-retries=12 \

–-health-timeout=20s \

{image}

Для демонстрации мы возьмём команду создания файла. Если приложение не достигло в отведённый лимит времени (поставим пок 0) рабочего состояния (к примеру, создания файла), то помечается как на рабочее, но до этого делается заданное кол-во проверок:

vagrant@ubuntu:~$ sudo docker run \

–d –name healt \

–-health-timeout=0s \

–-health-interval=5s \

–-health-retries=3 \

–-health-cmd="ls /halth" \

ubuntu bash -c 'sleep 1000'

c0041a8d973e74fe8c96a81b6f48f96756002485c74e51a1bd4b3bc9be0d9ec5


vagrant@ubuntu:~$ sudo docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES

c0041a8d973e ubuntu "bash -c 'sleep 1000'" 4 seconds ago Up 3 seconds (health: starting) healt


vagrant@ubuntu:~$ sleep 20

vagrant@ubuntu:~$ sudo docker ps

CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES

c0041a8d973e ubuntu "bash -c 'sleep 1000'" 38 seconds ago Up 37 seconds (unhealthy) healt


vagrant@ubuntu:~$ sudo docker rm -f healt

healt

Если же хотя бы одна из проверок сработала – то контейнер помечается как работоспособный (healthy) сразу:

vagrant@ubuntu:~$ sudo docker run \

–d –name healt \

–-health-timeout=0s \

–-health-interval=5s \

–-health-retries=3 \

–-health-cmd="ls /halth" \

ubuntu bash -c 'touch /halth && sleep 1000'


vagrant@ubuntu:~$ sudo docker ps

CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES

160820d11933 ubuntu "bash -c 'touch /hal…" 4 seconds ago Up 2 seconds (health: starting) healt

vagrant@ubuntu:~$ sudo docker ps

CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES

160820d11933 ubuntu "bash -c 'touch /hal…" 6 seconds ago Up 5 seconds (healthy) healt


vagrant@ubuntu:~$ sudo docker rm -f healt

healt

При этом проверки повторяются всё время с заданным интервалом:

vagrant@ubuntu:~$ sudo docker run \

–d –name healt \

–-health-timeout=0s \

–-health-interval=5s \

–-health-retries=3 \

–-health-cmd="ls /halth" \

ubuntu bash -c 'touch /halth && sleep 60 && rm -f /halth && sleep 60'


vagrant@ubuntu:~$ sudo docker ps

CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES

8ec3a4abf74b ubuntu "bash -c 'touch /hal…" 7 seconds ago Up 5 seconds (health: starting) healt

vagrant@ubuntu:~$ sudo docker ps

CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES

8ec3a4abf74b ubuntu "bash -c 'touch /hal…" 24 seconds ago Up 22 seconds (healthy) healt

vagrant@ubuntu:~$ sleep 60

vagrant@ubuntu:~$ sudo docker ps

CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES

8ec3a4abf74b ubuntu "bash -c 'touch /hal…" About a minute ago Up About a minute (unhealthy) healt

Kubernetes предоставляет (kubernetes.io/docs/tasks/configure-POD-container/configure-liveness-readiness-probes/) три инструмента, которые проверяют состояние контейнера из вне. Они имеют больше значение, так они служат не только для информирования, но и для управления жизненным циклом приложения, накатом и откатом обновления. Их неправильная настройка может, и часто такое бывает, приводят к неработоспособности приложения. Так, к если liveness проба буте срабатывать до начала работы приложения – Kubernetes будет убивать контейнер, не дав ему подняться. Рассмотрим её более подробно. Проба liveness служит для определения работоспособности приложения и в случае, если приложение сломалось и не отвечает на пробу liveness – Kubernetes перезагружает контейнер. В качестве примера возьмём shell-пробу, из-за простоты демонстрации работы, но на практике её следует использовать только в крайних случаях, например, если контейнер запускается не как долгоживущий сервер, а как JOB, выполняющий свою работу и завершающий своё существование, достигнув результата. Для проверок серверов лучше использовать HTTP-пробы, которые уже имеют встроенный выделенный проксировщик и не требуют наличия в контейнере curl и не зависящие от внешних настроек kube-proxy. При использовании баз данных нужно использовать TCP-пробу, так как HTTP—протокол они обычно не поддерживают. Создадим долгоживущий контейнер в www.katacoda.com/courses/kubernetes/playground:

controlplane $ cat << EOF > liveness.yaml

apiVersion: v1

kind: Pod

metadata:

name: liveness

spec:

containers:

– name: healtcheck

image: alpine:3.5

args:

– /bin/sh

– -c

– touch /tmp/healthy; sleep 10; rm -rf /tmp/healthy; sleep 60

livenessProbe:

exec:

command:

– cat

– /tmp/healthy

initialDelaySeconds: 15

periodSeconds: 5

EOF


controlplane $ kubectl create -f liveness.yaml

pod/liveness created


controlplane $ kubectl get pods

NAME READY STATUS RESTARTS AGE

liveness 1/1 Running 2 2m11s


controlplane $ kubectl describe pod/liveness | tail -n 10

Type Reason Age From Message

–– – – – –

Normal Scheduled 2m37s default-scheduler Successfully assigned default/liveness to node01

Normal Pulling 2m33s kubelet, node01 Pulling image "alpine:3.5"

Normal Pulled 2m30s kubelet, node01 Successfully pulled image "alpine:3.5"

Normal Created 33s (x3 over 2m30s) kubelet, node01 Created container healtcheck

Normal Started 33s (x3 over 2m30s) kubelet, node01 Started container healtcheck

Normal Pulled 33s (x2 over 93s) kubelet, node01 Container image "alpine:3.5" already present on machine

Warning Unhealthy 3s (x9 over 2m13s) kubelet, node01 Liveness probe failed: cat: can't open '/tmp/healthy': No such file or directory

Normal Killing 3s (x3 over 2m3s) kubelet, node01 Container healtcheck failed liveness probe, will be restarted

Мы видим, что контейнер постоянно перезапускается.

controlplane $ cat << EOF > liveness.yaml

apiVersion: v1

kind: Pod

metadata:

name: liveness

spec:

containers:

– name: healtcheck

image: alpine:3.5

args:

– /bin/sh

– -c

– touch /tmp/healthy; sleep 30; rm -rf /tmp/healthy; sleep 60

livenessProbe:

exec:

command:

– cat

– /tmp/healthy

initialDelaySeconds: 15

periodSeconds: 5

EOF


controlplane $ kubectl create -f liveness.yaml

pod/liveness created


controlplane $ kubectl get pods

NAME READY STATUS RESTARTS AGE

liveness 1/1 Running 2 2m53s


controlplane $ kubectl describe pod/liveness | tail -n 15

SecretName: default-token-9v5mb

Optional: false

QoS Class: BestEffort

Node-Selectors: < none>

Tolerations: node.kubernetes.io/not-ready:NoExecute for 300s

node.kubernetes.io/unreachable:NoExecute for 300s

Events:

Type Reason Age From Message

–– – – – –

Normal Scheduled 3m44s default-scheduler Successfully assigned default/liveness to node01

Normal Pulled 68s (x3 over 3m35s) kubelet, node01 Container image "alpine:3.5" already present on machine

Normal Created 68s (x3 over 3m35s) kubelet, node01 Created container healtcheck

Normal Started 68s (x3 over 3m34s) kubelet, node01 Started container healtcheck

Warning Unhealthy 23s (x9 over 3m3s) kubelet, node01 Liveness probe failed: cat: can't open '/tmp/healthy': No such file or directory

Normal Killing 23s (x3 over 2m53s) kubelet, node01 Container healtcheck failed liveness probe, will be restarted

Также мы видим и на событиях кластера, что когда cat /tmp/health терпит неудачу – контейнере пересоздаётся:

controlplane $ kubectl get events


controlplane $ kubectl get events | grep pod/liveness

13m Normal Scheduled pod/liveness Successfully assigned default/liveness to node01

13m Normal Pulling pod/liveness Pulling image "alpine:3.5"

13m Normal Pulled pod/liveness Successfully pulled image "alpine:3.5"

10m Normal Created pod/liveness Created container healtcheck

10m Normal Started pod/liveness Started container healtcheck

10m Warning Unhealthy pod/liveness Liveness probe failed: cat: can't open '/tmp/healthy': No such file or directory

10m Normal Killing pod/liveness Container healtcheck failed liveness probe, will be restarted

10m Normal Pulled pod/liveness Container image "alpine:3.5" already present on machine

8m32s Normal Scheduled pod/liveness Successfully assigned default/liveness to node01

4m41s Normal Pulled pod/liveness Container image "alpine:3.5" already present on machine

4m41s Normal Created pod/liveness Created container healtcheck

4m41s Normal Started pod/liveness Started container healtcheck

2m51s Warning Unhealthy pod/liveness Liveness probe failed: cat: can't open '/tmp/healthy': No such file or directory

5m11s Normal Killing pod/liveness Container healtcheck failed liveness probe, will be restarted

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

controlplane $ cat << EOF > readiness.yaml

apiVersion: apps/v1

kind: Deployment

metadata:

name: readiness

spec:

replicas: 2

selector:

matchLabels:

app: readiness

template:

metadata:

labels:

app: readiness

spec:

containers:

– name: readiness

image: python

args:

– /bin/sh

– -c

– sleep 15 && (hostname > health) && python -m http.server 9000

readinessProbe:

exec:

command:

– cat

– /tmp/healthy

initialDelaySeconds: 1

periodSeconds: 5

EOF


controlplane $ kubectl create -f readiness.yaml

deployment.apps/readiness created


controlplane $ kubectl get pods

NAME READY STATUS RESTARTS AGE

readiness-fd8d996dd-cfsdb 0/1 ContainerCreating 0 7s

readiness-fd8d996dd-sj8pl 0/1 ContainerCreating 0 7s


controlplane $ kubectl get pods

NAME READY STATUS RESTARTS AGE

readiness-fd8d996dd-cfsdb 0/1 Running 0 6m29s

readiness-fd8d996dd-sj8pl 0/1 Running 0 6m29s


controlplane $ kubectl exec -it readiness-fd8d996dd-cfsdb – curl localhost:9000/health

readiness-fd8d996dd-cfsdb