Левент Огут
Kubernetes ставит перед разработчиками определенные задачи. Им нужно изучить некоторые новые концепции, как они связаны друг с другом, и, самое главное, как разрабатывать приложения с использованием кластера Kubernetes. Но чем больше времени они тратят на изучение этих тем, тем меньше времени у них остается на создание приложений. DevSpace — это швейцарский армейский нож для разработчиков, который устраняет этот пробел исключительно хорошо. Инструкции DevSpace распространяются в виде простого YAML-файла в репозитории для всей команды.
DevSpace призван облегчить жизнь разработчикам, предоставляя широкий спектр инструментов. Различные функции DevSpace позволяют разработчику не беспокоиться о среде Kubernetes. Вместо этого он позволяет разработчику вести разработку так, как он делал бы это на своей локальной машине.
Некоторые возможности DevSpace, включая, но не ограничиваясь ими:
- Развертывание с помощью Helm, kubectl
- Модификация Dockerfile в памяти во время выполнения
- Инструменты разработки, такие как синхронизация файлов, агрегация журналов.
- Пользовательские хуки — это действия, которые выполняются на основе событий.
- Пользовательские команды, с помощью которых можно собрать сложные или длинные команды в одну подкоманду.
- Пользовательские профили могут использоваться для изменения чего-либо в
devspace.yaml
и Dockerfile с помощью операций add, patch, remove и merge. Профили дают возможность использовать различные конфигурации для определенных типов развертывания, например, staging, production, testing.
- Требования
- Разработка в DevSpace
- Добавление кэша (Memcached)
- Добавление значений окружения в развертывание
- Настройки кэширования Flask
- Проверка статистики кэша
- Создайте новую конечную точку
- Развертывание в производство
- Устранение неполадок с Devspace
- Журналы
- Вход в контейнеры
- Выполнение команд внутри контейнера
- Очистка
- Заключение
- Дальнейшее чтение
Требования
Помимо доступа к кластеру Kubernetes — удаленному или локальному — нам необходимо установить три инструмента CLI, если они еще не установлены.
- Kubectl.
- Helm.
- DevSpace.
Для продолжения работы вам также понадобится Python-проект на основе Flask; если у вас нет проекта, вы можете использовать представленный здесь код или обратиться к документации Flask о том, как его создать.
Разработка в DevSpace
Все действия DevSpace зависят от его конфигурационного файла devspace.yaml
. Поскольку у нас нет такого файла, давайте попросим помощи у DevSpace. Запуск devspace init
проанализирует текущую папку, задаст несколько вопросов и создаст минимальный файл devspace.yaml
. Этот конфигурационный файл будет описывать все наши развертывания, зависимости, хуки, специальные команды и так далее.
$ devspace init
____ ____
| _ _____ __/ ___| _ __ __ _ ___ ___
| | | |/ _ / /___ | '_ / _` |/ __/ _
| |_| | __/ V / ___) | |_) | (_| | (_| __/
|____/ ___| _/ |____/| .__/ __,_|______|
|_|
? How do you want to deploy this project? helm: Use Component Helm Chart [QUICKSTART] (https://devspace.sh/component-chart/docs)
? How should DevSpace build the container image for this project? Create a new Dockerfile for this project
? Select the programming language of this project python
[info] DevSpace does *not* require pushing your images to a registry but let's assume you wanted to do that (optional)
? Which registry would you want to use to push images to? (optional, choose any) Use hub.docker.com => you are logged in as leventogut
[done] √ Great! You are authenticated with hub.docker.com
[info] Configuration saved in devspace.yaml - you can make adjustments as needed
[done] √ Project successfully initialized
You can now run:
- `devspace use namespace` to pick which Kubernetes namespace to work in
- `devspace dev` to start developing your project in Kubernetes
- `devspace deploy -p production` to deploy your project to Kubernetes
- `devspace -h` to get a list of available commands
Убедитесь, что выбран правильный контекст Kubernetes.
$ kubectl config use-context docker-desktop
Switched to context "docker-desktop".
Также убедитесь, что выбрано правильное пространство имен.
$ devspace use namespace default
Мы будем использовать следующий код для нашего приложения.
#!/usr/bin/env python
from flask import Flask
app = Flask(__name__)
@app.route("/")
def hello_world():
return "<p>Hello, World!</p>"
if __name__ == '__main__':
app.run(debug=True, use_debugger=True, use_reloader=False)
Сохраните этот код в файл app.py в корневом каталоге проекта или используйте свой собственный проект Flask, если он у вас есть.
На этом этапе я советую вам посмотреть на devspace.yaml
, чтобы получить представление о сгенерированной конфигурации.
Поскольку Flash по умолчанию использует порт 5000, нам нужно исправить это в нашем devspace.yaml
в разделе dev.ports
.
Теперь давайте запустим devspace dev
.
$ devspace dev
[warn] Deploying into the 'default' namespace is usually not a good idea as this namespace cannot be deleted
[info] Using namespace 'default'
[info] Using kube context 'docker-desktop'
[info] Execute 'helm upgrade devspace-flask /Users/logut/.devspace/component-chart/component-chart-0.8.1.tgz --namespace default --values /var/folders/3h/tq577p717mdccgjpcgtcvqv80000gn/T/089143002 --install --kube-context docker-desktop'
[info] Execute 'helm list --namespace default --output json --kube-context docker-desktop'
[done] √ Deployed helm chart (Release revision: 2)
[done] √ Successfully deployed devspace-flask with helm
#########################################################
[info] DevSpace UI available at: http://localhost:8090
#########################################################
[done] √ Port forwarding started on 5000:5000 (default/devspace-flask-5f785f7fdd-6rx5f-devspace)
[0:sync] Waiting for pods...
[0:sync] Starting sync...
[0:sync] Sync started on /Users/logut/dev/loft/devspace-flask <-> . (Pod: default/devspace-flask-5f785f7fdd-6rx5f-devspace)
[0:sync] Waiting for initial sync to complete
[info] Opening 'http://localhost:8080' as soon as application will be started (timeout: 4m0s)
[info] Opening shell to pod:container devspace-flask-5f785f7fdd-6rx5f-devspace:container-0
Installing Python Dependencies
Requirement already satisfied: click==8.0.1 in /usr/local/lib/python3.9/site-packages (from -r requirements.txt (line 1)) (8.0.1)
Requirement already satisfied: Flask==2.0.1 in /usr/local/lib/python3.9/site-packages (from -r requirements.txt (line 2)) (2.0.1)
Requirement already satisfied: itsdangerous==2.0.1 in /usr/local/lib/python3.9/site-packages (from -r requirements.txt (line 3)) (2.0.1)
Requirement already satisfied: Jinja2==3.0.1 in /usr/local/lib/python3.9/site-packages (from -r requirements.txt (line 4)) (3.0.1)
Requirement already satisfied: MarkupSafe==2.0.1 in /usr/local/lib/python3.9/site-packages (from -r requirements.txt (line 5)) (2.0.1)
Requirement already satisfied: Werkzeug==2.0.1 in /usr/local/lib/python3.9/site-packages (from -r requirements.txt (line 6)) (2.0.1)
WARNING: Running pip as root will break packages and permissions. You should install packages reliably by using venv: https://pip.pypa.io/warnings/venv
WARNING: You are using pip version 21.1.2; however, version 21.2.4 is available.
You should consider upgrading via the '/usr/local/bin/python -m pip install --upgrade pip' command.
____ ____
| _ _____ __/ ___| _ __ __ _ ___ ___
| | | |/ _ / /___ | '_ / _` |/ __/ _
| |_| | __/ V / ___) | |_) | (_| | (_| __/
|____/ ___| _/ |____/| .__/ __,_|______|
|_|
Welcome to your development container!
This is how you can work with it:
- Run `python main.py` to build the application
- Files will be synchronized between your local machine and this container
- Some ports will be forwarded, so you can access this container on your local machine via localhost:
Image ImageSelector LabelSelector Ports (Local:Remote)
imagerepo-repo1/app 5000:5000
root@devspace-flask-7c4bd546-nfmzf-devspace:/app#
Запустим наше приложение.
root@devspace-flask-7c4bd546-nfmzf-devspace:/app# python app.py
* Serving Flask app 'app' (lazy loading)
* Environment: production
WARNING: This is a development server. Do not use it in a production deployment.
Use a production WSGI server instead.
* Debug mode: on
* Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
* Restarting with stat
* Debugger is active!
* Debugger PIN: 276-822-672
Мы выбрали опцию отладки, чтобы сервер разработки Flask перезагружался при изменении файлов кода.
Команда devspace dev
выполнила несколько действий по настройке нашей среды разработки.
- Используя Helm, она развернула наше приложение на кластере Kubernetes с помощью диаграммы компонентов.
- Запустила перенаправление портов на порт 5000, чтобы мы могли получить доступ к приложению в том виде, в котором оно запущено локально.
- Настроил синхронизацию локальной папки в контейнер с помощью функции sync.
- Разобрали файл
requirement.txt
и установили все зависимости. - Используя функцию
dev.replacedPods
, заменил образ исходного контейнера на образ контейнера разработки. - Открыл оболочку в контейнере приложения. Обратите внимание, что это делается путем изменения инструкции
CMD
в Dockerfile, поэтому вам нужно самостоятельно запустить приложение, как показано выше.
По умолчанию DevSpace использует dev.replacedPods
для разработки. Возможность замены образа позволяет разработчику использовать другой образ с той же кодовой базой. Разработчик может создать образ с установленными инструментами отладки для использования в процессе разработки.
Теперь вы можете выйти из оболочки контейнера и завершить работу DevSpace. В следующем разделе будет добавлена функциональность кэширования, чтобы мы могли увидеть изменения, которые нужно сделать в нашем devspace.yaml
.
Добавление кэша (Memcached)
Давайте добавим решение для кэширования в наше приложение Flask. Это позволит нам настроить devspace.yaml
. Ниже приведен сниппет, который нам нужно добавить в раздел deployments в devspace.yaml
. Этот сниппет определяет развертывание с помощью helm с репозиторием Bitnami и графикой Memcached
. Мы также указываем версию графика.
- name: memcached
helm:
componentChart: false
chart:
name: memcached
version: 5.12.0
repo: https://charts.bitnami.com/bitnami
И измените раздел vars
следующим образом:
vars:
- name: CACHE_MEMCACHED_SERVERS
Добавление значений окружения в развертывание
Чтобы добавить значения окружения в нашу капсулу развертывания приложения, нам нужно определить их в разделе deployments; вам нужно только добавить раздел env в существующий devspace.yaml
.
- name: devspace-flask
# This deployment uses `helm` but you can also define `kubectl` deployments or kustomizations
helm:
# We are deploying the so-called Component Chart: https://devspace.sh/component-chart/docs
componentChart: true
# Under `values` we can define the values for this Helm chart used during `helm install/upgrade`
# You may also use `valuesFiles` to load values from files, e.g. valuesFiles: ["values.yaml"]
values:
containers:
- image: ${IMAGE} # Use the value of our `${IMAGE}` variable here (see vars above)
env:
- name: CACHE_MEMCACHED_SERVERS
value: $!{CACHE_MEMCACHED_SERVERS}
service:
ports:
- port: 5000
Поскольку вся наша конфигурация готова, теперь мы можем заполнить значения окружения для серверов кэша. Выполните следующую команду.
$ devspace list vars
DevSpace спросит вас, если не сможет найти значение для переменной окружения. Переменные в DevSpace могут быть получены из окружения, команд, ввода и жестко закодированных значений. Эти переменные могут быть использованы в любой части конфигурации.
? Please enter a value for CACHE_MEMCACHED_SERVERS memcached:11211
Variable Value
CACHE_MEMCACHED_SERVERS memcached:11211
IMAGE imagerepo-repo1/app
Далее нам нужно настроить наше приложение на использование кэширования.
Настройки кэширования Flask
Ниже приведены изменения, которые мы сделали, чтобы включить кэширование по пути /
. Во-первых, мы импортируем модуль кэширования, также настраиваем этот модуль для кэш-серверов; как вы заметили, здесь мы используем переменную окружения, ту, которую мы указывали в предыдущих разделах; далее, настраиваем приложение для кэша; наконец, добавляем декоратор кэша в нашу функцию route.
diff --git a/app.py b/app.py
index d26f024..f840dc3 100755
--- a/app.py
+++ b/app.py
@@ -1,11 +1,16 @@
#!/usr/bin/env python
from flask import Flask
+from flask_caching import Cache
+import os
-app = Flask(__name__)
+cache = Cache(config={'CACHE_TYPE': 'MemcachedCache','CACHE_MEMCACHED_SERVERS': [os.environ['CACHE_MEMCACHED_SERVERS']]})
+app = Flask(__name__)
+cache.init_app(app)
@app.route("/")
+@cache.cached(timeout=50)
def hello_world():
return "<p>Hello, World!</p>"
if __name__ == '__main__':
app.run(debug=True, use_debugger=True, use_reloader=False)
Вот версия, удобная для копирования-вставки.
#!/usr/bin/env python
from flask import Flask
from flask_caching import Cache
import os
cache = Cache(config={'CACHE_TYPE': 'MemcachedCache','CACHE_MEMCACHED_SERVERS': [os.environ['CACHE_MEMCACHED_SERVERS']]})
app = Flask(__name__)
cache.init_app(app)
@app.route("/")
@cache.cached(timeout=50)
def hello_world():
return "<p>Hello, World!</p>"
if __name__ == '__main__':
app.run(debug=True, use_debugger=True, use_reloader=False)
Теперь снова запустите devspace dev
, чтобы запустить нашу среду разработки.
Как только вы окажетесь в оболочке, выполните команду python app.py
, чтобы запустить сервер разработки.
root@devspace-flask-7c4bd546-nfmzf-devspace:/app# python app.py
* Serving Flask app 'app' (lazy loading)
* Environment: production
WARNING: This is a development server. Do not use it in a production deployment.
Use a production WSGI server instead.
* Debug mode: on
* Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
* Restarting with stat
* Debugger is active!
* Debugger PIN: 276-822-672
Теперь при посещении конечной точки /
будут создаваться записи в кэше.
root@devspace-flask-7c4bd546-nfmzf-devspace:/app# curl http://127.0.01:5000
<p>Hello, World!</p>
Мы также можем видеть запросы в журналах.
127.0.0.1 - - [21/Sep/2021 11:10:13] "GET / HTTP/1.1" 200 -
127.0.0.1 - - [21/Sep/2021 11:10:15] "GET / HTTP/1.1" 200 -
Проверка статистики кэша
Чтобы убедиться, что наш кэш работает так, как ожидалось, давайте подключимся к нему по telnet из контейнера приложения и посмотрим статистику. Вы можете установить telnet с помощью команды apt install -y telnet
.
root@devspace-flask-5f785f7fdd-6rx5f-devspace:/app# telnet memcached 11211
Trying 10.108.20.56...
Connected to memcached.default.svc.cluster.local.
Escape character is '^]'.
stats items
STAT items:2:number 1
STAT items:2:number_hot 0
STAT items:2:number_warm 0
STAT items:2:number_cold 1
STAT items:2:age_hot 0
STAT items:2:age_warm 0
STAT items:2:age 26
STAT items:2:mem_requested 101
STAT items:2:evicted 0
STAT items:2:evicted_nonzero 0
STAT items:2:evicted_time 0
STAT items:2:outofmemory 0
STAT items:2:tailrepairs 0
STAT items:2:reclaimed 1
STAT items:2:expired_unfetched 0
STAT items:2:evicted_unfetched 0
STAT items:2:evicted_active 0
STAT items:2:crawler_reclaimed 0
STAT items:2:crawler_items_checked 0
STAT items:2:lrutail_reflocked 0
STAT items:2:moves_to_cold 3
STAT items:2:moves_to_warm 2
STAT items:2:moves_within_lru 1
STAT items:2:direct_reclaims 0
STAT items:2:hits_to_hot 2
STAT items:2:hits_to_warm 1
STAT items:2:hits_to_cold 4
STAT items:2:hits_to_temp 0
END
Мы видим, что ответы уже кэшируются.
Мы развернули наше приложение в режиме разработки, мы добавили кэш в смесь, теперь давайте посмотрим на функцию синхронизации DevSpace. Это позволит нам продолжать разработку локально и видеть результаты в кластере Kubernetes.
Создайте новую конечную точку
Сначала отправьте пару запросов к конечной точке /ping
, проверьте, что ответ 404; затем отредактируйте файл app.py
и добавьте следующую функцию с декоратором route:
@app.route("/ping")
def ping():
return "pong"
С помощью этого небольшого кода мы создали конечную точку, которая возвращает pong
ответы на все запросы. Теперь снова отправьте несколько запросов, и ответ будет 200 с содержимым pong
.
Ниже приведен результат проделанных нами выше действий:
root@devspace-flask-7c4bd546-nfmzf-devspace:/app# python app.py
* Serving Flask app 'app' (lazy loading)
* Environment: production
WARNING: This is a development server. Do not use it in a production deployment.
Use a production WSGI server instead.
* Debug mode: on
* Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
* Restarting with stat
* Debugger is active!
* Debugger PIN: 276-822-672
127.0.0.1 - - [21/Sep/2021 11:29:44] "GET /ping HTTP/1.1" 404 -
127.0.0.1 - - [21/Sep/2021 11:29:49] "GET /ping HTTP/1.1" 404 -
* Detected change in '/app/app.py', reloading
* Restarting with stat
* Debugger is active!
* Debugger PIN: 276-822-672
127.0.0.1 - - [21/Sep/2021 11:29:50] "GET /ping HTTP/1.1" 200 -
127.0.0.1 - - [21/Sep/2021 11:29:51] "GET /ping HTTP/1.1" 200 -
Как вы можете видеть, до добавления кода конечная точка выдавала ошибку 404 not found; сразу после добавления кода мы видим код возврата 200 и текстовый ответ pong
. Важным аспектом этой установки является то, что мы используем debug=True
. Это заставляет сервер следить за локальными файлами Python и перезагружать их при изменениях. Таким образом, DevSpace обнаруживает изменения на вашей локальной машине, синхронизирует изменения с контейнером, сервер отладки обнаруживает изменения и перезагружает код. Эта операция позволяет нам разрабатывать локально и сразу же развертывать на кластере Kubernetes.
Развертывание в производство
DevSpace — это не только инструмент для разработки. Его можно использовать для развертывания в staging, production и даже в конвейерах CI/CD. С помощью функции Profiles вы можете создавать различные настройки развертывания для вашего приложения и его зависимостей. Изменения включают изменения Dockerfile
, изменения devspace.yaml
и так далее. Вы можете найти профиль production
в вашем начальном devspace.yaml
Вы можете выбрать профиль или несколько профилей, которые вы хотите использовать, следующим образом:
$ devspace deploy -p production
Устранение неполадок с Devspace
Журналы
По умолчанию DevSpace перебрасывает вас в оболочку контейнера приложения, чтобы вы могли выполнить любую команду и устранить ошибки. Вы также можете изменить это поведение так, чтобы журналы всех или некоторых (фильтрующих) контейнеров передавались в потоковом режиме.
Пока что откройте другой терминал и выполните следующую команду, чтобы увидеть все журналы контейнера.
$ devspace logs
Если вы не укажете контейнер, DevSpace спросит вас, журналы какого контейнера вы хотите получить.
? Select a container memcached-6c775fbd9d-hwbhf:memcached
[info] Printing logs of pod:container memcached-6c775fbd9d-hwbhf:memcached
memcached 14:11:52.97
memcached 14:11:52.97 Welcome to the Bitnami memcached container
memcached 14:11:52.97 Subscribe to project updates by watching https://github.com/bitnami/bitnami-docker-memcached
memcached 14:11:52.98 Submit issues and feature requests at https://github.com/bitnami/bitnami-docker-memcached/issues
memcached 14:11:52.98
memcached 14:11:52.98 INFO ==> ** Starting Memcached setup **
memcached 14:11:52.99 INFO ==> Initializing Memcached
memcached 14:11:53.00 INFO ==> ** Memcached setup finished! **
memcached 14:11:53.00 INFO ==> ** Starting Memcached **
Вход в контейнеры
Вы можете использовать DevSpace для управления развернутой средой. Одним из аспектов является быстрый вход в контейнеры. Не указывая имя контейнера, вы можете выбрать его из списка.
$ devspace enter
? Which pod do you want to open the terminal for? [Use arrows to move, type to filter]
> devspace-flask-7c4bd546-nfmzf-devspace:container-0
memcached-6c775fbd9d-hwbhf:memcached
Мы также можем указать имя контейнера напрямую с помощью флага -c
. Как видите, это намного проще, чем получать случайное имя стручка и затем указывать имя контейнера; DevSpace делает это автоматически для развернутого ресурса.
$ devspace enter -c container-0
[info] Opening shell to pod:container devspace-flask-7c4bd546-nfmzf-devspace:container-0
root@devspace-flask-7c4bd546-nfmzf-devspace:/app#
Выполнение команд внутри контейнера
Используя ту же подкоманду enter, мы можем выполнять команды непосредственно внутри контейнера.
$ devspace enter -c container-0 -- cat requirements.txt
[info] Opening shell to pod:container devspace-flask-7c4bd546-nfmzf-devspace:container-0
click==8.0.1
Flask==2.0.1
Flask-Caching==1.10.1
itsdangerous==2.0.1
Jinja2==3.0.1
MarkupSafe==2.0.1
python-memcached==1.59
six==1.16.0
Werkzeug==2.0.1
$ devspace enter -c memcached -- ps aux
[info] Opening shell to pod:container memcached-6c775fbd9d-hwbhf:memcached
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
1001 1 0.0 0.0 409280 3684 ? Ssl Sep20 0:44 memcached -u me
1001 58 0.0 0.0 7644 2700 pts/0 Rs+ 12:40 0:00 ps aux
В DevSpace также есть функция Commands, где вы можете создавать пользовательские команды для запуска локально или в определенном контейнере; это особенно полезно для длительных и подверженных ошибкам команд, которые вы хотите запустить.
Очистка
DevSpace предоставляет подкоманду, которая легко удаляет все развертывания и ресурсы (кроме PV/PVC), чтобы вы могли легко удалить среду разработки.
$ devspace purge
Заключение
Мы рассмотрели и реализовали некоторые возможности DevSpace, которые помогут разработчикам. Бесшовное развертывание, простота разработки — это мощные возможности. Кроме того, возможность распространять эту конфигурацию среди команды очень проста.
Существует множество функций DevSpace, о которых мы не успели рассказать. Чтобы узнать больше, ознакомьтесь с документацией или свяжитесь с нами в Kubernetes Slack в канале #devspace.
Дальнейшее чтение
- Документация DevSpace
- Документация по Flask
- Python: Разработка Django на Kubernetes с помощью DevSpace