Comments 28
1500 pod и 50 нод — не такие уж и маленькие проекты вообще то.
Кстати, а как персистентность и базы разруливаете? В качестве распределенного файлового хранилища что используете, nfs (как на слайде)?
Базы живут у вас где, внутри kubernetes (в одном экземпляре, с маппингом на хостовую файловую систему, часть нод помечены как соделжащие базы), или же во внешнем окружении есть отдельный кластер или просто отдельная машина.
Кстати, а как персистентность и базы разруливаете? В качестве распределенного файлового хранилища что используете, nfs (как на слайде)?
ceph, вроде я об этом в докладе рассказывал.
Базы живут у вас где, внутри kubernetes (в одном экземпляре, с маппингом на хостовую файловую систему, часть нод помечены как соделжащие базы), или же во внешнем окружении есть отдельный кластер или просто отдельная машина.
Все перечисленные варианты. Очень ждем https://github.com/kubernetes/features/issues/121 .
ceph… Ты как то тоже рассматривали как делать персистентность и ceph рассматривали. Не понравилось, что там должна обязательно быть главная нода. Я тогда думал выбрать glusterFs, но админы сказали что не факт что будет стабильно работать. В итоге сейчас админы настроили torrentSync между нодами, вроде для наших целей пока подходит.
Запуск тестов в 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-сервером автоматом. Поддержки такого режима работы из коробки пока нет.
В плане самой фичи 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 — пересобрал и перезапустил.
Очень общая фраза. Можете рассказать, как именно вы разворачиваете новые images? Заливаете их командой set image, определяя свежий доступный образ? Используете deployment-файлы? Вызываете apply или replace?
Apply, судя по документации, должно разруливать это, но так вроде бы с самого начала нужно создавать ресурсы:
> To use 'apply', always create the resource initially with either 'apply' or 'create --save-config'.
Так, так и должно быть. Старые реплики остаются, но они нулевого размера. Посмотрите видос полностью, там рассказывается о том зачем и почему так.
Версия kubernetes?
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. Но конфигурация сервисов отделена от кода проекта.
Ссылка изменилась: https://flant.github.io/dapp/secrets_for_kube.html
Можно, наверное, еще вспомнить, что существуют 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 .
Наш опыт с Kubernetes в небольших проектах (обзор и видео доклада)