Введение

В этом учебном модуле мы развернем контейнеризованное приложение Django polls в кластере Kubernetes.

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

В учебном модуле Создание приложения Django и Gunicorn с помощью Docker мы изменили приложение Polls из учебного модуля Django согласно методологии Двенадцать факторов, предназначенной для построения масштабируемых веб-приложений, оптимизированных для работы в облаке. Для масштабирования и защиты контейнера использовался обратный прокси-сервер Nginx и подписанный Let's Encrypt сертификат TLS (см. описание в учебном модуле Масштабирование и защита приложения Django с помощью Docker, Nginx и Let's Encrypt). В этом последнем учебном модуле из серии От контейнеров к Kubernetes с Django мы покажем, как развернуть модернизированное приложение Django polls в кластере Kubernetes.

Kubernetes — мощная система оркестрации контейнеров с открытым исходным кодом, помогающая автоматизировать развертывание, масштабирование и управление контейнеризованными приложениями. Такие объекты Kubernetes как ConfigMaps и Secrets позволяют централизовать конфигурацию и отсоединить ее от контейнеров, а такие контроллеры как Deployments автоматически перезагружают неработающие контейнеры и позволяют быстро масштабировать реплики контейнеров. Шифрование TLS активируется с помощью объекта Ingress и контроллера ingress-nginx с открытым исходным кодом. Надстройка Kubernetes cert-manager проверяет и выпускает сертификаты, используя бесплатный центр сертификации Let's Encrypt.

Предварительные требования

django illustration for: Предварительные требования

Для данного обучающего модуля вам потребуется следующее:

  • Инструмент командной строки kubectl, установленный на локальном компьютере и настроенный для подключения к вашему кластеру. Дополнительную информацию об установке kubectl можно найти в официальной документации. Если вы используете кластер Kubernetes, ознакомьтесь с руководством Подключение к кластеру Kubernetes, чтобы узнать, как подключиться к кластеру с помощью kubectl.
  • Зарегистрированное доменное имя. В этом учебном модуле мы будем использовать имя your_domain.com. Вы можете получить бесплатный домен на Freenom или зарегистрировать доменное имя по вашему выбору.
  • Запись DNS A для your_domain.com, указывающая на публичный IP-адрес балансировщика нагрузки Ingress. Если вы используете the cloud provider для управления записями DNS вашего домена, руководство Управление записями DNS поможет вам научиться создавать записи класса A.
  • Экземпляр сервера PostgreSQL, база данных и пользователь для приложения Django. Внеся незначительные изменения, вы можете использовать любую базу данных, которую поддерживает Django.
  • База данных PostgreSQL должна называться polls (можно использовать любое другое запоминающееся имя для ввода в файлы конфигурации ниже). В качестве имени пользователя базы данных Django в данном учебном модуле будет использоваться sammy. Инструкции, как это сделать, см. в шаге 1 руководства Создание приложения Django и Gunicorn с помощью Docker. Эти действия следует выполнять на локальном компьютере.
  • Учетная запись Docker Hub и публичный репозиторий. Более подробную информацию по их созданию можно найти в разделе Repositories (Репозитории) в документации по Docker.

Проверив наличие этих компонентов, вы можете начать прохождение этого обучающего модуля.

Шаг 1 — Клонирование и настройка приложения

На этом шаге мы клонируем код приложения с GitHub и настроим такие параметры, как учетные данные БД и ключи хранения объектов.

Код приложения и файл Dockerfile можно найти в ветви polls-docker репозитория Django Tutorial Polls App на GitHub. Этот репозиторий содержит код приложения Polls, используемого в документации по Django в качестве образца, на примере которого показывается, как создать приложение для опросов с нуля.

Ветвь polls-docker содержит размещенную в контейнере Docker версию приложения Polls. Более подробную информацию об изменениях, внесенных в приложение Polls для эффективной работы в контейнеризированной среде, можно найти в руководстве Создание приложения Django и Gunicorn с помощью Docker.

Для начала используйте git, чтобы клонировать ветвь polls-docker репозитория Django Tutorial Polls App на GitHub на локальном компьютере:

				
					
git clone --single-branch --branch polls-docker https://github.com/do-community/django-polls.git

				
			

Перейдите в каталог django-polls:

				
					
cd django-polls

				
			

В этом каталоге содержится код Python приложения Django, файл Dockerfile, который Docker будет использовать для построения образа контейнера, а также файл env, содержащий список переменных среды для передачи в рабочую среду контейнера. Проверьте файл Dockerfile:

				
					
cat Dockerfile

				
			
				
					
[secondary_label Output]

FROM python:3.7.4-alpine3.10



ADD django-polls/requirements.txt /app/requirements.txt



RUN set -ex \

    && apk add --no-cache --virtual .build-deps postgresql-dev build-base \

    && python -m venv /env \

    && /env/bin/pip install --upgrade pip \

    && /env/bin/pip install --no-cache-dir -r /app/requirements.txt \

    && runDeps="$(scanelf --needed --nobanner --recursive /env \

        | awk '{ gsub(/,/, "\nso:", $2); print "so:" $2 }' \

        | sort -u \

        | xargs -r apk info --installed \

        | sort -u)" \

    && apk add --virtual rundeps $runDeps \

    && apk del .build-deps



