Pull to refresh

Comments 43

Rook пока очень сырой чтобы на него смотреть как мне кажется. Что-то пойдет не так и все, все хранилище мертво.

Подскажите что почитать по сетям в контейнерах… сколько всего перечитал, но кроме проброса портов в контейнер с ноды, так ничего для себя и не открыл :( Так и не могу понять, как это должно правильно работать с большом кластере
А что именно вы хотите для себя открыть?
Есть какая-то задача, которую вы не можете решить? Тогда опишите конкретнее о задаче.
Я просто хочу понять, как работать с контейнерами через сеть. Допустим простой пример: 3 ноды докера, там пара контейнеров с БД и веб-сервером, между собой контейнеры работают, это понятно, а как осуществлять правильно внешний доступ к веб-серверу? Пробрасывать порт через ноду кластера? Использовать балансер, где указывать все ноды кластера, что бы это работало отказоустойчиво?
Сервисы объединяют pod-ы, а ingress «выпускает» твой сервис во внешний мир)

Посмотри для начала вот это видео, меня оно вдохновило:
www.youtube.com/watch?v=CgCLPYJRxbU&t=1406s

А можите больше рассказать о сетевой подсистеме? Почему выбрали Flannel? Делали какие-то тесты скорости между нодами на разных серверах? Отличаются ли время пингов между контейнерами от пингов между серверами?

У flannel есть режим работы host-gw, когда все ваши машины в пределах одного сегмента L2, там минимальный оверхед — по сути он просто все забивает в таблицу маршрутизации.


С другой стороны, calico так тоже может, но у calico еще и NetworkPolicy есть.

host-gw это ни для всех. Хочется кластер на недорогом арендном железе/в разных дц/или просто в облаке.
Я рассматривал и этот вариант, но мне нравится и спокойнее, использовать тот вариант, который я понимаю.
Мне видится мой вариант проще и надежнее. Не нужно клонировать стороннюю репу, не нужно разбираться с Go и ловить баги сторонних разработчиков.
ловить баги сторонних разработчиков

Так это все те же rootfs / cofyc, по большему счету :-)

Вы пошли по похожему, как и я делал.
У меня есть пара замечаний.
Ваш k8s получился с одним мастером, что при трёх серверах как-то не понятно. Я устанавливал через kubespray, плюс тут в том, что у меня получаеся кластер с мультимастером и есть лёгкая возможность добавлять новые ноды (путём записи в inventory файл). Так-же можно позже делать обновления всего кластера, я так делал, когда обновлял с 1.7 на 1.8.
И второй момент это StorageClass, с этим пунктом я не очень уверен и может быть путаю. Как я помню, для использования rbd, перед этим его (rbd) надо сперва создать. В принципе в этом нет ничего сложного, но для этого его надо в ручную создать (или через скрипты), что вроде не очень удобно. Может быть использовать лучше cephfs и её потом монтировать в поды, для каждого можно создавать отдельные папки. Как-то так:
        volumeMounts:
        - name: icingaweb2
          mountPath: /icingaweb2
...
      volumes:
      - name: icingaweb2
        hostPath:
          path: /a/data/monitoring.adito.de/icingaweb2

То есть "/a/data" это папка на cephfs, а остальное создаётся при запуске pod/deployment

и для rbd и для cephfs есть контроллеры StorageClass, которые создают хранилище сами.

Ничего, кроме того, что я описал в статье, создавать не нужно)
Разделы создаются, форматируются и монтируются автоматически.
CephFS и Ceph (RBD) это немного разные вещи, даже сильно разные)

CephFS требует создания раздела для данных и мета-данных (да, их нужно создавать самостоятельно). Далее, такие разделы монтируются с помощью обычного mount, например так:
mount -t cehp kub01:.....:/ /mnt/, либо через fuse.

