Как стать автором
Обновить

Комментарии 55

ЗакрепленныеЗакреплённые комментарии

Если не отключить swap, то kubeadm откажется поднимать кластер и потребует его отключения перед тем как продолжить. А с технической точки зрения, свап отключается из-за того, что при нехватке памяти (если свап включен) под будет записан на диск. При многочисленном удалении и создании подов в таком состоянии (например обновили deployment) вызовет деградацию перформанса всей вм-ки (или сервера). При выключенном свапе, сам kubelet способен обработать ситуацию когда нет памяти. Он тупо не поднимет под и в описании пода (kubectl describe pod my-pod) укажет что мало памяти. Для такого сценария ответственность за правильный scheduling пода на нужных нодах ложится на администратора (taint-ы и toleration-ы + node selector-ы, к тому же есть возможность установки ресурсных лимитов для самих подов)

А как настроить так терминал? Так удобно выглядит.

Если не вдаваться сильно в детали, которые под копотом, то основные детали это конфигурация tmux через пакетный мемеджер tpm и плагин dracula, и настройщик командной строки starship.

Так что вот этапы:

  1. Устанавливаем tmux, устанавливаем tpm и заносим мой tmux.conf в ~/.config/tmux/tmux.conf

  2. Устанавливаем starship и не забываем добавить в ~/.bashrc (или .zshrc, config.fish, тд). Заносим мой starship.conf в ~/.config/starship.toml

Остальные подробности придется как-нибудь описать в отдельном посте)

Простите, а что именно starship делает? Выглядит как просто tmux с вертикальным сплитом панелей.

Не совсем. Tmux и starship это совсем разные вещи. Tmux — это терминальный оконный менеджер. Starship — это конфигуратор самой строки в терминале. Он, например, позволяет превратить вот эту унылую строку:

user@ubuntu: ~/#

В вот такие красивые и полезные штуки:

Или вот такую:

То есть, starship это аналог Oh My Zsh для Zsh shell и ohmybash для Bash. Но у starship есть одно явное преимущество: он совместим с Bash, Fish, Zsh, Powershell, Elvish, Tcsh и со многими другими терминальными средами. То есть, один конфиг будет работать во всех этих средах. Плюс, starship написан на языке Rust, что делает его гораздо шустрее при генерации всех этих "красивых и полезных штук", в отличие от ohmyzsh и ohmybash, которые написаны на ответствующих терминальных средах.

Хм, надо будет попробовать. Спасибо

Спасибо что не только изложили порядок действий, но и разъяснили смысл каждого шага!

Помню как-то раз приходилось поднимать кластер таким способом, и я тогда еще не мог понять. Вот есть список шагов которые надо выполнить чтобы подготовиться к установке кластера, он досконально описан в официальных доках. Почему было просто не включить эти шаги в утилиту kubeadm? А там, где от пользователя требуется какое-то осознанное решение, например выбор движка для контейнеров, делать промпт? В этом есть какой-то тайный смысл, или просто у мейнтейнеров руки не дошли?

Видимо решили разделить роли. kubeadm это инструмент исключительно настройки кубера. Он не занимается настройкой ОС и ее компонентов. Для последнего есть kubespray - он предварительно все настроит, даст выбор контейнерного рантайма и много чего еще (статья, например, не коснулась вообще выбора CNI), а потом использует тот же kubeadm, чтобы настроить специфические куберовские вещи.

Дело в том, что Kubernetes — это прежде всего контейнрный оркестратор и на этом его, так скажем, "ответственность", почти заканчивается. Боллее того, сам Kubernetes отдаляется от поддержки отдельных компонентов, которые не связаны с его основной должностью. Например, с версии 1.24, Kubernetes больше не поддерживает dockershim официально. Это означает, что выбор контейнерного рантайма (containerd, cri-o, Docker Engine и другие) теперь стоит за Kubernetes администратором и kubeadm теперь делает гораздо меньше за тебя. С другой стороны, kubeadm делает достаточно проверок настроек перед созданием кластера.

