One place for hosting & domains

      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