Ceph (RBD) — создает раздел и устройство автоматически c помощью утилиты rbd, выглядит это так:
rbd create rbd/aaa  --size 100M  # создаем раздел
rdb map rbd/aaa # создаем устройство, вида: /dev/rbd0
mkfs.ext3 /dev/rbd0 # форматируем
mount /dev/rbd0 /mnt/disk # монтируем

Я использую именно RBD, и k8s эти команды выполняет самостоятельно)
Я смотрел в сторону kubespray, но он под капотом использует всё тот-же kubeadm, он за вас его запускает с нужными аргументами. Этот путь имеет право на жизнь, но мне нравится путь, когда я сам делаю то, что мне нужно, так я лучше контролирую весь процесс и систему в целом. Я пока не поднимал второго мастера, но уверен, что kubeadm для этого будет достаточно)

Для контейнеров типа MySQL где предполагается их постоянные данные хранить?

Это сложная и большая тема. Если БД не сильно нагружена, то можно разместить ее в Ceph. Но если БД требует большого кол-ва дисковых операций, то придется запустить ее где-то в другом месте, даже на другом сервере и ВНЕ k8s. На данный момент в k8s ведется разработка для local storage, но в данный момент это alpfa и перспективы весьма туманны.
Резюмирую: k8s не готов к работе с сервисами, требующих больших дисковых ресурсов (производительности).
Здравствуйте.
Рассматривали ли вы альтернативы Ceph? Какой-либо glusterfs или иное?
Да, можете еще рассказать о сетевой инфраструктуре в вашем случае? Как будет себя чувствовать дисковый кластер (и k8s) при высокой нагрузке и слабым uplink между серверами?
Кроме непосредственно поднятия кластера до состояния «заработало» было бы еще интересно почитать основы по защите кластера — т.е. что нужно учитывать, когда настраиваешь кубернетс на серверах с прямым доступом из интернет: чтобы и внутренние сервисы можно было наружу отдавать и условно не выставлять базу с админским доступом без пароля во внешнюю сеть.
Данная статья всё таки больше о том, как запустить кластер до рабочего состояния.
При всём желании не получится описать в одной статье всё и про всё.
Не очень понятен вопрос о базе без пароля выставленную во внешнюю сеть. О чем это?
Если вы запустите какую либо БД (или вообще любое ПО) через k8s, то она не выставляется во внешнюю сеть, а наличие в ней пароля зависит от деплоя.
Для того, чтобы понять как работает k8s со внешней средой, советую почитать про Ingress.
Я имею ввиду доступ к самому kubernetes.
Например при настройках по умолчанию может остаться доступ к API без пароля или с каким-то известным паролем, заданным при установке по умолчанию.

Тогда без дополнительной настройки (смены пароля, закрытие всех путей доступа к API и методов авторизации, кроме тех что заданы явно) — кластер получается открытым для для внешних систем и кто угодно сможет запускать там свои образы.
kubernetes хорошо продуманна. Пароли не применяются. Доступы осуществляются с помощью ключей. Но Вы правы, безопасности нужно уделять внимание. Думаю, будет не лишним заняться более глубоким изучением сервисов, торчащих во внешний мир.
k8s требует распределенного файлового хранилища.
я может что то пропустил, но с каких пор k8s стал именно требовать распределенное хранилище? Сама суть кубернетиса в том, что у вас запускаются контейнеры и потеря контейнера никак не должна влиять на работу кластера. При потере контейнера/ноды scheduler k8s просто запустит их на другой ноде(подах)

Не увидел настройку докера для работы с flannel. Каким образом в вашем случае поды запущенные на разных нодах, а по дефолту докер использует подсеть 172.17.0.0/16, будут общаться между собой?

Если БД не сильно нагружена, то можно разместить ее в Ceph
да вы батенька знаете толк в извращениях
я может что то пропустил, но с каких пор k8s стал именно требовать распределенное хранилище?

Это написано в разделе про «Диски». Если приложению нужен диск (storage), то да, я повторюсь: «требует», и в статье я объяснил почему. Если приложению диск не нужен, то и требования не возникает.