Более того, сам Kubernetes кластер может быть настроен по разному, в зависимости от технических требований. Например, БД etcd может быть настроена вне нод мастеров, а сами мастера могут быть настроены через Load Balancer, которые осуществляют бесперебойность кластера. Это всё усложняет количество возможных конфигураций Kubernetes кластера. Поэтому, включать шаги настройки Kubernetes в утилиту kubeadm было бы достаточно трудно и кропотливо. С другой стороны, есть не мало утилит, которые упрощают настройку Kubernetes. Я думаю, всё зависит от требований.

Это машинный перевод? 'Debian-основной' это типа 'debian-based' что ли?

А можно ссылку на оригинал? Такой перевод что-то очень тяжело читать.

Судя по "можем начать установку контейнерного времени выполнения" - да.

Шож так сложно-то...

  1. Ставим убунту

  2. sudo snap install microk8s --classic

  3. Вы великолепны

Ага еще скажи

  1. sudo snap install microk8s --classic и продакшн

k3d же) а в продакшене EKS)

Не вижу нигде в статье слов про продакшен. Ну и для продакшена перечисленных действий скорее всего недостаточно.

Можно ли получить ссылку на официальную документацию, где было сказано про отключение файл подкачки?

Если бы автор хоть чуть-чуть шарил принципах работы операционной системы, он бы не рекомендовал отключать swap.

Я не рекомендую использовать этот гайд никому.

Ну тогда напишите гид, который объясняет почему не стоит отключать файл подкачки и я с удовольствием включу это в статью ;)

Потом про необоснованность отключения файла подкачки при настройки Kubernetes можно будет написать вот на эти ресурсы. Уверен, что там будет кому удивится:

Это особенность Kubelet и для его предсказуемого поведения SWAP должен быть отключен.

Если не отключить swap, то kubeadm откажется поднимать кластер и потребует его отключения перед тем как продолжить. А с технической точки зрения, свап отключается из-за того, что при нехватке памяти (если свап включен) под будет записан на диск. При многочисленном удалении и создании подов в таком состоянии (например обновили deployment) вызовет деградацию перформанса всей вм-ки (или сервера). При выключенном свапе, сам kubelet способен обработать ситуацию когда нет памяти. Он тупо не поднимет под и в описании пода (kubectl describe pod my-pod) укажет что мало памяти. Для такого сценария ответственность за правильный scheduling пода на нужных нодах ложится на администратора (taint-ы и toleration-ы + node selector-ы, к тому же есть возможность установки ресурсных лимитов для самих подов)

Спасибо за это лаконичнoe разъяснение. Думаю это стоит закрепить, так как тема про отключение swap при настройки kubeadm вызвало комичное количество недоумений)

Это всё вообще никак не объясняет в чём проблема kubelet'а считать лимиты памяти делая вид будто никакого свапа не существует.

К тому же я сходил по одной из предложенных ссылок и там отправляют в issue, которая очень даже fixed.

Тем не менее, в официальной документации (редакция 23 апреля, 2023 года ) твердится в жирном шрифте следующее:

"You MUST disable swap in order for the kubelet to work properly."

Если цель нашей дискуссии просто пофилософствовать от том, является ли бредом отключение swap памяти при настройки Kubernetes кластера, то можно хоть обфилософствоваться целами томами, на подобии софистов в Древней Греции. С практической же точки зрения, особенно в случаях, когда приходится настраивать Kubernetes в проде (таким, как мне), наверное, стоит придерживаться совету "вы ДОЛЖНЫ отключить swap память", который, в официальной документации, озвучивается соответствующим жирным шрифтом. Нет так ли?)

Оно fixed, но реализация в alpha стадии и не видно, чтобы что-то изменилось с тех пор https://kubernetes.io/blog/2021/08/09/run-nodes-with-swap-alpha/ Плюс реализация, по сути, никакая - кублет просто запускается с включенным свапом и может позволить подам использовать свап или не использовать. Все.

