Левент Огут
Возможности, которые Kubernetes привнес в пространство оркестровки контейнеров, огромны. Kubernetes упрощает развертывание и эксплуатацию таких систем. Однако, с точки зрения разработчика, это может быть не так просто, как их предыдущие рабочие процессы; есть некоторые нюансы системы, которые необходимо изучить. DevSpace — это инструмент, который устраняет этот пробел и помогает обеспечить лучший опыт разработчика. В этой статье мы будем использовать DevSpace для разработки и развертывания приложения на основе популярного и многофункционального Python-фреймворка Django.
- Требования и настройка среды разработки
- Разработка с помощью DevSpace
- Добавление базы данных (PostgreSQL)
- Добавление значений окружения в развертывание
- Изменение настроек базы данных Django
- Запуск миграции базы данных
- Создание образца приложения и представления
- Развертывание в производство
- Поиск и устранение неисправностей в DevSpace
- Журналы
- Вход в контейнеры
- Выполнение команд внутри контейнера
- Запуск тестов
- Очистка
- Заключение
- Дальнейшее чтение
Требования и настройка среды разработки
Для продолжения работы вам понадобятся три инструмента, а именно Kubectl, Helm и DevSpace. А также доступ к локальному или удаленному кластеру Kubernetes, подойдет любой кластер Kubernetes.
Вы можете найти инструкции по установке этих трех инструментов в следующих ссылках:
- Kubectl.
- Helm.
- DevSpace.
Разработка с помощью DevSpace
Первым шагом для настройки DevSpace является выполнение команды devspace init
для инициализации проекта. Эта команда задаст вам несколько вопросов, чтобы сгенерировать скелет конфигурации devspace.yaml
в соответствии с потребностями вашего проекта. Если у вас нет файла Dockerfile, он также будет создан для вас. Рекомендуется просмотреть конфигурацию devspace.yaml
, чтобы убедиться, что настройки подходят для вашего проекта. В 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
$
Установите правильный контекст для развертывания приложения.
$ kubectl config use-context docker-desktop
Switched to context "docker-desktop".
Кроме того, хорошей практикой является выбор пространства имен для разработки.
$ devspace use namespace myproject-namespace
Давайте установим нужные нам переменные, выполните следующую команду. Она запросит значения недостающих переменных:
$ devspace list vars
? Please enter a value for DB_PASSWORD ***********
Variable Value
DB_DATABASE django
DB_PASSWORD db.password
DB_PORT 5432
DB_USERNAME postgres
DB_VERSION 11.11.0
IMAGE leventogut/app
Теперь мы готовы выполнить команду devspace dev
, чтобы запустить нашу среду разработки. Эта команда развернет все компоненты, которые определены в файле devspace.yaml
. Также, по умолчанию, она откроет интерактивную консольную сессию для контейнера приложения. DevSpace создаст проброс портов, чтобы вы могли обращаться к приложению, используя локальный порт. Наконец, будет настроена синхронизация файлов между каталогом проекта и контейнером приложения.
$ 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 myproject /Users/logut/.devspace/component-chart/component-chart-0.8.0.tgz --namespace default --values /var/folders/3h/tq577p717mdccgjpcgtcvqv80000gn/T/478617250 --install --kube-context docker-desktop'
[info] Execute 'helm list --namespace default --output json --kube-context docker-desktop'
[done] √ Deployed helm chart (Release revision: 1)
[done] √ Successfully deployed myproject with helm
[done] √ Scaled down Deployment default/myproject
[done] √ Successfully replaced pod default/myproject-86cf556785-txfj5
[done] √ Port forwarding started on 8080:8080 (default/myproject-86cf556785-txfj5-devspace)
#########################################################
[info] DevSpace UI available at: http://localhost:8090
#########################################################
[0:sync] Waiting for pods...
[0:sync] Starting sync...
[0:sync] Sync started on /Users/logut/dev/loft/devspace-django/myproject <-> . (Pod: default/myproject-86cf556785-txfj5-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 myproject-86cf556785-txfj5-devspace:container-0
Installing Python Dependencies
Collecting asgiref==3.4.1
Downloading asgiref-3.4.1-py3-none-any.whl (25 kB)
Collecting Django==3.2.7
Downloading Django-3.2.7-py3-none-any.whl (7.9 MB)
|████████████████████████████████| 7.9 MB 7.8 MB/s
Collecting pytz==2021.1
Downloading pytz-2021.1-py2.py3-none-any.whl (510 kB)
|████████████████████████████████| 510 kB 9.7 MB/s
Collecting sqlparse==0.4.1
Downloading sqlparse-0.4.1-py3-none-any.whl (42 kB)
|████████████████████████████████| 42 kB 62 kB/s
Collecting psycopg2-binary==2.9.1
Using cached psycopg2_binary-2.9.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (3.4 MB)
Installing collected packages: sqlparse, pytz, asgiref, Django, psycopg2-binary
Successfully installed Django-3.2.7 asgiref-3.4.1 pytz-2021.1 sqlparse-0.4.1 psycopg2-binary-2.9.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)
leventogut/app 8080:8080
root@myproject-86cf556785-txfj5-devspace:/app#
В приведенном выше выводе DevSpace выполнил несколько действий:
- Развернуть наш проект в кластере Kubernetes с помощью диаграммы компонентов Helm.
- Запустить синхронизацию файлов
- Установить зависимости Python в соответствии с файлом requirement.txt
- Заменил фактический образ контейнера версией для разработки.
Наконец, мы попадаем в оболочку контейнера нашего приложения. Отсюда мы можем запускать команды внутри контейнера.
Важным моментом здесь является то, что по умолчанию DevSpace использует функцию replacedPods для разработки. Возможность замены образа позволяет разработчику использовать другой образ с той же кодовой базой. Разработчик может создать образ с установленными инструментами отладки, чтобы использовать его в процессе разработки, не влияя на развертывание на производстве. Если это нежелательно, вы можете удалить строфу replacedPods
в devspace.yaml
.
Добавление базы данных (PostgreSQL)
Чтобы добавить развертывание PostgreSQL, добавьте следующий фрагмент в раздел deployments.
- name: postgresql
helm:
componentChart: false
chart:
name: postgresql
version: 10.4.3
repo: https://charts.bitnami.com/bitnami
values:
image:
tag: $!{DB_VERSION}
postgresqlDatabase: $!{DB_DATABASE}
postgresqlUsername: $!{DB_USERNAME}
postgresqlPassword: $!{DB_PASSWORD}
service:
port: ${DB_PORT}
И измените раздел vars
следующим образом:
vars:
- name: IMAGE
value: leventogut/app
- name: DB_VERSION
value: 11.11.0
- name: DB_DATABASE
value: django
- name: DB_USERNAME
value: postgres
- name: DB_PASSWORD
password: true
- name: DB_PORT
value: 5432
- name: DB_HOST
Добавление значений окружения в развертывание
Чтобы добавить значения окружения в наш pod, нам нужно определить их в разделе deployments; вам нужно только добавить раздел env в существующий devspace.yaml
.
- name: myproject
# 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: DB_DATABASE
value: $!{DB_DATABASE}
- name: DB_HOST
value: $!{DB_HOST}
- name: DB_PORT
value: $!{DB_PORT}
- name: DB_USERNAME
value: $!{DB_USERNAME}
- name: DB_PASSWORD
value: $!{DB_PASSWORD}
service:
ports:
- port: 8080
Теперь повторно запустите devspace dev
, чтобы изменения вступили в силу.
Изменение настроек базы данных Django
Конфигурация базы данных находится в файле myproject>settings.py. Поскольку мы не хотим засекречивать наши конфиденциальные данные, мы будем использовать значения окружения.
В settings.py сначала импортируйте модуль os, чтобы мы могли использовать os.environ для получения значений из окружения:
import os
Затем перейдите в раздел DATABASES
, чтобы добавить значения окружения базы данных следующим образом.
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql',
'NAME': os.environ['DB_DATABASE'],
'USER': os.environ['DB_USERNAME'],
'PASSWORD': os.environ['DB_PASSWORD'],
'HOST': os.environ['DB_HOST'],
'PORT': os.environ['DB_PORT'],
}
}
Запуск миграции базы данных
Поскольку мы определили нашу базу данных PostgreSQL, теперь мы можем запустить миграции из нашей оболочки.
root@myproject-97954557-bzvp9-devspace:/app# ./manage.py migrate
Operations to perform:
Apply all migrations: admin, auth, contenttypes, sessions
Running migrations:
Applying contenttypes.0001_initial... OK
Applying auth.0001_initial... OK
Applying admin.0001_initial... OK
Applying admin.0002_logentry_remove_auto_add... OK
Applying admin.0003_logentry_add_action_flag_choices... OK
Applying contenttypes.0002_remove_content_type_name... OK
Applying auth.0002_alter_permission_name_max_length... OK
Applying auth.0003_alter_user_email_max_length... OK
Applying auth.0004_alter_user_username_opts... OK
Applying auth.0005_alter_user_last_login_null... OK
Applying auth.0006_require_contenttypes_0002... OK
Applying auth.0007_alter_validators_add_error_messages... OK
Applying auth.0008_alter_user_username_max_length... OK
Applying auth.0009_alter_user_last_name_max_length... OK
Applying auth.0010_alter_group_name_max_length... OK
Applying auth.0011_update_proxy_permissions... OK
Applying auth.0012_alter_user_first_name_max_length... OK
Applying sessions.0001_initial... OK
root@myproject-97954557-bzvp9-devspace:/app#
Все миграции успешно выполнены. Это встроенные в Django миграции модулей admin и auth, но тот же процесс применим и к нашим миграциям.
Наконец, мы можем запустить ./manage.py runserver 0.0.0.0:8080
, чтобы запустить сервер разработки в нашем контейнере.
root@myproject-97954557-bzvp9-devspace:/app# ./manage.py runserver 0.0.0.0:8080
Watching for file changes with StatReloader
Performing system checks...
System check identified no issues (0 silenced).
September 10, 2021 - 18:51:00
Django version 3.2.7, using settings 'myproject.settings'
Starting development server at http://0.0.0.0:8080/
Quit the server with CONTROL-C.
Давайте посетим приложение по URL http://localhost:8080
и посмотрим запросы в логах.
[11/Sep/2021 18:51:08] "GET / HTTP/1.1" 200 10697
[11/Sep/2021 18:51:08] "GET /static/admin/css/fonts.css HTTP/1.1" 200 423
[11/Sep/2021 18:51:08] "GET /static/admin/fonts/Roboto-Regular-webfont.woff HTTP/1.1" 200 85876
[11/Sep/2021 18:51:08] "GET /static/admin/fonts/Roboto-Bold-webfont.woff HTTP/1.1" 200 86184
[11/Sep/2021 18:51:08] "GET /static/admin/fonts/Roboto-Light-webfont.woff HTTP/1.1" 200 85692
Not Found: /favicon.ico
[11/Sep/2021 18:51:08] "GET /favicon.ico HTTP/1.1" 404 2113
[11/Sep/2021 18:52:07] "GET /admin HTTP/1.1" 301 0
[11/Sep/2021 18:52:07] "GET /admin/ HTTP/1.1" 302 0
[11/Sep/2021 18:52:07] "GET /admin/login/?next=/admin/ HTTP/1.1" 200 2214
[11/Sep/2021 18:52:07] "GET /static/admin/css/base.css HTTP/1.1" 200 19513
[11/Sep/2021 18:52:07] "GET /static/admin/css/nav_sidebar.css HTTP/1.1" 200 2271
[11/Sep/2021 18:52:07] "GET /static/admin/css/login.css HTTP/1.1" 200 939
[11/Sep/2021 18:52:07] "GET /static/admin/js/nav_sidebar.js HTTP/1.1" 200 1360
[11/Sep/2021 18:52:07] "GET /static/admin/css/responsive.css HTTP/1.1" 200 18545
[11/Sep/2021 18:52:07] "GET /static/admin/css/fonts.css HTTP/1.1" 304 0
[11/Sep/2021 18:52:07] "GET /static/admin/fonts/Roboto-Regular-webfont.woff HTTP/1.1" 304 0
[11/Sep/2021 18:52:07] "GET /static/admin/fonts/Roboto-Light-webfont.woff HTTP/1.1" 304 0
[11/Sep/2021 18:52:12] "POST /admin/login/?next=/admin/ HTTP/1.1" 200 2375
[11/Sep/2021 18:52:12] "GET /static/admin/fonts/Roboto-Bold-webfont.woff HTTP/1.1" 304 0
Наше приложение развернуто в режиме разработки в нашем кластере Kubernetes. Теперь мы можем начать разработку приложения локально, а DevSpace будет синхронизировать изменения с контейнером.
Создание образца приложения и представления
Мы будем использовать инструмент django-admin для создания нашего первого приложения для проекта. Если вы не знакомы с проектами и приложениями, пожалуйста, обратитесь сюда.
$ ../venv/bin/django-admin startapp myapp
Отредактируйте файл myproject/myapp/views.py
и добавьте следующий код:
from django.http import HttpResponse
from django.views import View
class MyView(View):
def get(self, request, *args, **kwargs):
return HttpResponse('pong')
Этот код создает представление и настраивает его на возврат pong
на все запросы.
Отредактируйте файл myproject/urls.py
и добавьте следующий код, чтобы мы приклеили путь ping/
к MyView:
from myapp.views import MyView
urlpatterns += [
path('ping/', MyView.as_view(), name='myview'),
]
Этот код добавляет путь к urlpatterns; ping/ связан с ранее созданным представлением.
Теперь посетите сайт http://localhost:8080/ping/, и вы должны увидеть pong
в качестве текстового ответа.
Обратите внимание, что мы не развертывали приложение в кластере Kubernetes. После изменения файлы синхронизируются из локальной папки в контейнер, чтобы мы могли разрабатывать наше приложение так же, как и локально. Это одна из мощных возможностей DevSpace.
Развертывание в производство
В DevSpace есть полезная функция под названием профили. Эта функция позволяет вам изменять саму конфигурацию на основе заданного профиля. Изменения настраиваются в строфе профилей и применяются с помощью флага -p
, например, devspace dev -p staging
.
devspace deploy -p production
Поиск и устранение неисправностей в DevSpace
Журналы
В конфигурации по умолчанию DevSpace открывает оболочку в контейнер; однако вы можете изменить это поведение и получить поток журналов одного или всех компонентов. Чтобы получить журналы, вы также можете использовать следующую команду.
$ devspace logs
Если вы не указали контейнер, DevSpace спросит вас, для какого контейнера вы хотите получить журналы.
? Select a container [Use arrows to move, type to filter]
> myproject-97954557-bzvp9-devspace:container-0
postgresql-postgresql-0:postgresql
[info] Printing logs of pod:container postgresql-postgresql-0:postgresql
postgresql 18:44:31.47
postgresql 18:44:31.47 Welcome to the Bitnami postgresql container
postgresql 18:44:31.47 Subscribe to project updates by watching https://github.com/bitnami/bitnami-docker-postgresql
postgresql 18:44:31.47 Submit issues and feature requests at https://github.com/bitnami/bitnami-docker-postgresql/issues
postgresql 18:44:31.48
postgresql 18:44:31.49 INFO ==> ** Starting PostgreSQL setup **
postgresql 18:44:31.51 INFO ==> Validating settings in POSTGRESQL_* env vars..
postgresql 18:44:31.51 INFO ==> Loading custom pre-init scripts...
postgresql 18:44:31.52 INFO ==> Initializing PostgreSQL database...
Вход в контейнеры
DevSpace позволяет вам входить в контейнеры с именем контейнера вместо обычного способа, используя длинное имя стручка, а затем имя контейнера.
Без каких-либо параметров он спросит вас, в какой стручок/контейнер вы хотите войти.
$ devspace enter
? Which pod do you want to open the terminal for? [Use arrows to move, type to filter]
> myproject-97954557-bzvp9-devspace:container-0
postgresql-postgresql-0:postgresql
Здесь мы специально выбираем container-0
для входа.
$ devspace enter -c container-0
[info] Opening shell to pod:container myproject-97954557-bzvp9-devspace:container-0
root@myproject-97954557-bzvp9-devspace:/app#
Выполнение команд внутри контейнера
DevSpace позволяет вам настраивать предопределенные команды в devspace.yaml
в строфе commands
. Также у вас есть возможность использовать следующий синтаксис для запуска команды в контейнере без конфигурации.
$ devspace enter -c container-0 ./manage.py
Здесь мы видим текст справки команды manage.py
, поскольку мы не погрузились в подкоманду или параметр.
[info] Opening shell to pod:container myproject-97954557-bzvp9-devspace:container-0
Type 'manage.py help <subcommand>' for help on a specific subcommand.
Available subcommands:
[auth]
changepassword
createsuperuser
...
...
Запуск тестов
У вас есть несколько вариантов запуска тестов. Вот простой пример:
$ devspace enter -c container-0 ./manage.py test
[info] Opening shell to pod:container myproject-97954557-bzvp9-devspace:container-0
System check identified no issues (0 silenced).
----------------------------------------------------------------------
Ran 0 tests in 0.000s
OK
Выполнение тестов очень похоже на то, как вы выполняли бы их в локальной среде. Также обратите внимание, что эту команду можно превратить в команду DevSpace, чтобы использовать ее как devspace run test
, и все указанные тесты будут запущены одной командой.
Очистка
DevSpace предоставляет подкоманду, которая легко удаляет все развертывания и ресурсы (кроме PV/PVC), так что вы можете легко удалить среду разработки.
$ devspace purge
Заключение
Мы рассмотрели, как настроить DevSpace в базовой среде Django. Мы также увидели, что DevSpace легко синхронизирует измененные файлы с запущенным контейнером, поэтому нам не нужно повторно развертывать приложение в кластере Kubernetes при каждом изменении. Эта синхронизация также работает для скомпилированных языков.
DevSpace обладает высокой степенью конфигурируемости и очень многофункционален, чтобы облегчить вам жизнь. Ознакомьтесь с документацией, чтобы узнать, как создавать команды, подключать крючки на основе событий, проверять зависимости и создавать профили для различных сред развертывания, таких как staging, production и CI/CD конвейеры.
Дальнейшее чтение
- Документация DevSpace
- Документация по Django
Фото Chris Ried on Unsplash