K8s Q A Shell Operator: различия между версиями
Sirmax (обсуждение | вклад) |
Sirmax (обсуждение | вклад) |
||
Строка 134: | Строка 134: | ||
FROM ghcr.io/flant/shell-operator:latest |
FROM ghcr.io/flant/shell-operator:latest |
||
ADD hooks /hooks |
ADD hooks /hooks |
||
+ | </PRE> |
||
+ | ===Build=== |
||
+ | Удалить старый, пересобрать заново, пушнуть на докерхаб |
||
+ | <PRE> |
||
+ | !/bin/bash |
||
+ | |||
+ | set -ex |
||
+ | |||
+ | for i in $(docker image ls | grep sirmax123/shell-operator-test | awk '{ print $3}'); |
||
+ | do |
||
+ | docker image rm ${i} |
||
+ | done |
||
+ | |||
+ | docker build . -t sirmax123/shell-operator-test:1 |
||
+ | docker push sirmax123/shell-operator-test:1 |
||
</PRE> |
</PRE> |
Версия 19:54, 11 января 2024
Shell Operator
https://habr.com/ru/companies/flant/articles/447442/
Что нужно сделать
Есть cron-job которая
- Падает время от времени (но не всегда, а скорее редко)
- Подчищает за собой POD
- Хочется найти упавший под и собрать с него логи ДО того как под будет удален
- Не хочется сидеть и ждать такой под
- Доступа к централизованной системе логгирования нет (так бывает - логи пишутся централизованно в корпоративную систему)
Как это сделать
Идея такая - на основании shell-operator написать свой скрипт, который подписывается на события в кластере, и при появлении нужного POD сохранит логи в доступном месте.
В целом довольно костыльно - но задачу решает
Shell-Operator
Shell-оператор это фреймворк для написания своих операторов на shell или python
Hook
Для обработки событий использую вот такой скрипт, при запуске с параметром --config
он должен выдать описания событий на которые нужно подписаться,
при запуске без параметров ему передается (чеерз переменную окружения ${BINDING_CONTEXT_PATH}
путь к файлу который содержит данные события
#!/usr/bin/env bash NAMESPACE="stacklight" POD_NAME="elasticsearch-curator" # Эта часть кода запускается при старте оператора, и # определяет на какие именно события будет подписываться этот скрипт # В частности - в каком именно неймспейсе if [[ $1 == "--config" ]] ; then cat <<EOF { "configVersion":"v1", "kubernetes":[ { "apiVersion": "events.k8s.io/v1", "kind": "Event", "namespace": { "nameSelector": { "matchNames": ["${NAMESPACE}"] } }, "fieldSelector": { "matchExpressions": [ { "field": "metadata.namespace", "operator": "Equals", "value": "${NAMESPACE}" } ] } } ] } EOF else # Сохранить содержимое BINDING_CONTEXT (для последующего анализа) cat "${BINDING_CONTEXT_PATH}" >> /tmp/log2 echo "" echo "[events-hook.sh] Starting HOOK" echo "[events-hook.sh] ------------------------------------------" # Вывести в лог (лог пода) cat "${BINDING_CONTEXT_PATH}" echo "[events-hook.sh] " type=$(jq -r '.[0].type' ${BINDING_CONTEXT_PATH}) echo "[events-hook.sh] ------------------------------------------" echo "[events-hook.sh] TYPE=${type}" echo "------------------------------------------" if [[ $type == "Event" ]] ; then echo "[events-hook.sh] Got Event: " echo "[events-hook.sh] ------------------------------------------" jq '.[0].object' ${BINDING_CONTEXT_PATH} echo "[events-hook.sh] ------------------------------------------" podName=$(jq -r '.[0].object.metadata.name' $BINDING_CONTEXT_PATH) echo "[events-hook.sh] Pod Name: '${podName}'" echo "[events-hook.sh] ------------------------------------------" else echo "DATA: ${BINDING_CONTEXT_PATH}" >> /tmp/log fi #jq -r '.[0].object.note' ${BINDING_CONTEXT_PATH} >> /tmp/note.log note=$(jq -r '.[0].object.note' ${BINDING_CONTEXT_PATH}) echo "[events-hook.sh] ------------------------------------------" echo "[events-hook.sh] Got note: ${note}" echo "[events-hook.sh] ------------------------------------------" # Возможно на первой иттерации под не успеет стартовать, но # если он упадет, то его логи будут получены при следующем запуске # Cron Job if [[ "${note}" == "Started container ${POD_NAME}" ]]; then D=$(date +%Y%m%d-%H%M%S) kubectl get pod | grep "${POD_NAME}"| grep -vE "Completed|Running|Pending|ContainerCreating" >> /tmp/list_pods_${D} for failedPod in $(kubectl get pod | grep "${POD_NAME}" | grep -vE "Completed|Running|Pending|ContainerCreating" | awk '{ print $1 }' ); do # Найти под и вывести в логи его описание, дескрайб и логи echo "[events-hook.sh] Found failed POD: ${failedPod}" describeFailedPod=$(kubectl describe pod ${failedPod}) echo "[events-hook.sh] POD Describe: ${describeFailedPod}" echo "${describeFailedPod}" > /tmp/${failedPod}_describe_${D} getFailedPodYaml=$(kubectl get pod ${failedPod} -o yaml) echo "[events-hook.sh] POD Definition: ${getFailedPodYaml}" echo "${getFailedPodYaml}" > /tmp/${failedPod}_yaml_${D} failedPodLogs=$(kubectl \ logs -f ${failedPod} \ --all-containers 2>&1) echo "${failedPodLogs}" > /tmp/${failedPod}_logs_${D} echo "[events-hook.sh] POD Logs: ${failedPodLogs}" done fi fi
Сборка образа
Dockerfile
Так-как это только оператор для единоразовой задачи - все максимально просто, помещаем скрипт в директорию hooks
и все
FROM ghcr.io/flant/shell-operator:latest ADD hooks /hooks
Build
Удалить старый, пересобрать заново, пушнуть на докерхаб
!/bin/bash set -ex for i in $(docker image ls | grep sirmax123/shell-operator-test | awk '{ print $3}'); do docker image rm ${i} done docker build . -t sirmax123/shell-operator-test:1 docker push sirmax123/shell-operator-test:1