Не увидел настройку докера для работы с flannel. Каким образом в вашем случае поды запущенные на разных нодах, а по дефолту докер использует подсеть 172.17.0.0/16, будут общаться между собой?

Когда k8s запускает pod (докер), он выделяет свободный IP адрес из диапазона flannel, и назначает его контейнеру. Ничего дополнительно конфигурировать не нужно.
Когда k8s запускает pod (докер), он выделяет свободный IP адрес из диапазона flannel
очень странно, а откуда докер вообще узнает о существовании flannel? Насколько я помню, то по дефолту pod'ы поднимались в дефолтной подсети docker и только после явной правки конфига docker оно начинало работать как надо.

У них собственно и в документации об этом говорится. И именно поэтому flannel генерирует файл /var/run/flannel_docker_opts.env. Например у меня в тестовой среде он имеет вид

# cat /var/run/flannel_docker_opts.env
DOCKER_OPT_BIP="--bip=172.16.2.1/24"
DOCKER_OPT_IPMASQ="--ip-masq=true"
DOCKER_OPT_MTU="--mtu=1450"


Соответственно на каждой ноде flannel получает свою подсеть /24, запрашивая ее у etcd

Если приложению нужен диск (storage), то да, я повторюсь: «требует», и в статье я объяснил почему
лично мне не понятна формулировка «Если приложению нужен диск (storage)» — в каких случаях приложение будет требовать диск? Например при запуске nginx диск будет востребован? При этом нигде не упоминается stateful/stateless приложения и их отличия.

И пробросим порт 8001 с вашей рабочей машины до сервера kub01:
ssh -L 8001:127.0.0.1:8001 -N kub01 &
для этих вещей специально придумали kubectl proxy --port=8001
очень странно, а откуда докер вообще узнает о существовании flannel?

Этого я не знаю. К счастью, k8s работает очень прозрачно, и многое от нас скрыто под капотом (да, туда можно залезть, но если всё и так работает, то зачем?). Хотите верьте, хотите нет, но k8s запускает pod-ы c уже настроенной сетью, и нам ничего дополнительного делать не нужно.
Если у вас есть желание разобраться в этом глубже, добро пожаловать на Хабр со своей статьей)

лично мне не понятна формулировка «Если приложению нужен диск (storage)» — в каких случаях приложение будет требовать диск?

Тут два пути:
1) Вы сами создаете нужный вам контейнер, и пишите к нему YAML файл, где и просите у k8s (claim) о диске (если он вам нужен).
2) Используете helm, где для каждого проекта описана необходимость в диске
Вообще, постановка вопроса странная: мне кажется, вы просто обязаны понимать, что делаете и как это должно работать, и нужен ли вам диск.

для этих вещей специально придумали kubectl proxy --port=8001

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

Не все разработчики понимают нужен ли им диск, по крайней мере диск с rw правами. На прямой вопрос нужен ли rw доступ куда-то на диск, говорят "нет, мы не используем в приложении работу с файлами, у нас всё в базе". А потом выясняется, по логам ошибок, что они -то не использует, а вот рантайм под капотом использует: сессии, временные файлы какие-то, иногда даже исполняемые. Ну и собственно логи :)

Спасибо за вашу статью, во многом полезная для новичка, но до полного howto не хватает подробностей и нюансов.

С чем столкнулся я:
1) Прежде всего нужно удалить из /etc/hosts связку хостнейма и 127.0.0.1, в противном случае команда ceph-deploy не пройдет и упадет с ошибкой:
[ceph_deploy][ERROR ] UnableToResolveError: Unable to resolve host: kub01

2) На всех тачках нужно поставить python. Без него все тот же ceph-deploy будет валиться с ошибкой, только уже с другой:
[kub02][INFO  ] Running command: ssh -CT -o BatchMode=yes kube02
bash: python: command not found

