Kubernetes tips & tricks: про локальну розробку та Telepresence
Нас все частіше запитують про створення мікросервісів в Kubernetes. Розробники, особливо інтерпретованих мов, хочуть швидко поправити код у улюбленій IDE і без очікування складання/деплою побачити результат — просто натиснувши на F5. І коли йшлося про монолітну програму, достатньо було локально підняти базу даних і веб-сервер (у Docker, VirtualBox ...), після чого - відразу ж насолоджуватися розробкою. З розпилюванням монолітів на мікросервіси і приходом Kubernetes, з появою залежностей один від одного, все стало трохи складніше. Що більше цих мікросервісів, то більше проблем. Щоб знову насолодитися розробкою, потрібно підняти вже не один і не два Docker-контейнери, а іноді навіть не один десяток… Загалом, на все це може витрачатись досить багато часу, оскільки потрібно ще й підтримувати в актуальному стані.
У різні часи ми пробували різні рішення проблеми. І почну я з накопичених workarounds або просто «милиць».
1. Милиці
Більшість IDE мають можливість правити код прямо на сервері за допомогою FTP/SFTP. Такий шлях дуже очевидний і ми одразу вирішили ним скористатися. Суть його зводиться до такого:
У pod'і у оточення для розробки (dev/review) запускається додатковий контейнер з доступом по SSH і прокиданням публічного SSH-ключа того розробника, що комітувати/деплоїти додаток.
На init-стадії (в рамках контейнера prepare-app) переносимо код у emptyDir, щоб мати доступ до коду з контейнерів з додатком та SSH-сервера.
Для кращого розуміння технічної реалізації такої схеми наведу фрагменти задіяних YAML-конфігурацій Kubernetes.
Зміни
1.1. values.yaml
ssh_pub_key:
vasya.pupkin: <ssh public key in base64>
Тут vasya.pupkin - Це значення змінної ${GITLAB_USER_LOGIN}.
Вуаля: розробник, що запустив деплой, може підключитися на ім'я сервісу (як безпечно видавати доступи до кластера, ми вже розповідали) зі свого робочого столу по SFTP і правити код без очікування його доставки в кластер.
Це цілком робоче рішення, проте з погляду реалізації має очевидні мінуси:
необхідність у доопрацюванні Helm-чарта, що надалі ускладнює його читання;
використовувати може лише той, хто задеплоїв сервіс;
необхідно не забути потім синхронізувати його з локальною директорією з кодом і комітнути в Git.
2. Telepresence
Проект Телеприсутність відомий досить давно, проте всерйоз спробувати його на ділі у нас, як то кажуть, «не доходили руки». Однак попит зробив свою справу і тепер ми раді поділитися досвідом, який може стати корисним читачам нашого блогу — тим більше, що на хабрі досі не було інших матеріалів про Telepresence.
Якщо стисло, то все виявилося не так страшно. Усі дії, які вимагають виконання з боку розробника, ми розмістили у текстовому файлі Helm-чарта, названому NOTES.txt. Таким чином, розробник після деплою сервісу в Kubernetes бачить інструкцію із запуску локального dev-оточення в лозі job'а GitLab:
!!! Разработка сервиса локально, в составе Kubernetes !!!
* Настройка окружения
* * Должен быть доступ до кластера через VPN
* * На локальном ПК установлен kubectl ( https://kubernetes.io/docs/tasks/tools/install-kubectl/ )
* * Получить config-файл для kubectl (скопировать в ~/.kube/config)
* * На локальном ПК установлен telepresence ( https://www.telepresence.io/reference/install )
* * Должен быть установлен Docker
* * Необходим доступ уровня reporter или выше к репозиторию https://gitlab.site.com/group/app
* * Необходимо залогинится в registry с логином/паролем от GitLab (делается один раз):
#########################################################################
docker login registry.site.com
#########################################################################
* Запуск окружения
#########################################################################
telepresence --namespace {{ .Values.global.env }} --swap-deployment {{ .Chart.Name }}:backend --mount=/tmp/app --docker-run -v `pwd`:/app -v /tmp/app/var/run/secrets:/var/run/secrets -ti registry.site.com/group/app/backend:v8
#########################################################################
Не будемо докладно зупинятися на описаних у цій інструкції кроках… крім останнього. Що відбувається під час запуску Telepresence?
Робота з Telepresence
При старті (за останньою командою, вказаною в інструкції вище) ми задаємо:
простір імен (namespace), у якому запущено мікросервіс;
імена deployment'а та контейнера, до якого хочемо проникнути.
Інші аргументи опціональні. Якщо наш сервіс взаємодіє з Kubernetes API та для нього створено ServiceAccount, нам необхідно змонтувати сертифікати/токени на свій робочий стіл. Для цього використовується опція --mount=true (або --mount=/dst_path), яка змонтує корінь (/) з контейнера Kubernetes до нас на desktop. Після цього ми можемо (залежно від ОС та способу запуску програми) скористатися ключами від кластера.
Спочатку розглянемо найуніверсальніший варіант запуску програми — в Docker-контейнері. Для цього скористаємося ключем --docker-run та примонтуємо директорію з кодом у контейнер: -v `pwd`:/app
Зверніть увагу, що тут мається на увазі запуск із каталогу з проектом. Код програми буде змонтований у директорію /app у контейнері.
Далі: -v /tmp/app/var/run/secrets:/var/run/secrets — для монтування директорії із сертифікатом/токеном у контейнер.
За цією опцією слід, нарешті, образ, в якому запускатиметься додаток. NB: При складанні образу треба обов'язково вказати CMD або ENTRYPOINT!
Що ж, власне, станеться далі?
У Kubernetes для вказаного Deployment'а кількість реплік буде змінено на 0. Замість нього запуститься новий Deployment — із підміненим контейнером backend.
На десктопі запустяться 2 контейнери: перший - з Telepresence (він здійснюватиме проксування запитів з/в Kubernetes), другий - з додатком, що розробляється.
Якщо exec'нуться в контейнер з додатком, то нам будуть доступні всі ENV-змінні, передані Helm'ом при депло, а також доступні всі сервіси. Залишається лише правити код у улюбленій IDE та насолоджуватися результатом.
Наприкінці роботи досить просто закрити термінал, у якому запущено Telepresence (оборвати сесію по Ctrl+C), — на робочому столі зупиняться Docker-контейнери, а в Kubernetes все повернеться до початкового стану. Залишиться лише комітнути, оформити MR і передати його на review/merge/… (залежно від ваших робочих процесів).
Якщо ми не хочемо запускати програму в Docker-контейнері — наприклад, ми розробляємо не на PHP, а на Go, і все-таки збираємо його локально, — запуск Telepresence буде ще простіше:
Якщо програма звертається до Kubernetes API, потрібно змонтувати директорію з ключами (https://www.telepresence.io/howto/volumes). Для Linux є утиліта корінь:
Після запуску Telepresence без опції --docker-run всі змінні оточення будуть доступні в поточному терміналі, тому запуск програми необхідно робити саме в ньому.
NB: При використанні, наприклад, PHP, потрібно не забувати відключати для розробки різні op_cache, apc та інші акселератори - інакше редагування коду не призводитиме до бажаного результату.
Підсумки
Локальна розробка з Kubernetes – проблема, потреба у вирішенні якої зростає пропорційно поширенню цієї платформи. Отримуючи відповідні запити з боку розробників (від наших клієнтів), ми почали їх вирішувати першими засобами, які, однак, не зарекомендували себе на довгій дистанції. Благо, це стало очевидним не тільки зараз і не тільки нам, тому у світі вже з'явилися більш підходящі кошти, і Telepresence — найвідоміший з них (до речі, є ще лісок від Google). Наш досвід його використання ще не такий великий, але вже дає підстави рекомендувати колегам по цеху - спробуйте!