ADD django-polls /app

WORKDIR /app



ENV VIRTUAL_ENV /env

ENV PATH /env/bin:$PATH



EXPOSE 8000



CMD ["gunicorn", "--bind", ":8000", "--workers", "3", "mysite.wsgi"]

				
			

В качестве базы в файле Dockerfile используется официальный образ Docker Python 3.7.4, который устанавливает требуемые пакеты Python для Django и Gunicorn в соответствии с файлом django-polls/requirements.txt. Затем он удаляет некоторые ненужные файлы сборки, копирует код приложения в образ и устанавливает параметр выполнения PATH. И в заключение заявляет, что порт 8000 будет использоваться для принятия входящих подключений контейнера, и запускает gunicorn с тремя рабочими элементами, прослушивающими порт 8000.

Дополнительную информацию о каждом этапе в Dockerfile см. в шаге 6 руководства Создание приложения Django и Gunicorn с помощью Docker.

Теперь создайте образ с помощью docker build:

				
					
docker build -t polls .

				
			

Назовем образ polls, используя флаг -t, и передадим в текущий каталог как *контекст сборки* набор файлов для справки при построении образа.

После того как Docker создаст и отметит образ, перечислите доступные образы, используя docker images:

				
					
docker images

				
			

Вы должны увидеть образ polls:

				
					
OutputREPOSITORY          TAG                 IMAGE ID            CREATED             SIZE

polls               latest              80ec4f33aae1        2 weeks ago         197MB

python              3.7.4-alpine3.10    f309434dea3a        8 months ago        98.7MB

				
			

Перед запуском контейнера Django нам нужно настроить его рабочую среду с помощью файла env, присутствующего в текущем каталоге. Этот файл передается в команду docker run, которая используется для запуска контейнера, после чего Docker внедрит настроенные переменные среды в рабочую среду контейнера.

Откройте файл env с помощью nano или своего любимого редактора:

				
					
nano env

				
			
				
					
[label django-polls/env]

DJANGO_SECRET_KEY=

DEBUG=True

DJANGO_ALLOWED_HOSTS=

DATABASE_ENGINE=postgresql_psycopg2

DATABASE_NAME=polls

DATABASE_USERNAME=

DATABASE_PASSWORD=

DATABASE_HOST=

DATABASE_PORT=

STATIC_ACCESS_KEY_ID=

STATIC_SECRET_KEY=

STATIC_BUCKET_NAME=

STATIC_ENDPOINT_URL=

DJANGO_LOGLEVEL=info

				
			

Заполните недостающие значения для следующих ключей:

  • DJANGO_ALLOWED_HOSTS: эта переменная защищает приложение и предотвращает атаки через заголовки хоста HTTP. С целью тестирования установите * как подстановочный символ, подходящий для всех хостов. В производственной среде следует использовать значение your_domain.com. Дополнительную информацию об этой настройке Django см. в разделе Core Settings (Базовые настройки) документации Django.
  • DATABASE_USERNAME: задает пользователя базы данных PostgreSQL, созданного на предварительных этапах.
  • DATABASE_NAME: задает polls или имя базы данных, созданной на предварительных этапах.
  • DATABASE_PASSWORD: задает пароль пользователя базы данных PostgreSQL, созданного на предварительных этапах.
  • DATABASE_HOST: задает имя хоста базы данных.
  • DATABASE_PORT: укажите порт вашей базы данных.
  • STATIC_ACCESS_KEY_ID: укажите ключ доступа своего пространства или хранилища объектов.
  • STATIC_SECRET_KEY: укажите секретный ключ своего пространства или хранилища объектов.
  • STATIC_BUCKET_NAME: укажите имя своего пространства или корзину хранилища объектов.
  • STATIC_ENDPOINT_URL: укажите URL соответствующего пространства или конечного пункта хранилища объектов, например images/how-to-deploy-a-scalable-and-secure-django-application-with-kubernetes-ru-section-1.png, если ваше пространство находится в области nyc3.

После завершения редактирования сохраните и закройте файл.

На следующем шаге мы запустим настроенный контейнер в локальной среде и создадим схему базы данных. Также мы выгрузим в хранилище объектов статические ресурсы, такие как таблицы стилей и изображения.

Шаг 2 — Создание схемы базы данных и выгрузка ресурсов в хранилище объектов

После построения и настройки контейнера используйте docker run, чтобы заменить заданную команду CMD в файле Dockerfile и создайте схему базы данных, используя команды manage.py makemigrations и manage.py migrate:

				
					
docker run --env-file env polls sh -c "python manage.py makemigrations && python manage.py migrate"

				
			

Мы запускаем образ контейнера polls:latest, передаем в только что измененный файл переменной среды и переопределяем команду Dockerfile с помощью sh -c "python manage.py makemigrations && python manage.py migrate", которая создаст схему базы данных, определяемую кодом приложения.

Если запускаете эти команды впервые, вы должны увидеть следующее:

				
					
[secondary_label Output]

No changes detected

Operations to perform:

  Apply all migrations: admin, auth, contenttypes, polls, 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 polls.0001_initial... OK

  Applying sessions.0001_initial... OK

				
			

