Pull to refresh

Comments 28

1500 pod и 50 нод — не такие уж и маленькие проекты вообще то.


Кстати, а как персистентность и базы разруливаете? В качестве распределенного файлового хранилища что используете, nfs (как на слайде)?


Базы живут у вас где, внутри kubernetes (в одном экземпляре, с маппингом на хостовую файловую систему, часть нод помечены как соделжащие базы), или же во внешнем окружении есть отдельный кластер или просто отдельная машина.

Кстати, а как персистентность и базы разруливаете? В качестве распределенного файлового хранилища что используете, nfs (как на слайде)?

ceph, вроде я об этом в докладе рассказывал.


Базы живут у вас где, внутри kubernetes (в одном экземпляре, с маппингом на хостовую файловую систему, часть нод помечены как соделжащие базы), или же во внешнем окружении есть отдельный кластер или просто отдельная машина.

Все перечисленные варианты. Очень ждем https://github.com/kubernetes/features/issues/121 .

ceph… Ты как то тоже рассматривали как делать персистентность и ceph рассматривали. Не понравилось, что там должна обязательно быть главная нода. Я тогда думал выбрать glusterFs, но админы сказали что не факт что будет стабильно работать. В итоге сейчас админы настроили torrentSync между нодами, вроде для наших целей пока подходит.

Не понравилось, что там должна обязательно быть главная нода

Это не совсем так. Мы от ceph используем в основном rbd, там нормальный multi master.

Это совсем не так. Там консенсус между мониторами. Из "главных" там только первичный OSD будет "главным", но потеря OSD прозрачна для клиента.

Спасибо за статью, подскажите, используете ли Вы kubernetes в локальной разработке? Если да, то как?
Запуск тестов в docker-образе это конечно хорошо, но как Вы тестируете взаимодействие нескольких сервисов (подов)?
Спасибо!
minikube — это да, но интересуют нюансы, например, как монтируются локальные директории, чтобы они были доступны в подах (при этом, желательно не плодить разны конфигурации кластера для дева и прода )?
Возможно используется helm для работы поддержания 1 конфигурации в разных контурах? Как происходит отладка приложения?
minikube — это да, но интересуют нюансы, например, как монтируются локальные директории, чтобы они были доступны в подах (при этом, желательно не плодить разны конфигурации кластера для дева и прода )? Возможно используется helm для работы поддержания 1 конфигурации в разных контурах?

Пока не придумали. Работаем над этим. Есть пачка вариантов, как делаем сейчас, но все они не нравятся:


  • Так-как у нас есть шеф-рецепты (dapp поддерживает), собирать одними и теми же шеф рецептами и docker-образы для прода и Vagrant'ы. Проблемы: очень долго, сложно писать универсальные рецепты.
  • Запускать докер контейнеры (dapp run) в Vagrant ИЛИ использовать minikube.
    • Можно собирать образ при каждом Ctrl-S. Проблемы: долго.
    • Монтировать или подключаться по SSH. Проблемы: описание правил монтирования/подключения
  • Разворачивать в кластере Kubernetes отдельное окружение для разработки (например давать туда доступ разработчикам, например по SSH). Проблемы: описание правил.

В целом все идет к тому, что мы будем работать над:


  • Ускорением сборки и деплоя. Если сократим время сборки нового образа и деплоя в minikube до 5 секунд, уже будет вполне реально передеплоивать приложение при каждом Ctrl-S.
  • Автомагией в dapp, которая будет понимать какие исходники куда добавлены (мы знаем это и так) и сама генерить маунты.

Как происходит отладка приложения?

У нашего сборщика есть специальный флаг, --dev, ну и пачка других опция для удобной отладки.

По задумке dev-режима сборщика предполагается деплоить через helm в minikube. При этом описание helm-конфигурации для development-окружения, используемый namespace — на усмотрение пользователя.


Есть команда dapp kube minikube setup, которая:


  • Стартует minikube
  • Поднимает в minikube docker-registry
  • Поднимает proxy в host-системе для использования docker-registry

Предполагается такой сценарий использования:


  • Сборка образа в host-системе: dapp dimg build [--dev].
  • Загрузка образа в minikube docker-registry: dapp dimg push :minikube [--dev].
  • Запуск/обновление кластера: dapp kube deploy :minikube [--dev] [+ helm values options].

Но для web-приложений в development-режиме (например) необходимы mount-ы исходников в запущенные образа, чтобы изменения исходников подхватывались уже запущенным web-сервером автоматом. Поддержки такого режима работы из коробки пока нет.

Но для web-приложений в development-режиме (например) необходимы mount-ы исходников в запущенные образа, чтобы изменения исходников подхватывались уже запущенным web-сервером автоматом. Поддержки такого режима работы из коробки пока нет.

Вот тут пишут что добавили. Не то?

В плане самой фичи mount подойдет. Т.е. mount из host в minikube + mount из minikube в docker позволят пробросить директорию в контейнер из хост-системы. Но главная проблема не в этом, а в том, чтобы этот запущенный контейнер соответствовал тем инструкциям по сборке образа приложения, которые описываются в Dappfile. Например, при изменении Gemfile.lock надо сделать bundle install. Для этого в dapp предусмотрены стадии и для пересборки стадии можно поставить триггер на изменение файла Gemfile.lock. А в случае, если изменяется не Gemfile.lock, то при сборке новой версии происходит простое и быстрое наложение патча. Так вот, если поменялись какие-то файлы, от которых зависят инструкции по сборке каких-то стадий, то образ придется пересобрать и перезапустить контейнер приложения. Но если поменялись другие файлы приложения, то новый образ собирать не надо, если исходники уже примонтированы в запущенный контейнер.


