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.
Para seguir este tutorial, necesitará lo siguiente:
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
.your_domain.com
en todo momento. Puede obtener un ejemplar gratis en Freenom o utilizar el registrador de dominios que desee.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
.Una vez que haya configurado estos componentes, estará listo para comenzar con esta guía.
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
:
- cd 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
:
- cat Dockerfile
OutputFROM 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
:
- docker build -t polls .
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
:
- 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:
- nano 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.
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:
OutputNo 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.
Output121 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:
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:
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:
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.
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:
- docker login
OutputLogin 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.
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.
- mkdir yaml
- cd
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:
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
Outputconfigmap/polls-config created
Después de crear ConfigMap, crearemos el Secret que usó nuestra aplicación en el siguiente paso.
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:
- nano 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í:
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
Outputsecret/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
OutputName: 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.
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:
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
OutputNAME 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:
- kubectl describe deploy
Puede inspeccionar los dos Pods usando kubectl get pod
:
- kubectl get pod
OutputNAME 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:
- nano polls-svc.yaml
Pegue el siguiente manifiesto de Service:
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
Outputservice/polls created
Confirme que su Service se creó usando kubectl get svc
:
- kubectl get svc polls
OutputNAME 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:
- kubectl get node -o wide
OutputNAME 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:
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:
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
.
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:
- nano polls-ingress.yaml
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
Outputingress.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
OutputName: 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:
- nano polls-ingress.yaml
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
Outputingress.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:
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:
- nano polls-svc.yaml
Cambie el type
de NodePort
a ClusterIP
:
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
Outputservice/polls configured
Confirme que su Service se modificó usando kubectl get svc:
- kubectl get svc polls
OutputNAME 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.
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”.
Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.
This textbox defaults to using Markdown to format your answer.
You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!