Это означает, что схема базы данных успешно создана.

При последующем запуске команды migrate Django не будет выполнять никаких операций, если схема базы данных не изменилась.

Затем мы запустим еще один экземпляр контейнера приложения и используем внутри него интерактивную оболочку для создания административного пользователя проекта Django.

				
					
docker run -i -t --env-file env polls sh

				
			

Вы получите строку оболочки внутри работающего контейнера, которую сможете использовать для создания пользователя Django:

				
					
python manage.py createsuperuser

				
			

Введите имя пользователя, адрес электронной почты и пароль для пользователя, а после создания пользователя нажмите CTRL+D для выхода из контейнера и его удаления.

В заключение мы создадим статические файлы приложения и загрузим их в пространство the cloud provider с помощью collectstatic. Обратите внимание, что для завершения процесса может потребоваться время.

				
					
docker run --env-file env polls sh -c "python manage.py collectstatic --noinput"

				
			

После создания и загрузки файлов вы получите следующий вывод.

				
					
[secondary_label Output]

121 static files copied.

				
			

Теперь мы можем запустить приложение:

				
					
docker run --env-file env -p 80:8000 polls

				
			
				
					
[secondary_label Output]

[2019-10-17 21:23:36 +0000] [1] [INFO] Starting gunicorn 19.9.0

[2019-10-17 21:23:36 +0000] [1] [INFO] Listening at: http://0.0.0.0:8000 (1)

[2019-10-17 21:23:36 +0000] [1] [INFO] Using worker: sync

[2019-10-17 21:23:36 +0000] [7] [INFO] Booting worker with pid: 7

[2019-10-17 21:23:36 +0000] [8] [INFO] Booting worker with pid: 8

[2019-10-17 21:23:36 +0000] [9] [INFO] Booting worker with pid: 9

				
			

Мы запустим определенную в Dockerfile команду по умолчанию gunicorn --bind :8000 --workers 3 mysite.wsgi:application и откроем порт контейнера 8000, чтобы установить соответствие порта 80 на локальном компьютере и порта 8000 контейнера polls.

Теперь у вас должна появиться возможность открыть приложение polls в браузере, для чего нужно ввести http://localhost в адресную строку. Поскольку маршрут для пути / не определен, скорее всего, вы получите ошибку 404 Страница не найдена.

Введите в адресную строку http://localhost/polls, чтобы увидеть интерфейс приложения Polls:

Чтобы открыть интерфейс администрирования, введите адрес http://localhost/admin. Вы должны увидеть окно аутентификации администратора приложения «Опросы»:

Введите имя администратора и пароль, которые вы создали с помощью команды createsuperuser.

После аутентификации вы сможете получить доступ к административному интерфейсу приложения «Опросы»:

Обратите внимание, что статические активы приложений admin и polls поступают напрямую из хранилища объекта. Чтобы убедиться в этом, ознакомьтесь с материалами Тестирование доставки статических файлов пространства.

После завершения изучения данных нажмите CTRL+C в окне терминала, где запущен контейнер Docker, чтобы удалить контейнер.

Когда образ Docker приложения Django будет протестирован, статичные ресурсы будут выгружены в хранилище объектов, а схема базы данных будет настроена и готова к выгрузке образа приложения Django в реестр образов, например в Docker Hub.

Шаг 3 — Размещение образа приложения Django в Docker Hub

Чтобы развернуть приложение в Kubernetes, необходимо будет выгрузить образ приложения в реестр, например, в Docker Hub. Kubernetes извлечет образ приложения из репозитория, а затем развернет его в кластере.

Вы можете использовать частный реестр Docker, например, реестр контейнеров container registry, предварительная версия которого в настоящее время предоставляется бесплатно, или публичный реестр Docker, такой как Docker Hub. Docker Hub также позволяет создавать частные репозитории Docker. Публичный репозиторий позволяет любому пользователю видеть и извлекать образы контейнеров, а в частном репозитории доступ имеется только у вас и у членов вашей команды.

В этом учебном модуле мы разместим образ Django в публичном репозитории Docker Hub, созданном на этапе предварительных требований. Также вы можете перенести образ в частный репозиторий, однако извлечение образов из частного репозитория в этой статье не описывается. Чтобы получить более подробную информацию об аутентификации Kubernetes с Docker Hub и извлечении образов из частного репозитория, ознакомьтесь со статьей Pull an Image from a Private Registry (Извлечение образа из частного реестра) в документации по Kubernetes.

Для начала выполните вход в Docker Hub на локальном компьютере:

				
					
docker login

				
			
				
					
[secondary_label Output]

Login with your Docker ID to push and pull images from Docker Hub. If you don't have a Docker ID, head over to https://hub.docker.com to create one.

Username:

				
			

Введите имя пользователя и пароль Docker Hub для входа в систему.

Образ Django сейчас помечен тегом polls:latest. Чтобы поместить его в ваш репозиторий Docker Hub, измените теги образа, указав свое имя пользователя Docker Hub и имя репозитория:

				
					
docker tag polls:latest <^>your_dockerhub_username<^>/<^>your_dockerhub_repo_name<^>:latest

				
			

Разместите образ в репозитории:

				
					