А рекомендация отключать свап все так же в силе, т.к. имеем непредсказуемое поведение нагрузок с ним. Плюс кубер все так же не способен оценить использовать свапа процессами, а значит не имеет полного контроля над ситуацией.

Собственно, я всегда отключал свап на любых продовых серваках, не только кубера. От этого всегда становилось только лучше. Многий софт точно так же рекомендует это делать.

Ну кубику свап реально мешает ресурсы планировать.

Вообще есть софт который заточен на максимально прямое управление памятью и ему своп мешает.

Да к примеру та-же Cassandra сама очень хорошо управляет памятью, а включение свопа под нагрузкой точно ее замедляет тк она очень хитро внутренними буферами пользуется.

Если оставаться в рамках кубика. Вот представьте себе ситуацию. Прод кластер под кубиком. Есть два типа подов. Мелкие - кушают 2-4 ГБ склероза, и крупные - по 20 ГБ. Падает одна из нод и кубер должен пераспределить поды с этой ноды на оставшиеся. Если ну нас включен своп то большой под может попасть на ноду у которой физическая память уже загружена и ему придется бороться за ресурсы. Если своп выключен - произойдет перераспределение мелких подов так чтобы все помещались в памяти.

И если прям супер надо - своп можно включить в поде.

Каким образом отключение swap помогает избавиться от OOM? Если нет swap'а - он придёт еще раньше)

Просто со свап все будет умирать очень долго, в чем практически нет смысла. Если у вас la 20+ на 4х ядерном проце, то поверьте свап вас уже не спасет

Мой вопрос был не в этом, а в том как отключение swap решит проблему с OOM. ответ - никак =)

Что подразумевается под проблемой OOM ?

Вы статью читали?

"Кроме того, отключение swap может помочь предотвратить риск вызова так называемого "OOM killer"."

Не может.

:facepalm: мы вроде обсуждали комментарий @AkshinM относительно отключения swap, а оказывается что нет

У того комментария 0 ответов, более того он добавлен через 6 часов после моего - так что мы его точно не обсуждали)

Легко. Новый под не будет запланирован и начнет орать шедулер, а не сдохнет рандомный под из уже работающих.

Ну бред же. Высокий la может быть потому что вся система ждёт I/O, который некуда закешировать, потому что выключили свап (а если бы он был включен, то в него бы выпихнулись неактивные процессы, и появилась память для кэширования I/O).

И какой процент таких случаев 0,00001% ? В личной практике за 20 лет свап ни разу не помогал, а только мешал

Так кубер и решает это тем что не запускает нагрузку которую не выдержит кластер. В продакшн fast-fail гораздо лучше "очень медленно работает". Первое сразу детекится мониторингом и орет везде. Второе - очень сложно искать и ещё сложнее отлаживать.

Чтобы убедиться, что swap остается отключенным после запуска, нам необходимо закомментировать строку в файле /etc/fstab

Всё пытался по инструкции сделать, первое с чем столкнулся - ключ репозитория кубера, помогает добавить ключ руками и убрать из строчки параметр, указывающий на файл.

А второе с чем я столкнулся - файла нет /etc/kubernetes/admin.conf

его самому нужно создать или как?

Нужно ли инициализировать сеть кубера на воркерах? Или там просто джоин достаточно ввести после установки cri-o и докера?

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

А второе с чем я столкнулся - файла нет /etc/kubernetes/admin.conf

Файл /etc/kubernetes/admin.conf должен генерироваться при успешном выполнении kubeadm init. Стоит проверить, если инициализация первой ноды кластера прошла успешно.

С ключиком разобрался, делается примерно так

curl https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo apt-key add -
echo "deb https://apt.kubernetes.io/ kubernetes-xenial main" |  tee /etc/apt/sources.list.d/kubernetes.list

По файлу админ внимательно почитал, там написана команда после инита, оно куда то в другое место кладется