Однако сам minikube mount мы пробовали использовать для хранения файлов docker-registry на хост-системе, а не внутри minikube на виртуалке. Но производительность этой штуки для docker-registry неприемлема.

Так вот, если поменялись какие-то файлы, от которых зависят инструкции по сборке каких-то стадий, то образ придется пересобрать и перезапустить контейнер приложения. Но если поменялись другие файлы приложения, то новый образ собирать не надо, если исходники уже примонтированы в запущенный контейнер.

Я видимо уже привык и просто не вижу тут проблемы. Поменялся Dockerfile — пересобрал и перезапустил.
> При релизе (стадия release) YAML-конфигурации из директории .kube отдаём утилите kubectl, которая отправляет их в Kubernetes, после чего скачиваются Docker-образы и запускаются в инфраструктуре, развёрнутой по конфигурации из YAML. (Раньше мы использовали для этого Helm, но сейчас доделываем свой инструмент dapp.)

Очень общая фраза. Можете рассказать, как именно вы разворачиваете новые images? Заливаете их командой set image, определяя свежий доступный образ? Используете deployment-файлы? Вызываете apply или replace?

Тут лучше смотреть видос, там более подробно. Раньше мы использовали простейший shell скрипт, который проходится envsubst'ом по yaml-шаблонам. Потом стали использовать helm. Потом сделали поддержку helm в dapp.

Спасибо, ушел читать про helm
Ещё вопрос из чайника, сталкивались ли с такой ситуацией, когда kubectl replace для deployment приводит к появлению дубликатов replicasets? Старые реплики остаются в строю, а новые с новыми images поднимаются рядом. Вероятно, это актуально для старой версии kubernetes, но не так просто обновляться в рабочем окружении.

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

> To use 'apply', always create the resource initially with either 'apply' or 'create --save-config'.

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

Нет, в моём случае остаётся работающая реплика, не нулевого размера. Т.е. я получаю поды из двух реплик одновременно.
Client Version: version.Info{Major:"1", Minor:"5", GitVersion:"v1.5.3", GitCommit:"029c3a408176b55c30846f0faedf56aae5992e9b", GitTreeState:"clean", BuildDate:"2017-02-15T06:40:50Z", GoVersion:"go1.7.4", Compiler:"gc", Platform:"linux/amd64"}
Server Version: version.Info{Major:"1", Minor:"5", GitVersion:"v1.5.5", GitCommit:"894ff23729bbc0055907dd3a496afb725396adda", GitTreeState:"clean", BuildDate:"2017-03-22T00:17:51Z", GoVersion:"go1.7.4", Compiler:"gc", Platform:"linux/amd64"}

Спасибо за доклад!


В Git кладём Dockerfile (а точнее, мы используем для этого dapp) и каталог .kube с YAML-конфигурациями.

как поступаете, когда yaml (конфигурация сервиса) содержит sensetive data ?

Sensitive data кодируется симметричным ключом и попадает в repo. При выкате, если указана переменная окружения с ключом, то секретные данные становятся доступны. Эту переменную окружения можно указывать, например, как gitlab-secret-variable. Секретные значения — это либо файлы, либо helm values. Соответственно в yaml-шаблонах либо читается уже расшифрованный на момент запуска файл либо подставляется значение из values.
Подробнее здесь: https://flant.github.io/dapp/secrets_for_deploy.html.

Ясно, благодарю!
Со своей стороны использую ansible + ansible-vault для раскатки yaml kubernetes. Но конфигурация сервисов отделена от кода проекта.

> ReplicaSet — множество подов, количество которых автоматически поддерживается (при изменении числа подов в конфигурации, при падении каких-либо подов/узлов), что делает масштабирование очень простым;

Можно, наверное, еще вспомнить, что существуют Replication Controller (RC), которые больше не рекомендуют использовать, но они еще широко используются.

ПС. Отличная статья!
Отличная статья и видео, спасибо!

А как вы решаете вопрос с потерей IP-адреса при прохождении nginx ingress controller?

Зависит от инфраструктуры.


  • Если это AWS — там есть proxy protocol (у service нужно поставить специальную аннотацию и nginx сказать слушать proxy protocol, он это умеет штатно).
  • Если bare metal — мы делаем daemon set с hostNetwork, таким образом IP-адрес не теряется, но есть простой при обновлении самого ingress (или при падении). Проблему простоя решаем очень хитро, iptables с помощью модуля сокет, если 80 порт не слушается, перекидывает трафик на другой порт, на котором слушает nginx в режиме TCP-proxy, который добавляет proxy protocol и отправляет трафик в отдельный деплоймент с nginx ingress. Таким образом, у нас на фронтах ingress'ы в daemonset плюс дополнительный nginx tcp fallback в daemonset, плюс есть отдельный deployment nginx'ов. Тут можно посмотреть: https://github.com/flant/kubernetes-nginx-ingress .
Sign up to leave a comment.