docker push <^>sammy<^>/<^>sammy-django<^>:latest

				
			

В этом учебном модуле мы используем имя пользователя Docker Hub sammy и имя репозитория sammy-django. Вам следует заменить эти значения своим именем пользователя Docker Hub и именем репозитория.

По мере размещения слоев образа в Docker Hub вы будете видеть на экране определенные сообщения.

Теперь ваш образ доступен Kubernetes в репозитории Docker Hub, и вы можете начать его развертывание в своем кластере.

Шаг 4 — Настройка ConfigMap

При локальном запуске контейнера Django мы передали файл env в docker run для вставки переменных конфигурации в среду исполнения. Для вставки переменных конфигурации в Kubernetes используются элементы ConfigMap и Secret.

Элементы ConfigMap следует использовать для сохранения неконфиденциальной информации о конфигурации, такой как параметры приложения, а элементы Secret следует использовать для хранения важной информации, такой как ключи API и учетные данные для входа в базу данных. Они вставляются в контейнеры примерно одинаково, но у элементов Secret имеются дополнительные функции контроля доступа и безопасности, такие как шифрование в состоянии покоя. Элементы Secret хранят данные в формате base64, а элементы ConfigMap хранят данные в формате обычного текста.

Для начала необходимо создать каталог yaml, где мы будем хранить наши манифесты Kubernetes. Перейдите в каталог.

				
					
mkdir yaml

cd

				
			

Откройте файл polls-configmap.yaml в nano или в другом предпочитаемом текстовом редакторе:

				
					
nano polls-configmap.yaml

				
			

Вставьте в него следующий манифест ConfigMap:

				
					
[label polls-configmap.yaml]

apiVersion: v1

kind: ConfigMap

metadata:

  name: polls-config

data:

  DJANGO_ALLOWED_HOSTS: "*"

  STATIC_ENDPOINT_URL: "images/how-to-deploy-a-scalable-and-secure-django-application-with-kubernetes-ru-section-1.png"

  STATIC_BUCKET_NAME: "<^>your_space_name<^>"

  DJANGO_LOGLEVEL: "info"

  DEBUG: "True"

  DATABASE_ENGINE: "postgresql_psycopg2"

				
			

Мы извлекли неконфиденциальные данные конфигурации из файла env, измененного на шаге 1, и передали их в манифест ConfigMap. Объект ConfigMap носит имя polls-config. Скопируйте те же самые значения, введенные в файл env на предыдущем шаге.

Для тестирования оставьте для DJANGO_ALLOWED_HOSTS значение *, чтобы отключить фильтрацию на основе заголовков хоста. В производственной среде здесь следует указать домен вашего приложения.

Когда вы завершите редактирование файла, сохраните и закройте его.

Создайте в своем кластере элемент ConfigMap, используя kubectl apply:

				
					
kubectl apply -f polls-configmap.yaml

				
			
				
					
[secondary_label Output]

configmap/polls-config created

				
			

Мы создали элемент ConfigMap, а на следующем шаге мы создадим элемент Secret, который будет использоваться нашим приложением.

Шаг 5 — Настройка элемента Secret

Значения Secret должны иметь кодировку base64, то есть создавать объекты Secret в кластере немного сложнее, чем объекты ConfigMaps. Вы можете повторить описанную на предыдущем шаге процедуру, выполнив кодирование значений Secret в формате base64 вручную и вставив их в файл манифеста. Также вы можете создавать их, используя файл переменных среды, kubectl create и флаг --from-env-file, что мы и сделаем на этом шаге.

Мы снова используем файл env из шага 1, удалив переменные, вставленные в ConfigMap. Создайте копию файла env с именем polls-secrets в каталоге yaml:

				
					
cp ../env ./polls-secrets

				
			

Отредактируйте файл в предпочитаемом редакторе:

				
					
nano polls-secrets

				
			
				
					
[label polls-secrets]

DJANGO_SECRET_KEY=

DEBUG=True

DJANGO_ALLOWED_HOSTS=

DATABASE_ENGINE=postgresql_psycopg2

DATABASE_NAME=polls

DATABASE_USERNAME=

DATABASE_PASSWORD=

DATABASE_HOST=

DATABASE_PORT=

STATIC_ACCESS_KEY_ID=

STATIC_SECRET_KEY=

STATIC_BUCKET_NAME=

STATIC_ENDPOINT_URL=

DJANGO_LOGLEVEL=info

				
			

Удалите все переменные, вставленные в манифест ConfigMap. Когда вы закончите, содержимое файла должно выглядеть следующим образом:

				
					
[label polls-secrets]

DJANGO_SECRET_KEY=<^>your_secret_key<^>

DATABASE_NAME=polls

DATABASE_USERNAME=<^>your_django_db_user<^>

DATABASE_PASSWORD=<^>your_django_db_user_password<^>

DATABASE_HOST=<^>your_db_host<^>

DATABASE_PORT=<^>your_db_port<^>

STATIC_ACCESS_KEY_ID=<^>your_space_access_key<^>

STATIC_SECRET_KEY=<^>your_space_access_key_secret<^>

				
			

Обязательно используйте те же значения, что и на шаге 1. Закончив, сохраните и закройте файл.

