Prólogo
El siguiente es un ejemplo de integración de Kubernetes con el servicio de CDN de Edgio Delivery para profesionales experimentados de Kubernetes. Asume un nivel de conocimiento en Kubernetes y conocimiento de protocolos estándar de Internet como TCP, DNS y HTTP/HTTPS. El objetivo final es demostrar una manera de hacer que el servicio Edgio Delivery CDN aparezca como entrada estándar. El usuario de Kubernetes puede mantener la configuración de ingreso en sistemas familiares como Portainer o Terraform.
Kubernetes
Kubernetes.io define a Kubernetes como “un sistema de código abierto para automatizar la implementación, escalado y gestión de aplicaciones contenerizadas”. Hay varias maneras de crear un cluster. La forma más rápida y fácil es aprovechar uno de los muchos proveedores de nube que permiten implementaciones de “un solo clic”.
Los clusters de Kubernetes contienen muchas partes. En la demo, nos centraremos en un subconjunto del total.
Partes de Kubernetes
- Nodo: Máquina o VM que aloja las cargas de trabajo y los servicios.
- Carga de trabajo: Aplicación simple o compleja
- Pod: Contenedores en los que se ejecuta el software de la aplicación. Uno o más pods componen una carga de trabajo.
- Servicio: Mecanismo que expone una carga de trabajo a otras cargas de trabajo o entradas
- Ingreso: Un mecanismo para exponer los servicios al mundo exterior
Edgio
Edgio hace que la vida conectada sea más rápida, segura y sencilla de administrar al potenciar una velocidad, seguridad y simplicidad inigualables en el borde con nuestra entrega, aplicaciones y soluciones de streaming perfectamente integradas. Nuestra tecnología a escala mundial y nuestros servicios expertos alimentan a las principales marcas del mundo con la capacidad de ofrecer la educación, entretenimiento, eventos y eventos más rápidos, dinámicos y sin fricciones. aplicaciones a cada usuario. Dedicado a proporcionar una atención al cliente sin igual y extender el valor en cada paso del camino, Edgio es un socio de elección, impulsando el tráfico de Internet en todo el mundo para apoyar los programas, películas, deportes, juegos y música más populares, y sitios web de carga instantánea.
Arquitectura
Edgio Delivery CDN
Para esta demostración, usamos el SDK de Edgio python en GitHub – llnw/llnw-sdk-python: Limelight Networks Python SDK. La configuración básica se mantendrá simple.
Al configurar la CDN, se necesitan los siguientes datos (aparte de la autenticación).
- Shortname: Un identificador único dentro de Edgio Delivery CDN que contiene reglas de CDN.
- Nombre de host publicado: El nombre de host que se enfrenta a Internet desde la CDN. En el caso de esta demo, el nombre de host cstradtman.s.llnwi.net se configuró previamente.
- Ruta URL publicada: La ruta asignada a la regla específica en cuestión.
- Nombre de host de origen: El nombre de host del origen. En este caso, un registro de round-robin apunta al cúmulo de Kubernetes.
- Ruta URL de origen: La ruta de destino asociada con el nombre de host. En este caso, estará en blanco ya que lo describimos más adelante en este documento. En esta demostración, las cargas de trabajo se diferenciarán por número de puerto y no por ruta.
DNS
La demo utiliza la API DNS de Vultr. Configurar la CDN usando direcciones IP como orígenes no es una buena práctica. La demo utiliza una API para crear o modificar un registro round-robin que apunta a los nodos del clúster.
Grupo
La demo está en Vultr en un clúster de tres nodos.
Espacios de nombres
La demo existirá bajo el espacio de nombres predeterminado, ya que es la única cosa que se ejecuta en este clúster
Nodos
- Clúster VKE – 3 nodos cada uno con
- 4G ram
- Disco 80G.
- 2 vCPU
- 1 G red
Cargas de trabajo
La carga de trabajo es un programa Python simple que devuelve información básica sobre la conexión HTTP. Implementamos esta demo en línea, que no es un método de implementación típico. Sin embargo, permite que la demo sea totalmente autónoma en lugar de tener dependencias externas para construir los contenedores y almacenarlos. El código fuente está en el Apéndice 1. El código Python real está en cursiva, y el código YAML que describe la implementación no lo es. La carga de trabajo utiliza el puerto TCP 8000.
Servicios
Hay varios tipos de servicio disponibles. Estamos utilizando el tipo de servicio “NodePort”. Expone el servicio en las direcciones IP externas del clúster en un número de puerto alto seleccionado aleatoriamente. Kubernetes se encarga de la conexión a un nodo donde se ejecuta la carga de trabajo.
Entrada
Kubernetes Ingress es un objeto de software que describe el comportamiento de una colección de recursos que hacen que un servicio de Kubernetes esté disponible fuera del clúster.
Un controlador de ingreso combina software y / o hardware que instancian el objeto de software de ingreso.
Una CDN es un proxy inverso distribuido rico en características, además de la función de proxy inverso, las CDN suelen tener algoritmos de caché flexibles, diversidad geográfica, características de seguridad (ACL (GEO, Method, regex), Firewalls de aplicaciones web, marcas de agua, etc. y otras características más avanzadas que no se encuentran en los proxies inversos simples.
Las API para el monitoreo de objetos Kubernetes están bien definidas, y una serie de proxies inversos HTTP y balanceadores de carga se han ampliado para funcionar como controladores de entrada. Por ejemplo, NGINX y HAProxy son proxies de la vieja escuela que se han extendido para trabajar como controladores de ingreso y los que como Traefik e Itsio se desarrollaron en paralelo a Kubernetes. Una CDN es una siguiente progresión natural de los proxies inversos simples. En el caso de esta demo, crearemos un controlador de entrada personalizado que controle Edgio Delivery CDN. Los datos típicamente requeridos para describir un ingreso es
- Nombre de host público: El nombre de host en el que estará disponible el servicio de Kubernetes
- Ruta pública: La ruta asociada al nombre de host público en la que estarán disponibles los servicios de Kubernetes
- Nombre de servicio de backend: Nombre de servicio definido por una estrofa de servicios de Kubernetes
- Puerto de backend: Un nombre que coincide con la descripción del puerto en la descripción del servicio
Asignaciones de activos de Edgio Delivery CDN:
Kubernetes |
Edgio Delivery CDN |
Nombre de host público |
Hostname publicado |
Camino público |
Ruta de URL publicada |
Nombre del servicio de backend Único dentro del cluster de Kubernetes No conocido/disponible para el mundo exterior |
Nombre de host de origen Nombre de dominio totalmente cualificado En realidad no uno a uno |
La lógica detrás de esto es:
- Escuche el evento de ingreso de espacio de nombres desde el cluster
- Si el tipo de evento es “Añadido”.
- Obtener la dirección IP de los nodos en el clúster
- Crear registro DNS en vultr
- Cree reglas CDN en Edgio CDN que apunten hacia los registros DNS creados y el puerto asignado por el servicio NodePort.
- Si el tipo de evento es “Modificado”.
- Encuentra reglas CDN en Edgio CDN que coincidan con la entrada existente
- Modificar reglas en Edgio CDN para reflejar nuevos datos en el evento
- Si el tipo de evento es “eliminado”.
- Encuentra reglas de CDN en Edgio CDN que coincidan con la entrada eliminada
- Elimine los registros DNS en Vultr asociados con esta entrada
- Elimina las reglas CDN en Edgio que coincidan con la entrada eliminada
Configuración
Objetos
Los objetos Kubernetes se describen en archivos YAML . En Kubernetes, cada configuración es un objeto. Puede colocar todas las configuraciones de implementación en un solo archivo. Es una práctica común dividirlos en función de qué parte del despliegue describen.
Despliegue
En el Apéndice 1, hay un archivo YAML grande que es una combinación de código Python y YAML. Todo después de “spec.template.spec.containers.command” es el código Python que se convierte en un contenedor durante el despliegue. Desde el punto de vista del objeto Kubernetes las líneas que son importantes para nosotros para la demo son:
- Tipo: Despliegue: Describe el objeto como un despliegue
- Metadata.name: Nombre es utilizado por el objeto de servicio para crear el enlace entre los dos.
- Spec.selector.matchlabels.app: indica a qué pods se aplicará la implementación.
- Spec.template.spec.containers.image: Apunta a la imagen oficial de python 3 de docker hub
- Spec.template.spec.containers.ports.name: Una etiqueta para el puerto a hacer referencia en otro servicio de objetos en este caso
- Spec.template.spec.containers.ports.containerport: Enumera el puerto TCP expuesto desde el contenedor en ejecución
Servicio
- Tipo: Despliegue: Describe el objeto como un despliegue
- Metadata.name: Nombre es utilizado por el objeto Ingress para crear el enlace entre los dos.
- Spec.selector.app: señala el nombre de la implementación – pywai-inline-service como se nombra en el objeto de implementación.
- Spec.selector.type: Nodeport Esto define este servicio como el tipo Nodeport como se describe anteriormente
- Spec.ports.name: La etiqueta para el puerto a ser referenciado por otros objetos (entrada en este caso)
- Spec.ports.protocol: define el protocolo IP en uso – TCP
- Spec.ports.port: Define el puerto expuesto por este servicio
- Spec.ports.targetPort: Apunta al puerto expuesto por la implementación – pywai-inline-deployment en este caso
Entrada
En el Apéndice 3, verá el archivo YAML que describe el objeto Kubernetes para el controlador de entrada de Edgio. Los objetos a tratar son:
- Tipo: Ingreso – Esto le dice a Kubernetes que es un objeto de ingreso
- Medatdata.name – Todo en Kubernetes debe tener un nombre
- Metadata.label.cdn – Esta etiqueta se utiliza para indicar al controlador de entrada que este objeto es para el controlador de entrada de entrada de edición
- Spec.rules.host – Nombre de host público para exponer el servicio.
- Spec.rules.http.paths.path – ruta asociada al servicio.
- Spec.rules.http.paths.backend.service.name – etiqueta del servicio a exponer
- Spec.rules.http.paths.backend.service.port.name – etiqueta de puerto del servicio a exponer
Mapas de configuración
Secretos
Kubernetes tiene un concepto incorporado de secretos para el almacenamiento de datos sensibles. Esta demo aprovecha esto para los nombres de usuario y las claves compartidas tanto para Edgio SDK como para la API DNS de Vultr
Ejemplos de código
El código para esta demostración incluido en los repositorios git
- Edgio Delivery python SDK
- Despliegue de demostración de Kubernetes
- https://github.com/llnw/edgio-delivery-k8s-demo
- Se trata de una serie de objetos Kubernetes descritos como yaml que muestran cómo implementar la integración de Edgio Delivery
- Edgio Delivery Controlador de entrada demo
- https://github.com/llnw/edgio-delivery-k8s-ingress-demo
- Este es el código real que implementa el controlador de entrada de Edgio Delivery
- A largo plazo, debe ejecutarse como un servicio dentro de Kubernetes, sin embargo, para mantener la demostración simple, simplemente se ejecuta como un proceso separado
Futuras adiciones y mejoras al diseño actual
En una publicación futura, mostraremos cómo aprovechar otras soluciones de Edgio, por ejemplo Aplicaciones. Podríamos usar el clúster de Kubernetes como una forma de aprovechar y sincronizar configuraciones entre múltiples ofertas de CDN de Edgio para diferentes flujos de trabajo.
Apéndice 1 – pywai-inline-deployment.yaml
ApiVersion: Apps/v1
Tipo: Despliegue
metadatos:
nombre: pywai-inline-deployment
especificaciones:
selector:
MatchLabels:
aplicación: pywai-inline-deployment
réplicas: 1
plantilla:
metadatos:
etiquetas:
aplicación: pywai-inline-deployment
especificaciones:
contenedores:
– nombre: python
imagen: python:3
orden:
– /bin/sh
– “-c”
– |
cat > /test.py <<EOF
#!/usr/bin/env python3
“”
Servidor HTTP muy simple en python para las solicitudes de registro
Uso::
./server.py [<puerto>]
“”
Desde http.server importa BaseHTTPRequestHandler, HTTPServer
registro de importación
importar pprint
Clase S (BaseHTTPRequestHandler):
def _set_response(self):
self.send_response(200)
self.send_header(‘Content-type’, «text/html»)
self.end_headers()
def do_GET(self):
Solicitud logging.info(“GET,\nPath: %S\nHeaders:\n%s\n”, str(self.path), str(pprint.pformat(self.headers)))
self._set_response()
headerinfo=pprint.pformat(self.headers.items())
clientinfo=pprint.pformat(self.client_address)
lineinfo=pprint.pformat(self.requestline)
versioninfo=pprint.pformat(self.request_version)
self.wfile.write(“<pre> {} </pre>”.format(headerinfo).encode(‘utf-8’))
self.wfile.write(“<pre> {} </pre>”.format(clientinfo).encode(‘utf-8’))
self.wfile.write(“<pre> {} </pre>”.format(lineinfo).encode(‘utf-8’))
self.wfile.write(“<pre> {} </pre>”.format(versioninfo).encode(‘utf-8’))
def run(server_class=HTTPServer, handler_class=S, port=8080):
Logging.basicConfig(level=logging.INFO)
server_address = (”, puerto)
httpd = server_class(server_address, handler_class)
logging.info(‘Starting httpd…\n’)
intente:
httpd.serve_forever()
Excepto KeyboardInterrupt:
pase
httpd.server_close()
logging.info(‘Stopping httpd…\n’)
si __nombre__ == ‘__principal___’:
desde sys importar argv
si len(argv) == 2:
run(port=int(argv[1]))
de otro modo:
run()
EOF
exec python /test.py 8000
puertos:
– nombre: http
Puerto de contenedores: 8000
Apéndice 2 – pywai-inline-service.yaml
ApiVersion: v1
Tipo: Servicio
metadatos:
nombre: pywai-inline-service
especificaciones:
selector:
aplicación: pywai-inline-deployment
Tipo: NodePort
puertos:
– nombre: http
protocolo: TCP
puerto: 80
TargetPort: 8000
Apéndice 3 – pywai-edgio-ingress.yaml
ApiVersion: Networking.k8s.io/v1
Amable: Entrada
metadatos:
nombre: external-pywai-inline-ingress
anotaciones:
kubernetes.io/ingress.class: edgio
etiquetas:
cdn: edgio
especificaciones:
reglas:
– Host: <Introduzca el nombre corto único>.s.llnwi.net
http:
rutas:
– path: /fred
PathType: Exacto
backend:
servicio:
nombre: external-pywai-inline-service
puerto:
nombre: pywai-port