sudo cp -i /etc/kubernetes/tmp/kubeadm-init-dryrun3374606150/admin.conf $HOME/.kube/config

Но дальше вот ни приджойинться с других узлов, ни даже локально посмотреть статус не удается

user@kubi1:~$  kubectl get nodes
E0523 22:33:48.619600    5722 memcache.go:265] couldn't get current server API group list: Get "https://192.168.200.30:6443/api?timeout=32s": dial tcp 192.168.200.30:6443: connect: connection refused
E0523 22:33:48.619743    5722 memcache.go:265] couldn't get current server API group list: Get "https://192.168.200.30:6443/api?timeout=32s": dial tcp 192.168.200.30:6443: connect: connection refused
E0523 22:33:48.621086    5722 memcache.go:265] couldn't get current server API group list: Get "https://192.168.200.30:6443/api?timeout=32s": dial tcp 192.168.200.30:6443: connect: connection refused
E0523 22:33:48.622409    5722 memcache.go:265] couldn't get current server API group list: Get "https://192.168.200.30:6443/api?timeout=32s": dial tcp 192.168.200.30:6443: connect: connection refused
E0523 22:33:48.623691    5722 memcache.go:265] couldn't get current server API group list: Get "https://192.168.200.30:6443/api?timeout=32s": dial tcp 192.168.200.30:6443: connect: connection refused
The connection to the server 192.168.200.30:6443 was refused - did you specify the right host or port?

Вроде инит прошел успешно, но такое ощущение что какой-то сервис не запустился

P.s. понял что я от рута всё делал, когда через sudo запустил, то вдруг заработало...

тоже все пробовал внутри виртуалки sudo не был установлен в принципе, вряд ли в этом первопричина, да и по логике так быть не должно)

У меня удалось поднять кластер, присоединить к нему ноду, но хотелось бы продолжения статьи о назначении ролей нодам, о поднятии веб-админки)))

Боюсь, если всё описывать подробно, как я пытался это делать в этой статье (и при этом, всё равно пришлось вырезать десяток нюансов), то для описании правильной настройки RBAC ролей, придется писать целую книгу)

Я сейчас работаю над продолжением этой статьи, как раз примерно по этой теме, но мне предстоит ещё очень много протестировать, и понять, как это всё преподнести в формате статьи.

Мне интересно как вообще в кластер попадать, вот крутится на 5 нодах копия приложения, и куда на какой айпи заходить, как оно перераспределится? На работе мы крутим istio в опеншифте, но многие моменты за моими компетенциями, я обычно получаю проект, прокидываю в него 2-3 роута, дальше внутри кручу по урлам и портам, всякие там виртуалсервисы и гатевеи поднимаю, ингресс и эгресс, но вот когда дома поднял опеншифт, то даже к веб-панели не смог пробраться, запустил прокси с особым параметром чтобы пускало напрямую, а там мне вместо сайта отдает какой то json, будто это апи для сайта а не сайт.
Другой момент, что у меня есть в финале вашей инструкции одна пода контрол план, а вторая без роли, как назначить роль типа воркер или мастер и каких ролей минимально достаточно тоже надо гуглить собирать по крупицам.

Я вдруг понял что прочитал невнимательно, выполнял команду dry-run, и думал на этом всё, а эта команда ничего не делает кроме как проверки, простите.

Да, всё верно. "dry-run", это обычно универсальный флаг у многих команд, который, на человеческий язык, можно перевести примерно так:

"Пожалуйста, команда, покажи, что ты собираешься сделать и ничего при этом не сломай"

:)

может упустил, но где развертывание CNI?

Спасибо за статью, очень доступно изложено, но столкнулся с проблемой, возможно Вы сможете помочь. Поды на разных нодах не видят друг друга. В рамках одной ноды без проблем, но на разных что при доступе через сервис, что напрямую по ip - недоступны.

Спасибо, рад, что статья оказалась полезной.