Создайте в кластере объект Secret, используя kubectl create secret:

				
					
kubectl create secret generic polls-secret --from-env-file=poll-secrets

				
			
				
					
[secondary_label Output]

secret/polls-secret created

				
			

Здесь мы создадим объект Secret с именем polls-secret и передадим в него созданный нами файл secrets.

Вы можете проинспектировать объект Secret, используя kubectl describe:

				
					
kubectl describe secret polls-secret

				
			
				
					
[secondary_label Output]

Name:         polls-secret

Namespace:    default

Labels:       <none>

Annotations:  <none>



Type:  Opaque



Data

====

DATABASE_PASSWORD:     8 bytes

DATABASE_PORT:         5 bytes

DATABASE_USERNAME:     5 bytes

DJANGO_SECRET_KEY:     14 bytes

STATIC_ACCESS_KEY_ID:  20 bytes

STATIC_SECRET_KEY:     43 bytes

DATABASE_HOST:         47 bytes

DATABASE_NAME:         5 bytes

				
			

Мы сохранили конфигурацию вашего приложения в кластере Kubernetes, используя типы объектов Secret и ConfigMap. Мы готовы развернуть приложение в кластере.

Шаг 6 — Развертывание приложения Django с помощью контроллера Deployment

На этом шаге мы создадим Deployment для вашего приложения Django. Kubernetes Deployment — *контроллер*, который можно использовать для управления приложениями без состояния в вашем кластере. Контроллер — это контур управления, регулирующий рабочие задачи посредством вертикального масштабирования. Контроллеры также перезапускают и очищают неисправные контейнеры.

Контроллеры Deployment контролируют один или несколько подов. Под — это наименьшая развертываемая единица в кластере Kubernetes. Поды содержат один или несколько контейнеров. Чтобы узнать о различных типах рабочих задач, ознакомьтесь с учебным модулем Введение в Kubernetes.

Для начала откройте файл polls-deployment.yaml в предпочитаемом текстовом редакторе:

				
					
nano polls-deployment.yaml

				
			

Вставьте в него следующий манифест Deployment:

				
					
[label polls-deployment.yaml]

apiVersion: apps/v1

kind: Deployment

metadata:

  name: polls-app

  labels:

    app: polls

spec:

	replicas: 2

  selector:

    matchLabels:

      app: polls

  template:

    metadata:

      labels:

        app: polls

    spec:

      containers:

        - image: <^>your_dockerhub_username<^>/<^>app_repo_name<^>:latest

          name: polls

          envFrom:

          - secretRef:

              name: polls-secret

          - configMapRef:

              name: polls-config

          ports:

            - containerPort: 8000

              name: gunicorn

				
			

Введите соответствующее имя образа контейнера, ссылаясь на образ Django Polls, который вы разместили в Docker Hub на шаге 2.

Здесь мы определяем контроллер Kubernetes Deployment с именем polls-app и присваиваем ему пару ключ-значение app: polls. Мы указываем, что хотим запустить две реплики пода, определенного под полем template.

Используя envFrom с secretRef и configMapRef, мы указываем, что все данные из объектов polls-secret и polls-config следует вставить в контейнеры как переменные среды. Ключи ConfigMap и Secret становятся именами переменных среды.

В заключение мы откроем порт containerPort 8000 и назовем его gunicorn.

Чтобы узнать больше о настройке контроллеров Kubernetes Deployment, ознакомьтесь с разделом Deployments в документации по Kubernetes.

Когда вы завершите редактирование файла, сохраните и закройте его.

Создайте в кластере контроллер Deployment, используя kubectl apply -f:

				
					
kubectl apply -f polls-deployment.yaml

				
			
				
					
deployment.apps/polls-app created

				
			

Убедитесь, что контроллер Deployment развернут правильно, используя kubectl get:

				
					
kubectl get deploy polls-app

				
			
				
					
[secondary_label Output]

NAME        READY   UP-TO-DATE   AVAILABLE   AGE

polls-app   2/2     2            2           6m38s

				
			

Если вы столкнетесь с ошибкой или что-то не будет работать, вы можете использовать kubectl describe для проверки неработающего контроллера Deployment:

				
					
kubectl describe deploy

				
			

Чтобы проинспектировать два пода, используйте kubectl get pod:

				
					
kubectl get pod

				
			
				
					
[secondary_label Output]

NAME                         READY   STATUS    RESTARTS   AGE

polls-app-847f8ccbf4-2stf7   1/1     Running   0          6m42s

polls-app-847f8ccbf4-tqpwm   1/1     Running   0          6m57s

				
			

В кластеры запущены и работают две реплики вашего приложения Django. Чтобы получить доступ к приложению, вам нужно создать Kubernetes Service, и мы сделаем это на следующем шаге.

Шаг 7 — Предоставление внешнего доступа с использованием Service

На этом шаге мы создаем Service для нашего приложения Django. Kubernetes Service — это абстракция, позволяющая предоставить доступ к набору работающих подов как к сетевой службе. Используя Service, вы можете создать для вашего приложения стабильный конечный пункт, который не будет изменяться по мере уничтожения и воссоздания подов.

