Привет, меня зовут Саша Опрышко, я управляющий партнер в KTS.
В июле мы с Yandex Cloud провели K8s Challenge. На его основе запустили конкурс для всех, кто не успел поучаствовать в челлендже вживую.
Мы уже определили самых быстрых участников и составили рейтинг победителей, которые получат призовой мерч:
Список победителей
1. Dan aka @bratushkadan: 5 мин 6 сек
2. Alexandr Negashev aka @negashev: 5 мин 32 сек
3. Kairzhan Aubekerov aka @kaubekerov: 5 мин 45 сек
4. Соня aka @468***: 7 мин 6 сек
5. Timur aka @TimurKuzmin: 7 мин 42 сек
6. Alex Sharov aka @kvendingoldo: 8m 46s
7. Евгений Романов aka @nothing011235: 9m 37s
8. Sergey aka @ex_trim: 10m 12s
9. dmitriy aka @litrich: 11m 29s
10. Artem aka @vregret: 11m 45s
11. PS aka @tr3mor1401: 12m 5s
12. Ruslan aka @RuslanGozgeshev: 12m 15s
13. Maxim aka @mbaran0v: 12m 34s
14. Евгений aka @Ggwpkekwait: 13m 4s
15. ghost aka @649***: 13m 43s
P. S. Иногда разница в результатах была минимальной, поэтому мы увеличили число победителей с 10 до 15 😉
А сейчас я расскажу и покажу, как же всё-таки решить задачку и потратить на неё не больше 10 минут.
Решение задачи
Перед нами — достаточно стандартная задача по диагностике неработающего приложения. Поэтому начнём не менее стандартно: посмотрим, в каком состоянии на текущий момент находятся поды приложения:
Обнаруживаем, что один под завис в состоянии Pending, а второй не может запуститься и висит в состоянии ContainerCreating.
Дальше стоит проверить, почему это происходит и поочерёдно запускаем describe чтобы посмотреть ошибки, которые генерируют поды.
В первом поде, как оказалось, контейнер падает по OOM. Картина знакомая и надо поправить ему лимиты ресурсов в конфигурации deployment:
Из ошибок второго пода понимаем, что он не смог выбрать ноду для запуска из-за anti-affinity, всё в той же конфигурации deployment:
Запускаем kubectl edit и начинаем редактировать deployment. В первую очередь удаляем секцию за affinity:
Потом и исправляем лимиты контейнера на более приемлемые:
Сохраняем изменения и смотрим, что получилось:
Один из подов пересоздался, но картина не изменилась, и на него всё ещё действует anti-affinity, которого уже не должно быть в конфигурации. Надо понять, что же произошло — для этого посмотрим на ReplicaSet’ы которыми управляет наш deployment:
В этом месте нужно сделать небольшое отступление и рассказать, как работает RollingUpdate в k8s. Тем, кто активно пользуется k8s известно, что у k8s есть такой параметр как maxUnavailable, и в данном примере он равен 1.
А это значит, что поды будут пересоздаваться в новом ReplicaSet’е по одному и пока новый не создан, из старого ReplicaSet он не будет удалён.
Следующее, что нужно знать — первым будет удаляться под с наименьшим сроком жизни, а это значит что будет удален именно под, который не был размещён из-за конфликта anti-affinity, а значит уже размещенный на ноде под с anti-affinity останется.
И последнее, что нам мешает разместить новый под — симметричность anti-affinity. Т. е. данный механизм не только не позволяет разместить под с данным свойством на машине, где уже есть под конфликтующий с ним, но и не позволяет разместить конфликтующий под на машине, где уже есть под с данным свойством. Подробнее можно прочитать в документации.
Итак, по сути, для того чтобы решить проблему достаточно удалить старый ReplicaSet, что приведёт к удалению старых подов с anti-affinity и позволит разместить новый ReplicaSet без проблем.
И вот, наши поды, наконец запустились. Самое время проверить, доступен ли сервис:
Интересно, если поды работают, то стоит проверить, видит ли их сервис? Для этого проверим список эндпоинтов:
Похоже, что не сформированы необходимые эндпоинты, несмотря на поды, которые работают и готовы отвечать на запросы. Впрочем, такая ситуация вполне возможна, если допустить ошибку в оформлении сервиса, поэтому смотрим на его конфигурацию:
И тут задачка на внимательность – стоит обратить внимание на опечатку в названии селектора, после исправления которой у сервиса появляются два эндпоинта, и сам он начинает отвечать на запросы:
Дополнительно записали видеоразбор, чтобы наглядно показать решение.
Спасибо всем, кто участвовал в челлендже! Уже готовим ещё одну возможность проявить себя, следите за нашим блогом — точно не пропустите 🔥