3) В пункте про обмен ssh ключами было бы не лишним указать от имени какого юзера мы обмен ключами делаем. Потому что если мы распыляем ключ рута и коннектимся от имени рута, то нужно разрешить ssh коннект от рута, потому что в Ubuntu 16.04 по дефолту он запрещен.
4) После правки конфига контроллера нужно производить какие либо операции? У меня спустя даже полчаса ничего не произошло. В итоге помог ребут тачки.
5) На шаге присоединения нод не хватает однозначности. Что мы в итоге делаем, новый токен или используем старый. Если используем старый то как собрать команду приведенную вами? А самое главное IP 8.8.8.8 очень путает.
6) Еще было бы интересно организовать доступ к подам снаружи без проброса через ssh.
Пункты 1-3: Можно например почитать официальную документацию по установке кластера ceph. В котором все нормально расписано.
6)Что бы можно было ходить к подам снаружи можно взять другой сетевой плагин, например calico.
Отдельно стоит отметить, что kube-adm решение не для production.
p.s. Самую активную помощь по продуктам описанным в статье можно получить в каналах телеграм.
t.me/kubernetes_ru
t.me/ceph_ru
1) Прежде всего нужно удалить из /etc/hosts связку хостнейма и 127.0.0.1, в противном случае команда ceph-deploy не пройдет и упадет с ошибкой:

Вы что-то делали не так) Разумеется, если вы используете домен вида: kub01, то он должен резолвится. Если он прописан в /etc/hosts как 127.0.0.1, то он будет резолвится, и такой ошибки быть не должно. И да, наверное его лучше не прописывать как 127.0.0.1.
Я на эту проблему не попадал, так как hostname серверу задавал уже после инсталляции сервера.

2) На всех тачках нужно поставить python. Без него все тот же ceph-deploy будет валиться с ошибкой, только уже с другой:

У вас Ubunta? Странно, что python не поставился по зависимостям, при установке самого ceph-deploy…
Я python ставил отдельно, так как была необходимость запускать ansible (для своих целей).

коннектимся от имени рута, то нужно разрешить ssh коннект от рута, потому что в Ubuntu 16.04 по дефолту он запрещен.

Спасибо за замечание. Подумаю как это решить по изящнее)

В итоге помог ребут тачки.

Это какой-то windows-way. Всегда бейте себя по рукам за такое)
У меня нет четкого ответа на это. Обычно, k8s сам замечает изменения и перезапускает controller. Но если этого не произошло, то можно перезапустить: kubelet и docker. Если кто знает, как это сделать красиво, отпишитесь.

5) На шаге присоединения нод не хватает однозначности. Что мы в итоге делаем, новый токен или используем старый. Если используем старый то как собрать команду приведенную вами? А самое главное IP 8.8.8.8 очень путает.

Если у вас есть «старый» токен, то можно использовать его. Самое простое, это сохранить команду «присоединения», которая пишется после инсталляции k8s (kubeadm init ...).
Если по каким-то причинам, у вас нет этой команды, то смело создавайте новую. Токен присоединения имеет срок истечения, и он пропадет спустя два дня. Главное, успеть присоедениться )
Если же, вы присоединяете ноды спустя два дня, вам всегда потребуется создавать токен присоединения.

Чем пугает 8.8.8.8? его нужно заменить на IP вашего мастера.

6) Еще было бы интересно организовать доступ к подам снаружи без проброса через ssh.

Зачем так? Делайте сервис + Ingress.
Но если очень хочется, то iptables вам в помощь (PREROUTING, POSTROUTING).
Вы что-то делали не так) Разумеется, если вы используете домен вида: kub01, то он >должен резолвится. Если он прописан в /etc/hosts как 127.0.0.1, то он будет резолвится, >и такой ошибки быть не должно. И да, наверное его лучше не прописывать как 127.0.0.1.

Да я просто наткнулся на ошибку и первое что посоветовал гугл это как раз: "In /etc/hosts, remove the hostname of loopback address. Add a line of real IP address and hostname correspondence, then problem solved."