Существует несколько типов служб Service, в том числе службы ClusterIP, открывающие доступ к Service через внутренний IP-адрес кластера, службы NodePort, открывающие доступ к Service на каждом узле статического порта NodePort, и службы LoadBalancer, предоставляющие облачный балансировщик нагрузки для управления внешним трафиком подов вашего кластера (через порты NodePort, которые он создает автоматически). Чтобы узнать больше об этом, ознакомьтесь с разделом Service в документации по Kubernetes.

На заключительном шаге настройки мы используем службу ClusterIP Service, доступ к которой открыт через Ingress и контроллер Ingress, настроенный на этапе подготовки к этому учебному модулю. Сейчас мы убедимся, что все элементы работают корректно. Для этого мы создадим временную службу NodePort Service для доступа к приложению Django.

Для начала создайте файл с именем polls-svc.yaml в предпочитаемом редакторе:

				
					
nano polls-svc.yaml

				
			

Вставьте в него следующий манифест Service:

				
					
[label polls-svc.yaml]

apiVersion: v1

kind: Service

metadata:

  name: polls

  labels:

    app: polls

spec:

  type: NodePort

  selector:

    app: polls

  ports:

    - port: 8000

      targetPort: 8000

				
			

Здесь мы создаем службу NodePort под названием polls и присваиваем ей ярлык app: polls. Мы выберем поды серверной части с ярлыком app: polls и установим в качестве цели порты 8000.

Когда вы завершите редактирование файла, сохраните и закройте его.

Разверните Service с помощью команды kubectl apply:

				
					
kubectl apply -f polls-svc.yaml

				
			
				
					
[secondary_label Output]

service/polls created

				
			

Убедитесь, что служба была создана с использованием kubectl get svc:

				
					
kubectl get svc polls

				
			
				
					
[secondary_label Output]

NAME    TYPE       CLUSTER-IP       EXTERNAL-IP   PORT(S)          AGE

polls   NodePort   10.245.197.189   <none>        8000:32654/TCP   59s

				
			

Этот вывод показывает внутренний IP-адрес кластера службы и номер порта NodePort (32654). Чтобы подключиться к службе, нам потребуется внешний IP-адрес для нашего узла кластера:

				
					
kubectl get node -o wide

				
			
				
					
[secondary_label Output]

NAME                   STATUS   ROLES    AGE   VERSION   INTERNAL-IP   EXTERNAL-IP      OS-IMAGE                       KERNEL-VERSION          CONTAINER-RUNTIME

pool-7no0qd9e0-364fd   Ready    <none>   27h   v1.18.8   10.118.0.5    203.0.113.1   Debian GNU/Linux 10 (buster)   4.19.0-10-cloud-amd64   docker://18.9.9

pool-7no0qd9e0-364fi   Ready    <none>   27h   v1.18.8   10.118.0.4    203.0.113.2    Debian GNU/Linux 10 (buster)   4.19.0-10-cloud-amd64   docker://18.9.9

pool-7no0qd9e0-364fv   Ready    <none>   27h   v1.18.8   10.118.0.3    203.0.113.3   Debian GNU/Linux 10 (buster)   4.19.0-10-cloud-amd64   docker://18.9.9

				
			

Откройте в браузере приложение Polls, используя внешний IP-адрес и порт NodePort любого узла. С учетом приведенного выше вывода URL приложения будет выглядеть так: http://<^>203.0.113.1<^>:32654/polls.

Вы должны увидеть тот же интерфейс приложения Polls, который вы открыли локально на шаге 1:

Вы можете повторить ту же проверку, используя маршрут /admin: http://<^>203.0.113.1<^>:32654/admin. Вы увидите тот же интерфейс администрирования, что и раньше:

Мы развернули две реплики контейнера приложения Django Polls, используя Deployment. Также мы создали стабильный конечный пункт сети для этих двух реплик и обеспечили внешний доступ к ним через службу NodePort.

Заключительный шаг этого учебного модуля заключается в том, чтобы защитить внешний трафик нашего приложения, используя HTTPS. Для этого мы используем контроллер ingress-nginx, установленный на этапе предварительных требований, и создадим объект Ingress для перенаправления внешнего трафика в службу Kubernetes polls.

Шаг 8 — Настройка HTTPS с использованием Nginx Ingress и cert-manager

Сущности Ingress в Kubernetes обеспечивают гибкую маршрутизацию внешнего трафика кластера Kubernetes среди служб внутри кластера. Это достигается с помощью ресурсов Ingress, которые определяют правила маршрутизации трафика HTTP и HTTPS для служб Kubernetes, и *контроллеров* Ingress, которые реализуют правила посредством балансировки нагрузки трафика и его перенаправления на соответствующие службы серверной части.

На этапе предварительных требований мы установили контроллер ingress-nginx и надстройку cert-manager для автоматизации сертификатов TLS. Также мы настроили испытательную и производственную среду ClusterIssuers для вашего домена, используя центр сертификации Let's Encrypt, и создали объект Ingress для проверки выдачи сертификатов и шифрования TLS для двух фиктивных серверных служб. Прежде чем продолжить выполнение этого шага, удалите объект echo-ingress, созданный в подготовительном учебном модуле:

				
					
kubectl delete ingress echo-ingress

				
			

