K8s Q A Shell Operator: различия между версиями
Sirmax (обсуждение | вклад) (→11) |
Sirmax (обсуждение | вклад) |
||
| Строка 19: | Строка 19: | ||
=Как это сделать= |
=Как это сделать= |
||
| + | Идея такая - на основании shell-operator написать свой скрипт, который подписывается на события в кластере, и при появлении нужного POD сохранит логи в доступном месте. |
||
| + | <BR> |
||
| + | В целом довольно костыльно - но задачу решает |
||
==Shell-Operator== |
==Shell-Operator== |
||
Shell-оператор это фреймворк для написания своих операторов на shell или python |
Shell-оператор это фреймворк для написания своих операторов на shell или python |
||
Версия 19:49, 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