У вас Ubunta? Странно, что python не поставился по зависимостям, при установке самого >ceph-deploy…
Я python ставил отдельно, так как была необходимость запускать ansible (для своих >целей).

Да Ubuntu 16.04. Питон автоматом поставился только на мастер. А на остальных тачках команды python нет, только python3 из коробки.


Это какой-то windows-way. Всегда бейте себя по рукам за такое)

Я хочу чтоб вы правильно понимали мой подход к данной статье)
Я рассчитывал просто на copy-paste без напряга мозгов, что покрутить/посмотреть.
Поскольку для серьезного деплоя есть тот де kubespray.


Если у вас есть «старый» токен, то можно использовать его. Самое простое, это >сохранить команду «присоединения», которая пишется после инсталляции k8s (kubeadm >init ...).
Если по каким-то причинам, у вас нет этой команды, то смело создавайте новую. Токен >присоединения имеет срок истечения, и он пропадет спустя два дня. Главное, успеть >присоедениться )
Если же, вы присоединяете ноды спустя два дня, вам всегда потребуется создавать токен >присоединения.

ИМХО если нам нужен токен, тогда нужно описать на этапе init о том что нужно сохранить команду присоединения либо уж однозначно создавать новый токен на этапе коннекта нод.


Чем пугает 8.8.8.8? его нужно заменить на IP вашего мастера.

Пугает тем что это гугловый DNS. Вводит в заблуждение тем что не понятно, толи автор реально просто юзает гугловый DNS для каких то целей присоединения (ну мало ли что там может понадобиться), толи его надо заменить на мастер. Вот реально, лучше измените на какой нибудь 1.2.3.4 или вообще %master_ip%.


Зачем так? Делайте сервис + Ingress.
Но если очень хочется, то iptables вам в помощь (PREROUTING, POSTROUTING).

Да в том что и дело что я и еще не малый процент аудитории не знает как правильно. И понятия не имеет о том что такое Ingress :)
Отсюда и вопросы такие.


Еще кстати момент. На этапе создания конфига kube-controller-manager copy-paste сработает не правильно, потому что при вставке баш попытается отрезолвить переменные ${KUBERNETES_DOWNLOAD_ROOT},${KUBERNETES_COMPONENT} и тп, а их нет в том окружении в котором делаем вставку, они появятся только при сборке, но на этапе сборки на их месте будет уже пустота.

Как раз проверял вчера надстройку над ceph под kubernetes: rook.io

Весь план сводится к запуску собственно кубернетеса любым способом и дальше через kubectl деплоится ceph за счет «родного» PVC ну и использует относительно новую абстракцию операторов.

Если интересно, могу в песочницу написать howto на базе любого облака.
Конечно пишите статью, это всегда полезно)
Лично мне пока боязно «запихивать» ceph в контейнеры. Опять же, тут нужно пояснить, какую часть ceph мы собираемся запускать в контейнерах.
В том то и дело, что они абстрагировали все уровни. То есть мониторы, метаданные и собственно диски. Всё в контейнерах с автодискавери на основе метаданных самого кубернетеса.

Раньше были приблуды типа только клиентов для маунта экспортированной вне кубернетеса файловой системы, но это не тру контейнер вей.

Тут же интеграция на основе и в рамках API самого кубернетеса. Для примера можете посмотреть как coreos написали операторы для кубернетеса.

Напишу статью – сюда линк положу, если не забуду.

У меня ceph в контейнерах (официальный контейнер) в виде статических манифестов kubelet. С одной стороны удобно и изоляция, и обновлять приятно, и мониторить можно из k8s, с другой — хранилище полностью отделено от control plane куба (и управляется ансиблой).

Нет, не пробовал. Я решал конкретную задачу, и не было возможности попробовать всё. А пробовать там есть что, и ох как много)
Интересно, почему обязательно нужен параметр --pod-network-cidr=10.244.0.0/16? Нет никакого дефолтного значения для этой сети?
Sign up to leave a comment.

Articles