При желании вы также можете удалить фиктивные службы и развертывания, используя команды kubectl delete svc и kubectl delete deploy, но для прохождения этого учебного модуля это не обязательно.

Также вы должны были создать запись DNS типа A для <^>your_domain.com<^>, указывающую на публичный IP-адрес балансировщика нагрузки Ingress. Если вы используете балансировщик нагрузки the cloud provider, вы можете найти этот IP-адрес в разделе Load Balancers панели управления. Если вы также используете the cloud provider для управления записями DNS вашего домена, руководство Управление записями DNS поможет вам научиться создавать записи класса A.

Если вы используете Kubernetes, убедитесь, что вы внедрили обходное решение, описанное в шаге 5 учебного модуля Настройка Nginx Ingress с помощью Cert-Manager в Kubernetes).

Когда у вас будет запись A, указывающая на балансировщик нагрузки контроллера Ingress, вы можете создать Ingress для <^>your_domain.com<^> и службы polls.

Откройте файл с именем polls-ingress.yaml в предпочитаемом текстовом редакторе:

				
					
nano polls-ingress.yaml

				
			

Вставьте следующий манифест Ingress:

				
					
[polls-ingress.yaml]

apiVersion: networking.k8s.io/v1beta1

kind: Ingress

metadata:

  name: polls-ingress

  annotations:

    kubernetes.io/ingress.class: "nginx"

    cert-manager.io/cluster-issuer: "letsencrypt-staging"

spec:

  tls:

  - hosts:

    - &lt;^&gt;your_domain.com&lt;^&gt;

    secretName: polls-tls

  rules:

  - host: &lt;^&gt;your_domain.com&lt;^&gt;

    http:

      paths:

      - backend:

          serviceName: polls

          servicePort: 8000

				
			

Мы создаем объект Ingress под именем polls-ingress и добавляем к нему аннотацию, чтобы уровень управления использовал контроллер ingress-nginx и размещение ClusterIssuer. Также мы включаем TLS для домена your_domain.com и сохраняем сертификат и закрытый ключ в объекте Secret с именем polls-tls. В заключение мы определяем правило перенаправления трафика для хоста your_domain.com в службу polls через порт 8000.

Когда вы завершите редактирование файла, сохраните и закройте его.

Создайте в кластере объект Ingress, используя kubectl apply:

				
					
kubectl apply -f polls-ingress.yaml

				
			
				
					
[secondary_label Output]

ingress.networking.k8s.io/polls-ingress created

				
			

Вы можете использовать kubectl describe для отслеживания состояния только что созданного объекта Ingress:

				
					
kubectl describe ingress polls-ingress

				
			
				
					
[secondary_label Output]

Name:             polls-ingress

Namespace:        default

Address:          workaround.your_domain.com

Default backend:  default-http-backend:80 (&lt;error: endpoints "default-http-backend" not found&gt;)

TLS:

  polls-tls terminates your_domain.com

Rules:

  Host        Path  Backends

  ----        ----  --------

  your_domain.com

                 polls:8000 (10.244.0.207:8000,10.244.0.53:8000)

Annotations:  cert-manager.io/cluster-issuer: letsencrypt-staging

              kubernetes.io/ingress.class: nginx

Events:

  Type    Reason             Age   From                      Message

  ----    ------             ----  ----                      -------

  Normal  CREATE             51s   nginx-ingress-controller  Ingress default/polls-ingress

  Normal  CreateCertificate  51s   cert-manager              Successfully created Certificate "polls-tls"

  Normal  UPDATE             25s   nginx-ingress-controller  Ingress default/polls-ingress

				
			

Также вы можете запустить команду describe для сертификата polls-tls, чтобы убедиться, что он был успешно создан:

				
					
kubectl describe certificate polls-tls

				
			
				
					
[secondary_label Output]

. . .

Events:

  Type    Reason     Age    From          Message

  ----    ------     ----   ----          -------

  Normal  Issuing    3m33s  cert-manager  Issuing certificate as Secret does not exist

  Normal  Generated  3m32s  cert-manager  Stored new private key in temporary Secret resource "polls-tls-v9lv9"

  Normal  Requested  3m32s  cert-manager  Created new CertificateRequest resource "polls-tls-drx9c"

  Normal  Issuing    2m58s  cert-manager  The certificate has been successfully issued

				
			

Это подтверждает, что сертификат TLS успешно выдан, и шифрование HTTPS для домена your_domain.com активно.

Поскольку мы использовали тестовую версию ClusterIssuer, большинство браузеров не будут доверять поддельному сертификату Let's Encrypt, который она выдает, и поэтому при переходе по адресу your_domain.com появится страница с сообщением об ошибке.

Чтобы отправить тестовый запрос, мы используем wget из командной строки:

				
					
wget -O - http://&lt;^&gt;your_domain.com&lt;^&gt;/polls

				
			
				
					
[secondary_label Output]

. . .

ERROR: cannot verify your_domain.com's certificate, issued by ‘CN=Fake LE Intermediate X1’:

  Unable to locally verify the issuer's authority.