Сперва, наверное стоит проверить самые элементарные вещи. Выполняем команду ip a на одной VM, получаем IP адрес, пингуем этот адрес с другой машины при помощи ping 192.168.1.23 где 192.168.1.23 является адрес первой машины. Если не пингуется, разбираемся почему сеть между двумя VM неправильно настроена.

Надеюсь, проблема только в этом, иначе придётся разбираться глубже)

К сожалению, ноды пингуют друг друга без проблем без проблем :)

Тогда стоит почитать документацию по kubeadm init. Для начала, стоит обратить внимание на флаг --apiserver-advertise-address и --control-plane-endpoint. Возможно, дефолтные значения присваиваются неправильно. В качестве обеих этих значений, присваиваем адрес первой мастер ноды:

kubeadm init --pod-network-cidr=10.100.0.0/16 --dry-run --apiserver-advertise-address 192.168.1.23 --control-plane-endpoint 192.168.1.23

Где 192.168.1.23 является адрес первой мастер ноды на которой мы инициализируем кластер. При добавлении воркера через команду с токеном, дополнительно указывать эти два флага (--apiserver-advertise-address и --control-plane-endpoint), думаю, тоже не помешает.

Сделал "kubeadm reset" на всех нодах и указал явно apiserver-advertise-address и

control-plane-endpoint и ничего не изменилось.

root@k8s-master:~/yamls# kubectl get nodes
NAME          STATUS   ROLES           AGE   VERSION
k8s-master    Ready    control-plane   13m   v1.27.2
k8s-worker1   Ready    <none>          11m   v1.27.2
k8s-worker2   Ready    <none>          11m   v1.27.2
root@k8s-master:~/yamls# kubectl get po -o wide
NAME            READY   STATUS    RESTARTS   AGE     IP           NODE          NOMINATED NODE   READINESS GATES
testapp-2p5gd   1/1     Running   0          2m37s   10.85.0.67   k8s-worker1   <none>           <none>
testapp-b6cb5   1/1     Running   0          2m37s   10.85.0.21   k8s-worker2   <none>           <none>
testapp-bnstn   1/1     Running   0          2m37s   10.85.0.66   k8s-worker1   <none>           <none>
root@k8s-master:~/yamls# kubectl get svc
NAME         TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)   AGE
kubernetes   ClusterIP   10.96.0.1       <none>        443/TCP   10m
testapp      ClusterIP   10.109.131.36   <none>        80/TCP    3m

# Выполняю на мастере - запросы не проходят
root@k8s-master:~/yamls# curl 10.109.131.36
curl: (7) Failed to connect to 10.109.131.36 port 80: No route to host

# Выполняю на первом воркере - запросы проходят только к тем подам которые крутятся на этом же воркере, запрос к поду на worker2 не проходит
root@k8s-worker1:~# curl 10.109.131.36
You've hit testapp-2p5gd
root@k8s-worker1:~# curl 10.109.131.36
You've hit testapp-bnstn
root@k8s-worker1:~# curl 10.109.131.36
curl: (7) Failed to connect to 10.109.131.36 port 80: No route to host

# Со второго воркера запросы отрабатывают только для пода testapp-b6cb5
root@k8s-worker2:~# curl 10.109.131.36
You've hit testapp-b6cb5
root@k8s-worker2:~# curl 10.109.131.36
curl: (7) Failed to connect to 10.109.131.36 port 80: No route to host
root@k8s-worker2:~# curl 10.109.131.36
curl: (7) Failed to connect to 10.109.131.36 port 80: No route to host

Там, чуть выше, @scruffпишет про CNI, возможно в этом дело?

Решил проблему, добавьте пожалуйста в мануал

kubectl apply -f https://github.com/weaveworks/weave/releases/download/v2.8.1/weave-daemonset-k8s.yaml

Т.е. поставили CNI, коих, помимо weave, великое множество. Я, собственно, и удивлялся, как в статье что-то работает на multi-host кластере без CNI, задача которого как раз управлять роутингом между подами на разных хостах.

Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации

Истории