One place for hosting & domains

      Django

      Cómo implementar una aplicación Django escalable y segura con Kubernetes


      Introducción

      En este tutorial, implementará una aplicación de encuestas de Django en contenedor en un clúster de Kubernetes.

      Django es un poderoso framework web que puede ayudarle a poner en marcha rápidamente su aplicación o sitio web con Python. Incluye varias características convenientes como un mapeo objeto-relacional, la autenticación de usuarios y una interfaz administrativa personalizable para su aplicación. También incluye un marco de almacenamiento en caché y fomenta el diseño limpio de aplicaciones a través de su Despachador URL y sistema de Plantillas

      En Cómo crear una aplicación Django y Gunicorn con Docker, la aplicación de encuestas del Tutorial de Django fue modificada de acuerdo con la metodología de Twelve-Factor para crear aplicaciones web escalables y nativas en la nube. Esta configuración en contenedores se escaló y protegió con un proxy inverso Nginx y certificados TLS proporcionados por Let’s Encrypt en Cómo escalar y proteger una aplicación de Django con Docker, Nginx y Let’s Encrypt. En este tutorial final de la serie “De contenedores a Kubernetes con Django”, la aplicación de encuestas de Django modernizada se implementará en un clúster de Kubernetes.

      Kubernetes es un potente orquestador de contenedores de código abierto que automatiza la implementación, el escalamiento y la administración de aplicaciones en contenedores. Los objetos de Kubernetes, como ConfigMaps y Secrets, permiten centralizar y desvincular la configuración de los contenedores, mientras que los controladores como las implementaciones reinician automáticamente los contenedores fallidos y habilitar el escalamiento rápido de las réplicas de contenedores. El cifrado TLS se activa con un objeto Ingress y el controlador de Ingress de código abierto llamado ingress-nginx. El complemento cert-manager de Kubernetes renueva y emite certificados usando la autoridad de certificación de Let’s Encrypt gratuita.

      Requisitos previos

      Para seguir este tutorial, necesitará lo siguiente:

      • Un clúster de Kubernetes 1.15, o una versión posterior, con control de acceso basado en roles (RBCA) activado. Esta configuración usará un clúster de Kubernetes de DigitalOcean, pero puede crear un clúster usando otro método.
      • La herramienta de línea de comandos kubectl instalada en su equipo local y configurada para conectarse a su clúster. Puede leer más sobre la instalación de kubectl en la documentación oficial. Si está usando un clúster de Kubernetes de DigitalOcean, consulte Cómo conectarse a un clúster Kubernetes de DigitalOcean para aprender a conectarse a su clúster usando kubectl.
      • Un nombre de dominio registrado. Para este tutorial, se utilizará your_domain.com en todo momento. Puede obtener un ejemplar gratis en Freenom o utilizar el registrador de dominios que desee.
      • Un controlador de Ingress ingress-nginx y el administrador de certificados TLS cert-manager instalado en su clúster y configurado para emitir certificados TLS. Para aprender a instalar y configurar un Ingress con cert-manager, consulte Cómo configurar un Ingress de Nginx con Cert-Manager en Kubernetes de DigitalOcean.
      • Un registro DNS A con your_domain.com orientado a la dirección IP pública del equilibrador de cargas de Ingress. Si usa DigitalOcean para administrar los registros DNS de su dominio, consulte Cómo administrar registros DNS para aprender a crear registros A.
      • Un depósito de almacenamiento de objetos S3, como un Space de DigitalOcean, para almacenar los archivos estáticos de su proyecto de Django y un conjunto de claves de acceso para ese espacio. Para obtener información sobre cómo crear Spaces, consulte la documentación de Cómo crear Spaces. Para obtener información sobre cómo crear claves de acceso para Spaces, consulte Compartir el acceso a Spaces con claves de acceso. Con cambios menores, puede usar cualquier servicio de almacenamiento de objetos que admita el complemento django-storages
      • Una instancia de un servidor de PostgreSQL, una base de datos y un usuario para su aplicación de Django. Con cambios menores, puede usar cualquier base de datos que admita Django.
      • Un Docker Hub cuenta y repositorio público. Para obtener más información sobre cómo crearlos, consulte Repositorios de la documentación de Docker.
      • El motor Docker instalado en su máquina local. Consulte Cómo instalar y usar Docker en Ubuntu 18.04 para obtener más información.

      Una vez que haya configurado estos componentes, estará listo para comenzar con esta guía.

      Paso 1: Clonar y probar la aplicación

      En este paso, clonaremos el código de la aplicación de GitHub y configuraremos ajustes como las credenciales de la base de datos y las claves de almacenamiento de objetos.

      El código de la aplicación y Dockerfile se encuentran en la rama polls-docker del repositorio de GitHub de la aplicacipon Polls en el tutorial de Django. Este repositorio contiene el código para la aplicación Polls de muestra de la documentación de Django, que le enseña cómo crear una aplicación de encuestas desde cero.

      La rama polls-docker contiene una versión con Docker de esta aplicación Polls. Para obtener información sobre cómo se modificó la aplicación Polls para que funcionara de forma eficaz en un entorno de contenedores, consulte Cómo crear una aplicación de Django y Gunicorn con Docker.

      Comience usando git para clonar la rama polls-docker del repositorio de GitHub de la aplicación Polls del tutorial de Django en su máquina local:

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

      Diríjase al directorio django-polls:

      Este directorio contiene el código de Python de la aplicación de Django, un Dockerfile que Docker utilizará para crear la imagen del contenedor, y un archivo env que contiene una lista de las variables de entorno que se pasarán al entorno de ejecución del contenedor. Inspeccione el Dockerfile:

      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"]

      Este Dockerfile utiliza la imagen de Docker oficial de Python 3.7.4 como base e instala los requisitos del paquete de Python de Django y Gunicorn, tal como se define en el archivo django-polls/requirements.txt. A continuación, elimina algunos archivos de compilación innecesarios, copia el código de la aplicación en la imagen y establece el PATH de ejecución. Por último, declara que el puerto 8000 se utilizará para aceptar conexiones de contenedores entrantes y ejecuta gunicorn con 3 trabajadores, escuchando en el puerto 8000.

      Para obtener más información sobre cada uno de los pasos de este Dockerfile, consulte el Paso 6 de Cómo crear una aplicación de Django y Gunicorn con Docker.

      Ahora, compile la imagen con docker build:

      Nombramos la imagen polls con el indicador -t y pasamos el directorio actual como contexto de compilación, el conjunto de archivos a los que se debe hacer referencia al construir la imagen.

      Una vez que Docker haya compilado y etiquetado la imagen, enumere las imágenes disponibles utilizando docker images:

      Debería ver la imagen polls enumerada:

      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
      

      Antes de ejecutar el contenedor de Django, debemos configurar su entorno de ejecución utilizando el archivo env presente en el directorio actual. Este archivo se pasará al comando docker run que se utiliza para ejecutar el contenedor y Docker insertará las variables de entorno configuradas en el entorno en ejecución del contenedor.

      Abra el archivo env con nano o su editor favorito:

      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
      

      Complete los valores que faltan para las siguientes claves:

      • DJANGO_SECRET_KEY: establézcala en un valor único e impredecible, como se detalla en la documentación de Django. Se proporciona un método para generar esta clave en la sección Ajustar la configuración de la aplicación del tutorial Aplicaciones escalables de Django.
      • DJANGO_ALLOWED_HOSTS: esta variable asegura la aplicación y evita ataques a través del encabezado de host HTTP. Para propósitos de prueba, establézcala en *, un comodín que coincidirá con todos los hosts. En producción, debe establecerlo en your_domain.com. Para obtener más información sobre esta configuración de Django, consulte la sección Configuración principal en la documentación de Django.
      • DATABASE_USERNAME: establézcalo en el usuario de la base de datos de PostgreSQL creado en los pasos de requisitos previos.
      • DATABASE_NAME: establézcalo en polls o el nombre de la base de datos de PostgreSQL creado en los pasos de requisitos previos.
      • DATABASE_PASSWORD: establézcala en la contraseña de la base de datos de PostgreSQL creada en los pasos de requisitos previos.
      • DATABASE_HOST: establézcalo en el nombre de host de su base de datos.
      • DATABASE_PORT: establézcalo en el puerto de su base de datos.
      • STATIC_ACCESS_KEY_ID: establézcala en la clave de acceso de Space o en el almacenamiento de objetos.
      • STATIC_SECRET_KEY: establézcala en Secret de la clave de acceso de su Space o en el almacenamiento de objetos.
      • STATIC_BUCKET_NAME: establézcalo en el nombre de su Space o en el depósito de almacenamiento de objetos.
      • STATIC_ENDPOINT_URL: establézcala en la URL de extremo de Spaces o del almacenamiento del objeto que corresponda, por ejemplo, https://your_space_name.nyc3.digitaloceanspaces.com, si su Space está ubicado en la región nyc3.

      Una vez que haya finalizado la edición, guarde y cierre el archivo.

      En el siguiente paso, ejecutaremos el contenedor configurado a nivel local y crearemos el esquema de la base de datos. También cargaremos activos estáticos como hojas de estilos e imágenes al almacenamiento de objetos.

      Paso 2: Crear el esquema de la base de datos y cargar activos en el almacenamiento de objetos

      Con el contenedor creado y configurado, utilizaremos docker run para anular el CMD establecido en Dockerfile y crear el esquema de la base de datos utilizando los comandos manage.py makemigrations y manage.py migrate:

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

      Ejecutamos la imagen del contenedor polls:latest, pasamos el archivo de variables de entorno que acabamos de modificar y anulamos el comando de Dockerfile con sh -c "python manage.py makemigrations && python manage.py migrate", lo que creará el esquema de la base de datos definido mediante el código de la aplicación.

      Si lo está ejecutando por primera vez, debería ver lo siguiente:

      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

      Esto indica que el esquema de la base de datos se ha creado correctamente.

      Si no está ejecutando migrate por primera vez, Django realizará un no-op a menos que el esquema de la base de datos haya cambiado.

      A continuación, ejecutaremos otra instancia del contenedor de la aplicación y utilizaremos una shell interactiva en su interior para crear un usuario administrativo para el proyecto de Django.

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

      Esto le proporcionará una línea de comandos de shell dentro del contenedor en ejecución que puede usar para crear el usuario de Django:

      • python manage.py createsuperuser

      Ingrese un nombre de usuario, una dirección de correo electrónico y una contraseña para su usuario y, una vez que haya creado el usuario, presione CTRL+D para salir del contenedor y cerrarlo.

      Por último, generaremos los archivos estáticos de la aplicación y los subiremos al Space de DigitalOcean utilizando collectstatic. Tenga en cuenta que esta operación puede tardar un poco en completarse.

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

      Una vez que estos archivos se hayan generado y cargado, obtendrá el siguiente resultado.

      Output

      121 static files copied.

      Ahora, podemos ejecutar la aplicación:

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

      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

      Aquí, ejecutamos el comando predeterminado definido en el Dockerfile, gunicorn --bind :8000 --workers 3 mysite.wsgi:application y exponemos el puerto del contenedor 8000 para que el puerto 80 en su máquina local se asigne al puerto 8000 del contenedor polls.

      Ahora, debería poder navegar a la aplicación polls desde su navegador web al http://localhost en la barra de direcciones URL. Dado que no hay una ruta definida para la ruta / , es probable que reciba un error de 404 Page Not Found (Página no encontrada), lo que es de esperar.

      Diríjase a http://localhost/polls para ver la interfaz de la aplicación Polls:

      Interfaz de la aplicación Polls

      Para ver la interfaz administrativa, visite http://localhost/admin. Debería ver la ventana de autenticación de administración de la aplicación Polls:

      Página de autenticación de administración de Polls

      Ingrese el nombre de usuario administrativo y la contraseña que creó con el comando createsuperuser.

      Después de la autenticación, podrá acceder a la interfaz administrativa de la aplicación Polls:

      Interfaz principal de administración de Polls

      Tenga en cuenta que los que los recursos estáticos de las aplicaciones admin y polls se entregan directamente desde el almacenamiento de objetos. Para confirmar esto, consulte Prueba de la entrega de archivos estáticos de Spaces.

      Cuando haya terminado de explorar, presione CTRL+C en la ventana de terminal que está ejecutando el contenedor de Docker para cerrar el contenedor.

      Con la imagen de Docker de la aplicación de Django probada, los activos estáticos que se cargan en el almacenamiento de objetos y el esquema de la base de datos configurado y listo para ser utilizado en su aplicación, estará listo para subir la imagen de su aplicación de Django a un registro de imágenes como Docker Hub.

      Paso 3: Introducir la imagen de la aplicación de Django en Docker Hub

      Para implementar su aplicación en Kubernetes, la imagen de su aplicación debe cargarse en un registro como Docker Hub. Kubernetes extraerá la imagen de la aplicación de su repositorio y luego la implementará en su clúster.

      Puede usar un registro de Docker privado, como DigitalOcean Container Registry, actualmente gratuito en Early Access o un registro de Docker público como Docker Hub. Docker Hub también le permite crear repositorios de Docker privados. Un repositorio público permite a cualquiera ver y extraer las imágenes del contenedor, mientras que un repositorio privado permite restringir el acceso a usted y a los miembros de su equipo.

      En este tutorial, introduciremos la imagen de Django en el repositorio de Docker Hub público creado en los requisitos previos. También puede introducir su imagen en un repositorio privado, pero extraer imágenes de un repositorio privado no es el tema de este artículo. Para obtener más información sobre la autenticación de Kubernetes con Docker Hub y la extracción de imágenes privadas, consulte Extraer una imagen de un registro privado en la documentación de Kubernetes.

      Comience iniciando sesión en Docker Hub en su máquina local:

      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:

      Ingrese su nombre de usuario y contraseña de Docker Hub para iniciar sesión.

      La imagen de Django actualmente tiene la etiqueta polls:latest. Para introducirla en su repositorio de Docker Hub, vuelva a etiquetar la imagen con su nombre de usuario de Docker Hub y nombre de repositorio:

      • docker tag polls:latest your_dockerhub_username/your_dockerhub_repo_name:latest

      Introduzca la imagen en el repositorio:

      • docker push sammy/sammy-django:latest

      En este tutorial, el nombre de usuario de Docker Hub es sammy y el nombre de repositorio es sammy-django. Debe sustituir estos valores por su propio nombre de usuario y nombre de repositorio de Docker Hub.

      Verá un resultado que se actualiza a medida que las capas de imágenes se insertan en Docker Hub.

      Ahora que su imagen está disponible para Kubernetes en Docker Hub, puede comenzar a implementarla en su clúster.

      Paso 4: Configurar ConfigMap

      Cuando ejecutamos el contenedor de Django a nivel local, pasamos el archivo env a docker run para insertar variables de configuración en el entorno de tiempo de ejecución. En Kubernetes, las variables de configuración pueden insertarse usando ConfigMaps y Secrets.

      ConfigMaps debe usarse para almacenar información de configuración no confidencial, la configuración de la aplicación, mientras que Secrets debe usarse para información confidencial, como claves de API y credenciales de la base de datos. Ambos se insertan en contenedores de forma similar, pero Secrets tienen funciones de control de acceso y seguridad adicionales como encriptación en reposo. Secrets también almacenan datos en base64, mientras que ConfigMaps almacenan datos en texto simple.

      Para comenzar, cree un directorio llamado yaml en el que almacenaremos nuestros manifiestos de Kubernetes. Diríjase al directorio.

      Abra un archivo llamado polls-configmap.yaml en nano o su editor de texto preferido:

      • nano polls-configmap.yaml

      Pegue el siguiente manifiesto de ConfigMap:

      polls-configmap.yaml

      apiVersion: v1
      kind: ConfigMap
      metadata:
        name: polls-config
      data:
        DJANGO_ALLOWED_HOSTS: "*"
        STATIC_ENDPOINT_URL: "https://your_space_name.space_region.digitaloceanspaces.com"
        STATIC_BUCKET_NAME: "your_space_name"
        DJANGO_LOGLEVEL: "info"
        DEBUG: "True"
        DATABASE_ENGINE: "postgresql_psycopg2"
      

      Extrajimos la configuración no sensible del archivo env modificado en el Paso 1 y la pegamos en un manifiesto de ConfigMap. El objeto ConfigMap se llama polls-config. Copie los mismos valores que ingresó en el archivo env en el paso anterior.

      Para propósitos de prueba, establezca DJANGO_ALLOWED_HOSTS como * para desactivar el filtrado del encabezado de host. En un entorno de producción, debe establecerlo en el dominio de su aplicación.

      Cuando haya terminado de editar el archivo, guárdelo y ciérrelo.

      Cree ConfigMap en su clúster usando kubectl apply:

      • kubectl apply -f polls-configmap.yaml

      Output

      configmap/polls-config created

      Después de crear ConfigMap, crearemos el Secret que usó nuestra aplicación en el siguiente paso.

      Paso 5: Configurar Secret

      Los valores de Secret deben estar codificados en base64, lo que significa que crear objetos de Secret en su clúster es ligeramente más complicado que crear ConfigMaps. Puede repetir el proceso del paso anterior, codificando de forma manual los valores de Secret de base64 y pegándolos en un archivo de manifiesto. También puede crearlos usando un archivo de variable de entorno, kubectl create y el indicador --from-env-file, que realizaremos en este paso.

      Una vez más, usaremos el archivo env del Paso 1, eliminando las variables insertadas en ConfigMap. Cree una copia del archivo env llamado polls-secrets en el directorio yaml:

      • cp ../env ./polls-secrets

      Edite el archivo en el editor de su preferencia:

      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
      

      Elimine todas las variables insertadas en el manifiesto de ConfigMap. Cuando haya terminado, debe verse así:

      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
      

      Asegúrese de usar los mismos valores que se utilizan en el Paso 1. Cuando haya terminado, guarde y cierre el archivo.

      Cree el Secret en su clúster usando kubectl create secret:

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

      Output

      secret/polls-secret created

      Aquí creamos un objeto Secret llamado polls-secret y pasamos el archivo de secrets que acabamos de crear.

      Puede inspeccionar el Secret usando kubectl describe:

      • kubectl describe secret polls-secret

      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

      En este punto, almacenó la configuración de su aplicación en el clúster de Kubernetes usando los tipos de objeto Secret y ConfigMap. Ahora estamos listos para implementar la aplicación en el clúster.

      Paso 6: Implementar la aplicación de Django usando una implementación

      En este paso, creará una implementación para su aplicación de Django. Una implementación de Kubernetes es un controlador que puede usarse para administrar aplicaciones sin estado en su clúster. Un controlador es un bucle de control que regula las cargas de trabajo aumentándolas o reduciéndolas. Los controladores también reinician y eliminan los contenedores fallidos.

      Las implementaciones controlan uno o más Pods, la unidad implementable más pequeña de un clúster de Kubernetes. Los Pods están compuestos por uno o más contenedores. Para obtener más información sobre los diferentes tipos de cargas de trabajo que puede iniciar, consulte Introducción a Kubernetes.

      Empiece por abrir un archivo llamado polls-deployment.yaml en su editor favorito:

      • nano polls-deployment.yaml

      Pegue el siguiente manifiesto de implementación:

      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
      

      Complete el nombre de la imagen del contenedor correspondiente, haciendo referencia a la imagen de Django Polls que agregó a Docker Hub en el Paso 2.

      Aquí definimos una implementación de Kubernetes llamada polls-app y la etiquetamos con el par clave-valor app: polls. Especificamos que queremos ejecutar dos réplicas del Pod especificado debajo del campo template.

      Usando envFrom con secretRef y configMapRef, especificamos que todos los datos del Secret polls-secret y el ConfigMap polls-config deben insertarse en los contenedores como variables de entorno. Las claves ConfigMap y Secret se convierten en los nombres de las variables de entorno.

      Por último, exponemos el containerPort 8000 y lo nombramos gunicorn.

      Para obtener más información sobre la configuración de las implementaciones de Kubernetes, consulte Implementaciones en la documentación de Kubernetes.

      Cuando haya terminado de editar el archivo, guárdelo y ciérrelo.

      Cree la implementación en su clúster usando kubectl apply -f:

      • kubectl apply -f polls-deployment.yaml
      • deployment.apps/polls-app created

      Compruebe que la implementación se implementó correctamente usando kubectl get:

      • kubectl get deploy polls-app

      Output

      NAME READY UP-TO-DATE AVAILABLE AGE polls-app 2/2 2 2 6m38s

      Si encuentra un error o considera que algo no está funcionando, puede usar kubectl describe para inspeccionar la implementación fallida:

      Puede inspeccionar los dos Pods usando kubectl get pod:

      Output

      NAME READY STATUS RESTARTS AGE polls-app-847f8ccbf4-2stf7 1/1 Running 0 6m42s polls-app-847f8ccbf4-tqpwm 1/1 Running 0 6m57s

      Ahora hay dos réplicas de su aplicación de Django ejecutándose en el clúster. Para acceder a la aplicación, es necesario crear un Service de Kubernetes, lo cual es lo que haremos a continuación.

      En este paso, creará un Service para su aplicación de Django. Un Service de Kubernetes es una abstracción que le permite exponer un conjunto de Pods en ejecución como servicio de red. Mediante un Service, puede crear un extremo estable para su aplicación que no cambia a medida que los Pods mueren y se vuelvan a crear.

      Existen varios tipos de Service, incluidos ClusterIP Services, que exponen el servicio en un IP interno del clúster, NodePort Services que exponen el servicio en cada Nodo en un puerto estático llamado NodePort y LoadBalancer Services que proporcionan un equilibrador de carga en la nube para dirigir el tráfico externo a los Pods de su clúster (a través de NodePorts, que crea automáticamente). Para obtener más información sobre esos servicios, consulte el artículo Service en la documentación de Kubernetes.

      En nuestra configuración final, usaremos un Service ClusterIP que se expone usando un Ingress y el controlador de Ingress configurado en los requisitos previos de esta guía. Por ahora, para comprobar que todo funciona correctamente, crearemos un servicio de NodePort temporal para acceder a la aplicación de Django.

      Comience creando un archivo llamado polls-svc.yaml usando el editor de su preferencia:

      Pegue el siguiente manifiesto de Service:

      polls-svc.yaml

      apiVersion: v1
      kind: Service
      metadata:
        name: polls
        labels:
          app: polls
      spec:
        type: NodePort
        selector:
          app: polls
        ports:
          - port: 8000
            targetPort: 8000
      

      Aquí creamos un Service NodePort llamado polls y le asignamos la etiqueta app: polls. A continuación, seleccionamos los Pods backend con la etiqueta app: polls y orientamos sus puertos 8000.

      Cuando haya terminado de editar el archivo, guárdelo y ciérrelo.

      Implemente el Service usando kubectl apply:

      • kubectl apply -f polls-svc.yaml

      Output

      service/polls created

      Confirme que su Service se creó usando kubectl get svc:

      Output

      NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE polls NodePort 10.245.197.189 <none> 8000:32654/TCP 59s

      Este resultado muestra la IP y NodePort internos del clúster de Service (32654). Para conectarse al servicio, se necesitan las direcciones IP externas de los nodos del clúster:

      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

      En su navegador web, visite su aplicación Polls usando la dirección IP externa de cualquier nodo y el NodePort. Dado el resultado anterior, la URL de la aplicación sería la siguiente: http://203.0.113.1:32654/polls.

      Debería poder ver la misma interfaz de la aplicación Polls a la que accedió a nivel local en el Paso 1:

      Interfaz de la aplicación Polls

      Puede repetir la misma prueba usando la ruta /admin: http://203.0.113.1:32654/admin. Debería ver la misma interfaz administrativa que antes:

      Página de autenticación de administración de Polls

      En esta etapa, ya implementó dos réplicas del contenedor de la aplicación Polls de Django usando una implementación. También creó un extremo de red estable para estas dos réplicas e hizo que se pueda acceder a ellas externamente usando un servicio de NodePort

      El paso final de este tutorial es proteger el tráfico externo a su aplicación usando HTTPS. Para ello, usaremos el controlador de Ingress-nginx instalado en los requisitos previos y crearemos un objeto de Ingress para dirigir el tráfico externo al servicio de Kubernetes de polls.

      Paso 8: Configurar HTTPS usando el Ingress y cert-manager de Nginx

      Los Ingress de Kubernetes le permiten dirigir de manera flexible el tráfico del exterior de su clúster de Kubernetes a servicios dentro de su clúster. Esto se realiza usando objetos de Ingress, que definen reglas para dirigir el tráfico HTTP y HTTPS a servicios de Kubernetes, y controladores de Ingress, que implementan las reglas equilibrando la carga de tráfico y dirigiéndola a los servicios de backend correspondientes.

      En los requisitos previos, instaló el controlador de Ingress-nginx y el complemento para automatizar certificados TLS cert-manager. También ha configurado el ClusterIssuers de ensayo y producción de su dominio usando la autoridad de certificación Let’s Encrypt, y ha creado un Ingress para probar la emisión de certificados y el cifrado TLS en dos servicios de backend ficticios. Antes de continuar con este paso, debe eliminar el Ingress echo-ingress creado en el tutorial de requisitos previos:

      • kubectl delete ingress echo-ingress

      Si desea, también puede eliminar los servicios y las implementaciones ficticios usando kubectl delete svc y kubectl delete deploy, pero no es necesario que lo haga para completar este tutorial.

      También debería haber creado un registro DNS A con your_domain.com orientado a la dirección IP pública del equilibrador de cargas de Ingress. Si usa un equilibrador de carga de DigitalOcean, puede encontrar esta dirección IP en la sección Equilibradores de carga del panel de control. Si también usa DigitalOcean para administrar los registros DNS de su dominio, consulte Cómo administrar registros DNS para aprender a crear registros A.

      Si usa Kubernetes de DigitalOcean, también asegúrese de implementar la solución descrita en el Paso 5 de Cómo configurar un Ingress de Nginx con Cert-Manager en Kubernetes de DigitalOcean.

      Una vez que tenga un registro A que apunte al equilibrador de carga del controlador de Ingress, puede crear un Ingress para your_domain.com y el servicio polls.

      Abra un archivo llamado polls-ingress.yaml usando el editor de su preferencia:

      Pegue el siguiente manifiesto de 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:
          - your_domain.com
          secretName: polls-tls
        rules:
        - host: your_domain.com
          http:
            paths:
            - backend:
                serviceName: polls
                servicePort: 8000
      

      Creamos un objeto de Ingress llamado polls-ingress y lo anotamos para indicarle al plano de control que utilice el controlador de Ingress-nginx y el ClusterIssuer de ensayo. También habilitamos TLS para your_domain.com y almacenamos el certificado y la clave privada en un secret llamado polls-tls. Por último, definimos una regla para dirigir el tráfico del host your_domain.com al servicio polls del puerto 8000.

      Cuando haya terminado de editar el archivo, guárdelo y ciérrelo.

      Cree el Ingress en su clúster usando kubectl apply:

      • kubectl apply -f polls-ingress.yaml

      Output

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

      Puede usar kubectl describe para rastrear el estado del Ingress que acaba de crear:

      • kubectl describe ingress polls-ingress

      Output

      Name: polls-ingress Namespace: default Address: workaround.your_domain.com Default backend: default-http-backend:80 (<error: endpoints "default-http-backend" not found>) 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

      También puede ejecutar un describe en el certificado polls-tls para confirmar una vez más que se creó de manera correcta:

      • kubectl describe certificate polls-tls

      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

      Esto confirma que el certificado TLS ha sido emitido con éxito y que el cifrado HTTPS ahora está activo para your_domain.com.

      Dado que usamos el ClusterIssuer de ensayo, la mayoría de los navegadores de Internet no confiarán en el certificado Let’s Encrypt que emitió. Por lo tanto, dirigirse a your_domain.com lo llevará a una página de error.

      Para enviar una solicitud de prueba, usaremos wget desde la línea de comandos:

      • wget -O - http://your_domain.com/polls

      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'.

      Usaremos el indicador --no-check-certificate sugerido para omitir la validación del certificado:

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

      Output

      <link rel="stylesheet" type="text/css" href="https://your_space.nyc3.digitaloceanspaces.com/django-polls/static/polls/style.css"> <p>No polls are available.</p>

      Este resultado muestra el HTML de la página de la interfaz /polls, lo que confirma también que la hoja de estilos se toma desde el almacenamiento de objetos.

      Ahora que probó con éxito la emisión de certificados usando el ClusterIssuer de ensayo, puede modificar el Ingress para usar el ClusterIssuer de producción.

      Abra polls-ingress.yaml para editar una vez más:

      Modifique la anotación 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-prod"
      spec:
        tls:
        - hosts:
          - your_domain.com
          secretName: polls-tls
        rules:
        - host: your_domain.com
          http:
            paths:
            - backend:
                serviceName: polls
                servicePort: 8000
      

      Cuando termine, guarde y cierre el archivo. Actualice el Ingress usando kubectl apply:

      • kubectl apply -f polls-ingress.yaml

      Output

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

      Puede usar kubectl describe certificate polls-tls y kubectl describe ingress polls-ingress para rastrear el estado de emisión del certificado:

      • kubectl describe ingress polls-ingress

      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"

      El resultado anterior confirma que el nuevo certificado de producción se emitió y almacenó con éxito en el Secret polls-tls.

      Diríjase a your_domain.com/polls en su navegador web para confirmar que el cifrado HTTPS está habilitado y que todo funciona según lo previsto. Debería ver la interfaz de la aplicación Polls:

      Interfaz de la aplicación Polls

      Verifique que el cifrado HTTPS está activo en su navegador web. Si usa Google Chrome, llegar a la página anterior sin errores confirma que todo funciona correctamente. Además, debe ver un candado en la barra de direcciones URL. Al hacer clic en el candado, se le permitirá inspeccionar los detalles del certificado Let’s Encrypt.

      Como tarea de limpieza final, puede cambiar opcionalmente el tipo de servicio polls de NodePort al tipo ClusterIP interno solamente.

      Modifique polls-svc.yaml usando su editor:

      Cambie el type de NodePort a ClusterIP:

      polls-svc.yaml

      apiVersion: v1
      kind: Service
      metadata:
        name: polls
        labels:
          app: polls
      spec:
        type: ClusterIP
        selector:
          app: polls
        ports:
          - port: 8000
            targetPort: 8000
      

      Cuando haya terminado de editar el archivo, guárdelo y ciérrelo.

      Implemente los cambios usando kubectl apply:

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

      Output

      service/polls configured

      Confirme que su Service se modificó usando kubectl get svc:

      Output

      NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE polls ClusterIP 10.245.203.186 <none> 8000/TCP 22s

      Este resultado muestra que el tipo de servicio es ahora ClusterIP. La única forma de acceder a él es a través de su dominio y del Ingress creado en este paso.

      Conclusión

      En este tutorial, implementó una aplicación de Django escalable y protegida con HTTPS en un clúster de Kubernetes. El contenido estático se toma directamente desde el almacenamiento de objetos y el número de Pods en ejecución puede aumentar o disminuir rápidamente usando el campo réplicas en el manifiesto de implementación polls-app.

      Si usa un Space de DigitalOcean, también puede habilitar la entrega de activos estáticos a través de una red de entrega de contenido y crear un subdominio personalizado para su Space. Consulte Habilitar CDN en Cómo configurar una aplicación de Django escalable con bases de datos y Spaces administrados por DigitalOcean para obtener más información.

      Para revisar el resto de la serie, visite nuestra página “De contenedores a Kubernetes con Django”.



      Source link

      Como implantar um aplicativo Django escalável e seguro com o Kubernetes


      Introdução

      Neste tutorial, você irá implantar um aplicativo de pesquisa do Django em contêiner em um cluster do Kubernetes.

      O Django é um framework Web poderoso, que pode ajudar a acelerar a implantação do seu aplicativo Python. Ele inclui diversas funcionalidades convenientes, como um mapeador relacional do objeto, autenticação de usuário e uma interface administrativa personalizável para seu aplicativo. Ele também inclui um framework de cache e encoraja o design de aplicativos organizados através do seu URL Dispatcher e Sistema de modelos.

      Em Como construir um aplicativo Django e Gunicorn com o Docker, o aplicativo Polls de tutorial do Django foi modificado de acordo com a metodologia do Twelve-Factor para a construção de aplicativos Web escaláveis e nativos na nuvem. Essa configuração em contêiner foi dimensionada e protegida com um proxy reverso do Nginx e autenticada pelo Let’s Encrypt com certificados TLS seguindo Como dimensionar e proteger um aplicativo Django com o Docker, Nginx e Let’s Encrypt. Neste tutorial final da série De contêineres ao Kubernetes com o Django, o aplicativo modernizado de pesquisa do Django será implantado em um cluster do Kubernetes.

      O Kubernetes é um orquestrador de contêineres de código aberto poderoso, que automatiza a implantação, dimensionamento e gerenciamento de aplicativos em contêiner. Os objetos do Kubernetes como os ConfigMaps e Segredos permitem centralizar e desacoplar a configuração dos seus contêineres, enquanto os controladores como Deployments reiniciam automaticamente contêineres que falharam e habilitam o dimensionamento rápido de réplicas de contêineres. A criptografia TLS é habilitada com um objeto Ingress e o Controlador Ingress de código aberto ingress-nginx. O add-on cert-manager do Kubernetes renova e emite certificados usando a autoridade de certificação gratuita Let’s Encrypt.

      Pré-requisitos

      Para seguir este tutorial, será necessário:

      • Um cluster do Kubernetes 1.15+ com controle de acesso baseado na função (RBAC) habilitado. Essa configuração irá usar um cluster do Kubernetes da DigitalOcean, mas você pode criar um cluster usando outro método.
      • A ferramenta kubectl de linha de comando instalada em sua máquina local e configurada para se conectar ao seu cluster. Você pode ler mais sobre como instalar o kubectl na documentação oficial. Se você estiver usando um cluster do Kubernetes da DigitalOcean, consulte Como se conectar a um cluster do Kubernetes da DigitalOcean para aprender como se conectar ao seu cluster usando o kubectl.
      • Um nome de domínio registrado. Este tutorial usará your_domain.com do início ao fim. Você pode obter um domínio gratuitamente através do Freenom, ou usar o registrador de domínios de sua escolha.
      • Um Controlador Ingress ingress-nginx e o gerenciador de certificados TLS cert-manager instalados no seu cluster e configurados para emitir certificados TLS. Para aprender como instalar e configurar um Ingress com o cert-manager, consulte Como configurar um Nginx Ingress com Cert-Manager no Kubernetes da plataforma DigitalOcean.
      • Um registro de DNS A com your_domain.com apontando para o endereço IP público do Balanceador de carga do Ingress. Se estiver usando a DigitalOcean para gerenciar os registros de DNS do seu domínio, consulte Como gerenciar os registros de DNS para aprender como criar um registro A.
      • Um bucket de armazenamento de objetos S3, como um espaço da DigitalOcean para armazenar os arquivos estáticos do seu projeto Django e um conjunto de chaves de acesso para esse espaço. Para aprender como criar um espaço, consulte a documentação de produto Como criar espaços. Para aprender como criar chaves de acesso para espaços, consulte Compartilhando acesso a espaços com chaves de acesso. Com pequenas alterações, você pode usar qualquer serviço de armazenamento de objetos que o plug-in django-storages suporte.
      • Uma instância de servidor PostgreSQL, banco de dados e usuário para seu aplicativo Django. Com pequenas alterações, você pode usar qualquer banco de dados compatível com o Django.
      • Uma conta do Docker Hub e repositório público. Para obter mais informações sobre a criação deles, consulte Repositórios da documentação do Docker.
      • O mecanismo Docker instalado em sua máquina local. Consulte Como instalar e usar o Docker no Ubuntu 18.04 para aprender mais.

      Assim que tiver esses componentes configurados, tudo estará pronto para seguir o guia.

      Passo 1 — Clonando e configurando o aplicativo

      Neste passo, vamos clonar o código do aplicativo do GitHub e definir algumas configurações como as credenciais de banco de dados e chaves de armazenamento de objetos.

      O código do aplicativo e o Dockerfile podem ser encontrados na ramificação polls-docker do repositório GitHub do aplicativo Polls de tutorial do Django. Esse repositório contém códigos para o aplicativo de amostra Polls da documentação do Django, que ensina como construir um aplicativo de pesquisa a partir do zero.

      A ramificação polls-docker contém uma versão em Docker do aplicativo Polls. Para aprender como o aplicativo Polls foi modificado para funcionar efetivamente em um ambiente em contêiner, consulte Como construir um aplicativo Django e Gunicorn com o Docker.

      Comece usando o git para clonar o branch polls-docker do repositório GitHub do aplicativo Polls do tutorial do Django em sua máquina local:

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

      Navegue até o diretório django-polls:

      Esse diretório contém o código Python do aplicativo Django, um Dockerfile que o Docker usará para compilar a imagem do contêiner, bem como um arquivo env que contém uma lista de variáveis de ambiente a serem passadas para o ambiente de execução do contêiner. Verifique o Dockerfile:

      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"]

      Esse Dockerfile usa a imagem Docker oficial do Python 3.7.4 como base e instala os requisitos de pacote Python do Django e do Gunicorn, conforme definido no arquivo django-polls/requirements.txt. Em seguida, ele remove alguns arquivos de compilação desnecessários, copia o código do aplicativo na imagem e define o PATH de execução. Por fim, ele declara que a porta 8000 será usada para aceitar conexões de contêiner recebidas e executa gunicorn com 3 trabalhadores, escutando na porta 8000.

      Para aprender mais sobre cada um dos passos nesse Dockerfile, confira o Passo 6 de Como construir um aplicativo Django e Gunicorn com o Docker.

      Agora, crie a imagem usando o docker build:

      Nós demos o nome de polls para a imagem usando o sinalizador -t e passamos o diretório atual como um contexto de compilação, que é o conjunto de arquivos de referência ao compilar a imagem.

      Depois que o Docker compilar e marcar a imagem, liste as imagens disponíveis usando docker images:

      Você deve ver a imagem polls listada:

      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
      

      Antes de executarmos o contêiner Django, precisamos configurar seu ambiente de execução usando o arquivo env presente no diretório atual. Esse arquivo será passado para o comando docker run usado para executar o contêiner, e o Docker irá injetar as variáveis de ambiente configuradas no ambiente de execução do contêiner.

      Abra o arquivo env com o nano ou com o seu editor favorito:

      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
      

      Preencha os valores que estão faltando para as seguintes chaves:

      • DJANGO_SECRET_KEY: defina isso como um valor único e imprevisível, conforme detalhado na documentação do Django. Um método para gerar essa chave é fornecido em Ajustando as configurações do aplicativo do tutorial sobre o Aplicativo Django escalável.
      • DJANGO_ALLOWED_HOSTS: essa variável protege o aplicativo e impede ataques de cabeçalho de host HTTP. Para fins de teste, defina isso como *, um coringa que irá corresponder a todos os hosts. Na produção, isso deve ser definido como your_domain.com. Para aprender mais sobre esse ajuste do Django, consulte as Core Settings da documentação do Django.
      • DATABASE_USERNAME: defina isso como o usuário do banco de dados PostgreSQL criado nos passos pré-requisitos.
      • DATABASE_NAME: defina isso como polls ou o nome do banco de dados PostgreSQL criado nos passos pré-requisitos.
      • DATABASE_PASSWORD: defina isso como a senha do usuário do banco de dados PostgreSQL criada nos passos pré-requisitos.
      • DATABASE_HOST: defina isso como o nome do host do seu banco de dados.
      • DATABASE_PORT: defina isso como a porta do seu banco de dados.
      • STATIC_ACCESS_KEY_ID: defina isso como a chave de acesso do seu espaço ou armazenamento de objetos.
      • STATIC_SECRET_KEY: defina isso como o segredo da chave de acesso do seu espaço ou armazenamento de objetos.
      • STATIC_BUCKET_NAME: defina isso como seu nome de espaço ou bucket de armazenamento de objetos.
      • STATIC_ENDPOINT_URL: defina isso como o URL do ponto de extremidade do espaço apropriado ou armazenamento de objetos, como https://your_space_name.nyc3.digitaloceanspaces.com se o espaço estiver localizado na região nyc3.

      Assim que terminar a edição, salve e feche o arquivo.

      No próximo passo, vamos executar o contêiner configurado localmente e criar o esquema de banco de dados. Além disso, vamos carregar ativos estáticos como folhas de estilos e imagens para o armazenamento de objetos.

      Passo 2 — Criando o esquema de banco de dados e carregando ativos para o armazenamento de objetos

      Com o contêiner construído e configurado, use o docker run para substituir o conjunto CMD no Dockerfile e criar o esquema de banco de dados usando os comandos manage.py makemigrations e manage.py migrate:

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

      Executamos a imagem de contêiner polls:latest, passamos o arquivo de variável de ambiente que acabamos de modificar e substituímos o comando do Dockerfile com sh -c "python manage.py makemigrations && python manage.py migrate", o que irá criar o esquema de banco de dados definido pelo código do aplicativo.

      Se estiver executando isso pela primeira vez, você deve ver:

      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

      Isso indica que o esquema de banco de dados foi criado com sucesso.

      Se estiver executando migrate uma outra vez, o Django irá cancelar a operação a menos que o esquema de banco de dados tenha sido alterado.

      Em seguida, vamos executar outra instância do contêiner de aplicativo e usar um shell interativo dentro dela para criar um usuário administrativo para o projeto Django.

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

      Isso lhe fornecerá um prompt do shell dentro do contêiner em execução que você pode usar para criar o usuário do Django:

      • python manage.py createsuperuser

      Digite um nome de usuário, endereço de e-mail e senha para o seu usuário e, depois de criá-lo, pressione CTRL+D para sair do contêiner e encerrá-lo.

      Por fim, vamos gerar os arquivos estáticos para o aplicativo e fazer o upload deles para o espaço da DigitalOcean usando o collectstatic. Observe que esse processo pode demorar um pouco de tempo para ser concluído.

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

      Depois que esses arquivos forem gerados e enviados, você receberá a seguinte saída.

      Output

      121 static files copied.

      Agora, podemos executar o aplicativo:

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

      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

      Aqui, executamos o comando padrão definido no Dockerfile, gunicorn --bind :8000 --workers 3 mysite.wsgi:application e expomos a porta do contêiner 8000 para que a porta 80 na sua máquina local seja mapeada para a porta 8000 do contêiner polls.

      Agora, você deve ser capaz de navegar até o aplicativo polls usando seu navegador Web digitando http://localhost na barra de URL. Como não há nenhuma rota definida para o caminho /, você provavelmente receberá um erro 404 Page Not Found, o que é esperado.

      Navegue até http://localhost/polls para ver a interface do aplicativo Polls:

      Interface do aplicativo Polls

      Para visualizar a interface administrativa, visite http://localhost/admin. Você deve ver a janela de autenticação do administrador do aplicativo Polls:

      Página de autenticação de administrador do Polls

      Digite o nome e a senha do usuário administrativo que você criou com o comando createsuperuser.

      Depois de autenticar-se, você pode acessar a interface administrativa do aplicativo Polls:

      Interface administrativa principal do Polls

      Observe que os ativos estáticos para os aplicativos admin e polls estão sendo entregues diretamente do armazenamento de objetos. Para confirmar isso, consulte Testando a entrega de arquivos estáticos de espaços.

      Quando terminar de explorar, aperte CTRL+C na janela do terminal executando o contêiner Docker para encerrar o contêiner.

      Com a imagem Docker do aplicativo Django testada, ativos estáticos carregados no armazenamento de objetos e o esquema de banco de dados configurado e pronto para ser usado com seu aplicativo, tudo está pronto para carregar sua imagem do aplicativo Django em um registro de imagem como o Docker Hub.

      Passo 3 — Enviando a imagem do aplicativo Django para o Docker Hub

      Para implementar seu aplicativo no Kubernetes, sua imagem de aplicativo deve ser carregada em um registro como o Docker Hub. O Kubernetes irá puxar a imagem do aplicativo do seu repositório e implantá-la em seu cluster.

      É possível usar um registro privado do Docker, como o registro do contêiner da DigitalOcean, atualmente gratuito em acesso antecipado, ou um registro público do Docker como o Docker Hub. O Docker Hub também permite criar repositórios privados do Docker. Um repositório público permite que qualquer pessoa veja e puxe as imagens do contêiner, enquanto um repositório privado permite restringir o acesso a você e seus membros de equipe.

      Neste tutorial, vamos enviar a imagem do Django ao repositório público do Docker Hub criado nos pré-requisitos. Também é possível enviar sua imagem a um repositório privado, mas puxar imagens de um repositório privado está além do escopo deste artigo. Para aprender mais sobre a autenticação do Kubernetes com o Docker Hub e puxar imagens privadas, consulte Puxar uma imagem de um registro privado dos documentos do Kubernetes.

      Comece fazendo login no Docker Hub em sua máquina local:

      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:

      Digite seu nome de usuário e senha do Docker Hub para fazer login.

      A imagem do Django possui atualmente o sinalizador polls:latest. Para enviá-la ao seu repositório do Docker Hub, sinalize novamente a imagem com seu nome de usuário e nome de repositório do Docker Hub:

      • docker tag polls:latest your_dockerhub_username/your_dockerhub_repo_name:latest

      Carregue a imagem no repositório:

      • docker push sammy/sammy-django:latest

      Neste tutorial, o nome de usuário do Docker Hub é sammy e o nome do repositório é sammy-django. Você deve substituir esses valores pelo seu nome de usuário e nome de repositório do Docker Hub.

      Você verá um resultado que se atualiza conforme as camadas da imagem são enviadas ao Docker Hub.

      Agora que sua imagem está disponível no Kubernetes no Docker Hub, você pode começar a implantá-la em seu cluster.

      Passo 4 — Configurando o ConfigMap

      Quando executamos o contêiner do Django localmente, passamos o arquivo env ao docker run para injetar variáveis de configuração no ambiente de tempo de execução. No Kubernetes, as variáveis de configuração podem ser injetadas usando o ConfigMaps e Segredos.

      Os ConfigMaps devem ser usados para armazenar informações de configuração não confidenciais, como as configurações do aplicativo, enquanto os Segredos devem ser usados para informações confidenciais como chaves de API e credenciais de banco de dados. Ambos são injetados em contêineres de maneira similar, mas os Segredos têm recursos de controle de acesso e segurança adicionais, como a criptografia em repouso. Os Segredos também armazenam dados em base64, enquanto os ConfigMaps armazenam dados em texto simples.

      Para começar, crie um diretório chamado yaml no qual vamos armazenar nossos manifestos do Kubernetes. Navegue até o diretório.

      Abra um arquivo chamado polls-configmap.yaml no nano ou seu editor de texto preferido:

      • nano polls-configmap.yaml

      Cole o seguinte manifesto do ConfigMap:

      polls-configmap.yaml

      apiVersion: v1
      kind: ConfigMap
      metadata:
        name: polls-config
      data:
        DJANGO_ALLOWED_HOSTS: "*"
        STATIC_ENDPOINT_URL: "https://your_space_name.space_region.digitaloceanspaces.com"
        STATIC_BUCKET_NAME: "your_space_name"
        DJANGO_LOGLEVEL: "info"
        DEBUG: "True"
        DATABASE_ENGINE: "postgresql_psycopg2"
      

      As configurações não confidenciais foram extraídas do arquivo env modificado no Passo 1 e coladas em um manifesto do ConfigMap. O objeto do ConfigMap chama-se polls-config. Copie os mesmos valores inseridos no arquivo env no passo anterior.

      Por motivos de teste, deixe o DJANGO_ALLOWED_HOSTS como * para desativar a filtragem baseada em cabeçalhos de host. Em um ambiente de produção, isso deve ser definido como o domínio do seu aplicativo.

      Quando terminar de editar o arquivo, salve e feche-o.

      Crie o ConfigMap em seu cluster usando o kubectl apply:

      • kubectl apply -f polls-configmap.yaml

      Output

      configmap/polls-config created

      Com o ConfigMap criado, vamos criar o Segredo usado pelo nosso aplicativo no próximo passo.

      Passo 5 — Configurando o Segredo

      Os valores do Segredo devem ser codificados em base64, o que significa que criar objetos Segredo em seu cluster é ligeiramente mais complicado do que criar ConfigMaps. É possível repetir o processo do passo anterior, manualmente codificar os valores do Segredo em base64 e colá-los em um arquivo de manifesto. Também é possível criá-los usando um arquivo de variável de ambiente, kubectl create e o sinalizador --from-env-file, o que será feito neste passo.

      Novamente, vamos usar o arquivo env do Passo 1, removendo variáveis inseridas no ConfigMap. Faça uma cópia do arquivo env chamado polls-secrets no diretório yaml:

      • cp ../env ./polls-secrets

      Edite o arquivo em seu editor de preferência:

      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
      

      Exclua todas as variáveis inseridas no manifesto do ConfigMap. Quando terminar, ele deve ficar parecido com isto:

      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
      

      Certifique-se de usar os mesmos valores usados no Passo 1. Quando terminar, salve e feche o arquivo.

      Crie o Segredo em seu cluster usando o kubectl create secret:

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

      Output

      secret/polls-secret created

      Aqui, criamos um objeto Segredo chamado polls-secret e o passamos no arquivo de Segredos que acabamos de criar.

      Verifique o Segredo usando o kubectl describe:

      • kubectl describe secret polls-secret

      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

      Neste ponto, você armazenou a configuração do seu aplicativo em seu cluster do Kubernetes usando os tipos de objeto Segredo e ConfigMap. Agora, estamos prontos para implantar o aplicativo no cluster.

      Passo 6 — Implementando o aplicativo do Django usando uma Implantação

      Neste passo, você criará um Deployment (implantação) para seu aplicativo do Django. Uma Implantação do Kubernetes é um controlador que pode ser usado para gerenciar aplicativos sem estado em seu cluster. Um controlador é um loop de controle que regula cargas de trabalho aumentando ou diminuindo-as. Os controladores também reiniciam e limpam contêineres com falhas.

      As Implantações controlam um ou mais Pods, a menor unidade implantável em um cluster do Kubernetes. Os Pods incluem um ou mais contêineres. Para aprender mais sobre os diferentes tipos de cargas de trabalho que você pode inicializar, consulte Uma introdução ao Kubernetes.

      Inicie abrindo um arquivo chamado polls-deployment.yaml no seu editor de texto favorito:

      • nano polls-deployment.yaml

      Cole o manifesto de Implantação a seguir:

      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
      

      Preencha o nome apropriado da imagem do contêiner, referenciando a imagem do Polls do Django que você enviou para o Docker Hub no Passo 2.

      Aqui, definimos uma Implantação do Kubernetes chamada polls-app e a rotulamos com o par de chave-valor app: polls. Especificamos que queremos executar duas réplicas do Pod definido abaixo do campo template.

      Usando o envFrom com o secretRef e o configMapRef, especificamos que todos os dados do Segredo polls-secret e do ConfigMap polls-config devem ser injetados nos contêineres como variáveis de ambiente. As chaves ConfigMap e Segredo tornam-se os nomes das variáveis de ambiente.

      Por fim, expomos a containerPort 8000 e a nomeamos gunicorn.

      Para aprender mais sobre como configurar as Implantações do Kubernetes, consulte Deployments na documentação do Kubernetes.

      Quando terminar de editar o arquivo, salve e feche-o.

      Crie uma Implantação no seu cluster usando o kubectl apply -f:

      • kubectl apply -f polls-deployment.yaml
      • deployment.apps/polls-app created

      Verifique se a Implantação foi implantada corretamente usando o kubectl get:

      • kubectl get deploy polls-app

      Output

      NAME READY UP-TO-DATE AVAILABLE AGE polls-app 2/2 2 2 6m38s

      Se encontrar um erro ou algo não estiver funcionando, use o kubectl describe para verificar o Deployment que falhou:

      Verifique os dois Pods usando o kubectl get pod:

      Output

      NAME READY STATUS RESTARTS AGE polls-app-847f8ccbf4-2stf7 1/1 Running 0 6m42s polls-app-847f8ccbf4-tqpwm 1/1 Running 0 6m57s

      Agora, duas réplicas do seu aplicativo Django estão em funcionamento no cluster. Para acessar o aplicativo, é necessário criar um Service (serviço) do Kubernetes, que vamos fazer em seguida.

      Passo 7 — Permitindo o acesso externo usando um Serviço

      Neste passo, você irá criar um Serviço para seu aplicativo Django. Um Serviço do Kubernetes é uma abstração que permite expor um conjunto de Pods em execução como um serviço de rede. Ao usar um Serviço, é possível criar um ponto de extremidade estável para seu aplicativo que não muda à medida que os Pods são destruídos e recriados.

      Existem vários tipos de Serviço, incluindo os Serviços de ClusterIP, que expõem o Serviço em um IP interno do cluster, os Serviços de NodePort, que expõem o Serviço em cada nó em uma porta estática chamada NodePort, além de os Serviços de LoadBalancer, que fornecem um balanceador de carga em nuvem para direcionar o tráfego externo aos Pods no seu cluster (através dos NodePorts, criados por ele automaticamente). Para aprender mais sobre isso, consulte Service nos documentos do Kubernetes.

      Em nossa configuração final, vamos usar um Serviço de ClusterIP que é exposto usando um Ingress e um Controlador Ingress configurados nos pré-requisitos deste guia. Por enquanto, para testar se tudo está funcionando corretamente, vamos criar um Serviço de NodePort temporário para acessar o aplicativo Django.

      Inicie criando um arquivo chamado polls-svc.yaml usando seu editor favorito:

      Cole o manifesto de Serviço a seguir:

      polls-svc.yaml

      apiVersion: v1
      kind: Service
      metadata:
        name: polls
        labels:
          app: polls
      spec:
        type: NodePort
        selector:
          app: polls
        ports:
          - port: 8000
            targetPort: 8000
      

      Aqui, criamos um Serviço de NodePort chamado polls e damos a ele o rótulo app: polls. Em seguida, selecionamos os Pods de backend com o rótulo app: polls e miramos em suas portas 8000.

      Quando terminar de editar o arquivo, salve e feche-o.

      Implemente o Serviço usando o kubectl apply:

      • kubectl apply -f polls-svc.yaml

      Output

      service/polls created

      Confirme se seu Serviço foi criado usando o kubectl get svc:

      Output

      NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE polls NodePort 10.245.197.189 <none> 8000:32654/TCP 59s

      Esse resultado mostra o IP interno do cluster do Serviço e o NodePort (32654). Para nos conectar ao serviço, precisamos dos endereços IP externos para nossos nós de cluster:

      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

      Em seu navegador Web, visite seu aplicativo Polls usando um endereço IP externo de qualquer nó e o NodePort. De acordo com o resultado acima, a URL do aplicativo seria: http://203.0.113.1:32654/polls.

      Você deve ver a mesma interface do aplicativo Polls que você acessou localmente no Passo 1:

      Interface do aplicativo Polls

      É possível repetir o mesmo teste usando a rota /admin: http://203.0.113.1:32654/admin. Você deve ver a mesma interface de administrador que antes:

      Página de autenticação de administrador do Polls

      Neste estágio, você já implantou duas réplicas do contêiner do aplicativo Polls do Django usando uma Implantação. Você também criou um ponto de extremidade de rede estável para essas duas réplicas, e o tornou externamente acessível usando um Serviço de NodePort.

      O passo final neste tutorial é proteger o tráfego externo para seu aplicativo usando HTTPS. Para fazer isso, vamos usar o Controlador Ingress ingress-nginx instalado nos pré-requisitos e criar um objeto Ingress para rotear o tráfego externo para o Serviço polls do Kubernetes.

      Passo 8 — Configurando o HTTPS usando o Nginx Ingress e o cert-manager

      Os Ingresses do Kubernetes permitem o roteamento do tráfego externo ao cluster do seu Kubernetes de maneira flexível para os Serviços dentro de seu cluster. Isso é alcançado usando os objetos do Ingress, que definem as regras para rotear o tráfego HTTP e HTTPS para os Serviços do Kubernetes e para os Controladores do Ingress, os quais implementam as regras fazendo o balanceamento da carga do tráfego e o seu roteamento para os Serviços de backend apropriados.

      Nos pré-requisitos, você instalou o Controlador Ingress ingress-nginx e o add-on de automação de certificados TLS cert-manager. Você também definiu a preparação e a produção de ClusterIssuers para seu domínio usando a autoridade de certificação Let’s Encrypt e criou um Ingress para testar a emissão de certificados e a criptografia TLS em dois Serviços de backend fictícios. Antes de continuar com este passo, deve-se excluir o Ingress echo-ingress criado no tutorial pré-requisito:

      • kubectl delete ingress echo-ingress

      Se desejar, também pode excluir os Serviços e Implantações fictícios usando o kubectl delete svc e o kubectl delete deploy, mas isso não é essencial para completar este tutorial.

      Você também deve ter criado um registro de DNS A com your_domain.com apontando para o endereço IP público do balanceador de carga do Ingress. Se estiver usando um balanceador de carga da DigitalOcean, é possível encontrar esse endereço IP na seção Load Balancers do Painel de controle. Se estiver usando a DigitalOcean para gerenciar os registros de DNS do seu domínio, consulte Como gerenciar os registros de DNS para aprender como criar registros A.

      Se estiver usando o Kubernetes da DigitalOcean, também certifique-se de ter implementado a solução descrita no Passo 5 de Como configurar um Nginx Ingress com o Cert-Manager no Kubernetes da DigitalOcean.

      Assim que tiver um registro A apontando para o balanceador de carga do Ingress, crie um Ingress para your_domain.com e o Serviço polls.

      Abra um arquivo chamado polls-ingress.yaml no seu editor favorito:

      Cole o manifesto de Ingress a seguir:

      [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:
          - your_domain.com
          secretName: polls-tls
        rules:
        - host: your_domain.com
          http:
            paths:
            - backend:
                serviceName: polls
                servicePort: 8000
      

      Criamos um objeto Ingress chamado polls-ingress e o anotamos para instruir o plano de controle para usar o Controlador Ingress ingress-nginx e o ClusterIssuer de preparo. Também habilitamos o TLS para your_domain.com e armazenamos o certificado e a chave privada em um segredo chamado polls-tls. Por fim, definimos uma regra para rotear o tráfego para o host your_domain.com para o Serviço polls na porta 8000.

      Quando terminar de editar o arquivo, salve e feche-o.

      Crie o Ingress no seu cluster usando o kubectl apply:

      • kubectl apply -f polls-ingress.yaml

      Output

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

      É possível usar o kubectl describe para rastrear o estado do Ingress que acabou de ser criado:

      • kubectl describe ingress polls-ingress

      Output

      Name: polls-ingress Namespace: default Address: workaround.your_domain.com Default backend: default-http-backend:80 (<error: endpoints "default-http-backend" not found>) 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

      Também é possível executar um describe no certificado polls-tls para confirmar ainda mais se sua criação foi bem-sucedida:

      • kubectl describe certificate polls-tls

      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

      Isso confirma que o certificado TLS foi emitido com sucesso e a criptografia do HTTPS agora está ativa para your_domain.com.

      Como usamos o ClusterIssuer de preparo, a maior parte dos navegadores Web não irá confiar no certificado falso do Let’s Encrypt que ele emitiu, de forma que navegar até your_domain.com irá resultar em uma página de erro.

      Para enviar um pedido de teste, vamos usar o wget a partir da linha de comando:

      • wget -O - http://your_domain.com/polls

      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'.

      Vamos usar o sinalizador sugerido --no-check-certificate para ignorar a validação de certificados:

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

      Output

      <link rel="stylesheet" type="text/css" href="https://your_space.nyc3.digitaloceanspaces.com/django-polls/static/polls/style.css"> <p>No polls are available.</p>

      Esse resultado mostra o HTML para a página de interface de /polls, o que também confirma que a folha de estilos está sendo exibida a partir do armazenamento de objetos.

      Agora que você testou com sucesso a emissão de certificados usando o ClusterIssuer de preparo, modifique o Ingress para usar o ClusterIssuer de produção.

      Abra o polls-ingress.yaml para editar mais uma vez:

      Modifique a anotação do 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-prod"
      spec:
        tls:
        - hosts:
          - your_domain.com
          secretName: polls-tls
        rules:
        - host: your_domain.com
          http:
            paths:
            - backend:
                serviceName: polls
                servicePort: 8000
      

      Quando terminar, salve e feche o arquivo. Atualize o Ingress usando o kubectl apply:

      • kubectl apply -f polls-ingress.yaml

      Output

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

      É possível usar o kubectl describe certificate polls-tls e o kubectl describe ingress polls-ingress para rastrear o status da emissão de certificados:

      • kubectl describe ingress polls-ingress

      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"

      O resultado acima confirma que o novo certificado de produção foi emitido com sucesso e armazenado no Secredo polls-tls.

      Navegue até your_domain.com/polls no seu navegador Web para confirmar se a criptografia do HTTPS está habilitada e tudo está funcionando como esperado. Você deve ver a interface do aplicativo Polls:

      Interface do aplicativo Polls

      Verifique se a criptografia do HTTPS está ativa no seu navegador Web. Se estiver usando o Google Chrome, chegar na página acima sem erros confirma que tudo está funcionando corretamente. Além disso, você deve ver um cadeado na barra de URL. Clicar no cadeado permitirá verificar os detalhes do certificado do Let’s Encrypt.

      Como uma tarefa de limpeza final, você pode alterar opcionalmente o tipo de Serviço polls do NodePort para o tipo exclusivamente interno ClusterIP.

      Modifique o polls-svc.yaml usando seu editor:

      Altere o type de NodePort para ClusterIP:

      polls-svc.yaml

      apiVersion: v1
      kind: Service
      metadata:
        name: polls
        labels:
          app: polls
      spec:
        type: ClusterIP
        selector:
          app: polls
        ports:
          - port: 8000
            targetPort: 8000
      

      Quando terminar de editar o arquivo, salve e feche-o.

      Implemente as alterações usando o kubectl apply:

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

      Output

      service/polls configured

      Confirme se seu Serviço foi modificado usando o kubectl get svc:

      Output

      NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE polls ClusterIP 10.245.203.186 <none> 8000/TCP 22s

      Esse resultado mostra que o tipo de Serviço é agora ClusterIP. A única maneira de acessá-lo é através do seu domínio e do Ingress criados neste passo.

      Conclusão

      Neste tutorial, você implantou um aplicativo Django dimensionável e seguro via HTTPS em um cluster do Kubernetes. O conteúdo estático é servido diretamente do armazenamento de objetos, e o número de Pods em execução pode ser aumentado ou reduzido rapidamente usando o campo replicas no manifesto de Implantação polls-app.

      Se estiver usando um espaço da DigitalOcean, também é possível habilitar a entrega de ativos estáticos através de uma rede de entrega de conteúdo e criar um subdomínio personalizado para seu espaço. Por favor, consulte Habilitando o CDN de Como configurar um aplicativo Django dimensionável com os bancos de dados e espaços gerenciados da DigitalOcean para aprender mais.

      Para revisar o resto da série, visite nossa página da série De contêineres ao Kubernetes com o Django.



      Source link

      Развертывание масштабируемого и защищенного приложения Django с помощью Kubernetes


      Введение

      В этом учебном модуле мы развернем контейнеризованное приложение 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.

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

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

      • Кластер Kubernetes версии 1.15 или выше с включенным контролем доступа на основе ролей (RBAC). В нашем примере будет использоваться кластер DigitalOcean Kubernetes, но вы можете создать кластер с помощью другого метода.
      • Инструмент командной строки kubectl, установленный на локальном компьютере и настроенный для подключения к вашему кластеру. Дополнительную информацию об установке kubectl можно найти в официальной документации. Если вы используете кластер DigitalOcean Kubernetes, ознакомьтесь с руководством Подключение к кластеру DigitalOcean Kubernetes, чтобы узнать, как подключиться к кластеру с помощью kubectl.
      • Зарегистрированное доменное имя. В этом учебном модуле мы будем использовать имя your_domain.com. Вы можете получить бесплатный домен на Freenom или зарегистрировать доменное имя по вашему выбору.
      • Контроллер ingress-nginx и диспетчер сертификатов TLS cert-manager должны быть установлены в вашем кластере и настроены на использование сертификатов TLS. Чтобы узнать, как установить и настроить Ingress с помощью cert-manager, воспользуйтесь руководством Настройка Nginx Ingress с помощью Cert-Manager в кластере DigitalOcean Kubernetes.
      • Запись DNS A для your_domain.com, указывающая на публичный IP-адрес балансировщика нагрузки Ingress. Если вы используете DigitalOcean для управления записями DNS вашего домена, руководство Управление записями DNS поможет вам научиться создавать записи класса A.
      • Хранилище объектов S3, например пространство DigitalOcean, для хранения статических файлов проекта Django и набор ключей доступа к этому пространству. Чтобы узнать, как создать пространство, ознакомьтесь с документом Как создавать пространства. Чтобы узнать, как создать ключи доступа, ознакомьтесь со статьей Предоставление доступа к пространству с помощью ключей доступа. Внеся незначительные изменения, вы можете использовать любой сервис хранения, который поддерживает плагин django-storages.
      • Экземпляр сервера PostgreSQL, база данных и пользователь для приложения Django. Внеся незначительные изменения, вы можете использовать любую базу данных, которую поддерживает Django.
      • Учетная запись Docker Hub и публичный репозиторий. Более подробную информацию по их созданию можно найти в разделе Repositories (Репозитории) в документации по Docker.
      • Система Docker, установленная на локальном компьютере. Более подробную информацию можно найти в руководстве Установка и использование Docker в Ubuntu 18.04.

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

      Шаг 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:

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

      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:

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

      После того как Docker создаст и отметит образ, перечислите доступные образы, используя 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 или своего любимого редактора:

      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_SECRET_KEY: задает уникальное, непрогнозируемое значение, как описано в документации Django. Один метод генерирования этого ключа представлен в разделе Изменение настроек приложения руководства Масштабируемое приложение Django.
      • 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 соответствующего пространства или конечного пункта хранилища объектов, например https://your_space_name.nyc3.digitaloceanspaces.com, если ваше пространство находится в области 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", которая создаст схему базы данных, определяемую кодом приложения.

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

      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 для выхода из контейнера и его удаления.

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

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

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

      Output

      121 static files copied.

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

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

      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, например, реестр контейнеров DigitalOcean Container Registry, предварительная версия которого в настоящее время предоставляется бесплатно, или публичный реестр Docker, такой как Docker Hub. Docker Hub также позволяет создавать частные репозитории Docker. Публичный репозиторий позволяет любому пользователю видеть и извлекать образы контейнеров, а в частном репозитории доступ имеется только у вас и у членов вашей команды.

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

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

      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. Перейдите в каталог.

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

      • nano polls-configmap.yaml

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

      polls-configmap.yaml

      apiVersion: v1
      kind: ConfigMap
      metadata:
        name: polls-config
      data:
        DJANGO_ALLOWED_HOSTS: "*"
        STATIC_ENDPOINT_URL: "https://your_space_name.space_region.digitaloceanspaces.com"
        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

      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

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

      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. Когда вы закончите, содержимое файла должно выглядеть следующим образом:

      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

      Output

      secret/polls-secret created

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

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

      • kubectl describe secret polls-secret

      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:

      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

      Output

      NAME READY UP-TO-DATE AVAILABLE AGE polls-app 2/2 2 2 6m38s

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

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

      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 в предпочитаемом редакторе:

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

      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

      Output

      service/polls created

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

      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-адрес для нашего узла кластера:

      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. Если вы используете балансировщик нагрузки DigitalOcean, вы можете найти этот IP-адрес в разделе Load Balancers панели управления. Если вы также используете DigitalOcean для управления записями DNS вашего домена, руководство Управление записями DNS поможет вам научиться создавать записи класса A.

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

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

      Откройте файл с именем 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:
          - your_domain.com
          secretName: polls-tls
        rules:
        - host: your_domain.com
          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

      Output

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

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

      • kubectl describe ingress polls-ingress

      Output

      Name: polls-ingress Namespace: default Address: workaround.your_domain.com Default backend: default-http-backend:80 (<error: endpoints "default-http-backend" not found>) 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

      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://your_domain.com/polls

      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

      Output

      <link rel="stylesheet" type="text/css" href="https://your_space.nyc3.digitaloceanspaces.com/django-polls/static/polls/style.css"> <p>No polls are available.</p>

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

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

      Снова откройте файл 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-prod"
      spec:
        tls:
        - hosts:
          - your_domain.com
          secretName: polls-tls
        rules:
        - host: your_domain.com
          http:
            paths:
            - backend:
                serviceName: polls
                servicePort: 8000
      

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

      • kubectl apply -f polls-ingress.yaml

      Output

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

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

      • kubectl describe ingress polls-ingress

      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 в текстовом редакторе:

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

      polls-svc.yaml

      apiVersion: v1
      kind: Service
      metadata:
        name: polls
        labels:
          app: polls
      spec:
        type: ClusterIP
        selector:
          app: polls
        ports:
          - port: 8000
            targetPort: 8000
      

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

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

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

      Output

      service/polls configured

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

      Output

      NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE polls ClusterIP 10.245.203.186 <none> 8000/TCP 22s

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

      Заключение

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

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

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



      Source link