To connect to your_domain.com insecurely, use `--no-check-certificate'.

				
			

Мы используем предлагаемый флаг --no-check-certificate, чтобы пропустить проверку сертификата:

				
					
wget --no-check-certificate -q -O - http://your_domain.com/polls

				
			
				
					
[secondary_label Output]





&lt;link rel="stylesheet" type="text/css" href="https://www.progressiverobot.com/images/how-to-deploy-a-scalable-and-secure-django-application-with-kubernetes-ru-section-1.png"&gt;





    &lt;p&gt;No polls are available.&lt;/p&gt;

				
			

В этом выводе показан код HTML для страницы интерфейса /polls, а также подтверждается выдача таблицы стилей из хранилища объектов.

Мы успешно проверили выдачу сертификата с помощью тестовой версии ClusterIssuer и теперь можем изменить Ingress для использования производственной версии ClusterIssuer.

Снова откройте файл polls-ingress.yaml для редактирования:

				
					
nano polls-ingress.yaml

				
			

Измените аннотацию cluster-issuer:

				
					
[polls-ingress.yaml]

apiVersion: networking.k8s.io/v1beta1

kind: Ingress

metadata:

  name: polls-ingress

  annotations:

    kubernetes.io/ingress.class: "nginx"

    cert-manager.io/cluster-issuer: "letsencrypt-&lt;^&gt;prod&lt;^&gt;"

spec:

  tls:

  - hosts:

    - &lt;^&gt;your_domain.com&lt;^&gt;

    secretName: polls-tls

  rules:

  - host: &lt;^&gt;your_domain.com&lt;^&gt;

    http:

      paths:

      - backend:

          serviceName: polls

          servicePort: 8000

				
			

Внесите необходимые изменения, после чего сохраните и закройте файл. Обновите Ingress, используя kubectl apply:

				
					
kubectl apply -f polls-ingress.yaml

				
			
				
					
[secondary_label Output]

ingress.networking.k8s.io/polls-ingress configured

				
			

Вы можете использовать команды kubectl describe certificate polls-tls и kubectl describe ingress polls-ingress для отслеживания статуса выдачи сертификата:

				
					
kubectl describe ingress polls-ingress

				
			
				
					
[secondary_label Output]

. . .

Events:

  Type    Reason             Age                From                      Message

  ----    ------             ----               ----                      -------

  Normal  CREATE             23m                nginx-ingress-controller  Ingress default/polls-ingress

  Normal  CreateCertificate  23m                cert-manager              Successfully created Certificate "polls-tls"

  Normal  UPDATE             76s (x2 over 22m)  nginx-ingress-controller  Ingress default/polls-ingress

  Normal  UpdateCertificate  76s                cert-manager              Successfully updated Certificate "polls-tls"

				
			

Приведенный выше вывод подтверждает, что новый производственный сертификат успешно выдан и сохранен в объекте Secret polls-tls.

Откройте в браузере адрес your_domain.com/polls, чтобы убедиться, что шифрование HTTPS включено, и все работает ожидаемым образом. Вы должны увидеть интерфейс приложения Polls:

Убедитесь, что в браузере включено шифрование HTTPS. Если вы используете Google Chrome, то если вышеуказанная страница откроется без ошибок, это будет означать, что все работает правильно. Кроме того, на панели URL должно быть изображение замка. Нажав на замок, вы сможете просмотреть детали сертификата Let's Encrypt.

Для окончательной очистки вы можете переключить тип службы polls с NodePort на внутренний тип ClusterIP.

Отредактируйте файл polls-svc.yaml в текстовом редакторе:

				
					
nano polls-svc.yaml

				
			

Измените type с NodePort на ClusterIP:

				
					
[label polls-svc.yaml]

apiVersion: v1

kind: Service

metadata:

  name: polls

  labels:

    app: polls

spec:

  type: &lt;^&gt;ClusterIP&lt;^&gt;

  selector:

    app: polls

  ports:

    - port: 8000

      targetPort: 8000

				
			

Когда вы завершите редактирование файла, сохраните и закройте его.

Разверните изменения с помощью команды kubectl apply:

				
					
kubectl apply -f polls-svc.yaml --force

				
			
				
					
[secondary_label Output]

service/polls configured

				
			

Убедитесь, что служба Service была изменена, используя kubectl get svc:

				
					
kubectl get svc polls

				
			
				
					
[secondary_label Output]

NAME    TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)    AGE

polls   ClusterIP   10.245.203.186   &lt;none&gt;        8000/TCP   22s

				
			

Этот вывод показывает, что тип Service — ClusterIP. Для доступа можно использовать только домен и Ingress, созданный на этом шаге.

Заключение

В этом учебном модуле мы развернули масштабируемое приложение Django с защитой HTTPS в кластере Kubernetes. Статичный контент выдается напрямую из хранилища объектов, а количество работающих подов можно быстро увеличивать или уменьшать, используя поле replicas в манифесте Deployment polls-app.

Если вы используете пространство the cloud provider Space, вы также можете включить доставку статичных ресурсов через сеть доставки контента и создать настраиваемый субдомен для своего пространства. Дополнительную информацию можно найти в разделе Включение CDN учебного модуля Настройка масштабируемого приложения Django с управляемыми базами данных и пространствами the cloud provider.

С остальными частями серии можно ознакомиться на странице От контейнеров к Kubernetes с Django.