Python: Разработка Django на Kubernetes с помощью DevSpace

Левент Огут

Возможности, которые Kubernetes привнес в пространство оркестровки контейнеров, огромны. Kubernetes упрощает развертывание и эксплуатацию таких систем. Однако, с точки зрения разработчика, это может быть не так просто, как их предыдущие рабочие процессы; есть некоторые нюансы системы, которые необходимо изучить. DevSpace — это инструмент, который устраняет этот пробел и помогает обеспечить лучший опыт разработчика. В этой статье мы будем использовать DevSpace для разработки и развертывания приложения на основе популярного и многофункционального Python-фреймворка Django.

Требования и настройка среды разработки

Для продолжения работы вам понадобятся три инструмента, а именно 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

Оцените статью
Procodings.ru
Добавить комментарий