Avant-propos
Voici un exemple d’intégration de Kubernetes avec le service CDN Edgio Delivery pour les praticiens Kubernetes expérimentés. Il suppose un niveau de connaissance de Kubernetes et de connaissance des protocoles Internet standard tels que TCP, DNS et HTTP/HTTPS. L’objectif final est de démontrer un moyen de faire apparaître le service CDN Edgio Delivery comme une entrée standard. L’utilisateur Kubernetes peut conserver la configuration d’entrée dans des systèmes familiers tels que Portainer ou Terraform.
Kubernetes
Kubernetes.io définit Kubernetes comme « un système open source pour automatiser le déploiement, la mise à l’échelle et la gestion des applications conteneurisées ». Il existe plusieurs façons d’afficher un cluster. Le moyen le plus rapide et le plus simple est de tirer parti de l’un des nombreux fournisseurs de cloud qui permettent des déploiements en un clic.
Les clusters Kubernetes contiennent de nombreuses parties. Dans la démo, nous nous concentrerons sur un sous-ensemble du total.
Pièces Kubernetes
- Nœud : machine ou machine virtuelle qui héberge les charges de travail et les services.
- Charge de travail : application simple ou complexe
- POD : conteneurs dans lesquels le logiciel d’application s’exécute. Un ou plusieurs pods constituent une charge de travail.
- Service : mécanisme qui expose une charge de travail à d’autres charges de travail ou entrées
- Ingress : un mécanisme pour exposer les services au monde extérieur
Edgio
Edgio rend la vie connectée plus rapide, plus sûre et plus simple à gérer en offrant une vitesse, une sécurité et une simplicité inégalées à la périphérie grâce à nos solutions de diffusion, d’applications et de streaming intégrées de manière transparente. Notre technologie à l’échelle mondiale et nos services d’experts alimentent les plus grandes marques du monde avec la capacité de fournir l’éducation, le divertissement, les événements et les applications les plus rapides, les plus dynamiques et les plus frictionnés à chaque utilisateur. Dédié à fournir un service client inégalé et à augmenter la valeur à chaque étape du processus, Edgio est un partenaire de choix, générant le trafic Internet mondial pour soutenir les émissions les plus populaires, les films, les sports, les jeux et la musique, ainsi que les sites Web à chargement instantané.
Architecture
Edgio Delivery CDN
Pour cette démo, nous utilisons le SDK Edgio python sur GitHub – llnw/llnw-sdk-python : Limelight Networks Python SDK. La configuration de base restera simple.
Pour configurer le CDN, les éléments de données suivants (autres que l’authentification) sont nécessaires.
- SHORTNAME : identifiant unique dans Edgio Delivery CDN qui contient les règles CDN.
- Nom d’hôte publié : le nom d’hôte qui fait face à Internet à partir du CDN. Dans le cas de cette démonstration, le nom d’hôte cstradtman.s.llnwi.net a été précédemment configuré.
- Chemin d’URL publié : chemin mappé dans la règle spécifique en question.
- Nom d’hôte source : nom d’hôte de l’origine. Dans ce cas, un enregistrement round-robin pointe vers le cluster Kubernetes.
- Chemin de l’URL source : chemin de destination associé au nom d’hôte. Dans ce cas, il sera vide puisque nous le décrirons plus loin dans ce document. Dans cette démonstration, les charges de travail seront différenciées par numéro de port et non par chemin.
DNS
La démo utilise l’API DNS Vultr. La configuration du CDN à l’aide d’adresses IP comme origine n’est pas une bonne pratique. La démo utilise une API pour créer ou modifier un enregistrement circulaire A pointant vers les nœuds du cluster.
Cluster
La démo est dans Vultr sur un cluster à trois nœuds.
Espaces de noms
La démo existera sous l’espace de noms par défaut car c’est la seule chose qui fonctionne sur ce cluster
Nœuds
- Cluster VKE – 3 nœuds chacun avec
- RAM 4 G.
- Disque 80G.
- 2 vCPU
- Réseau 1 G.
Charges de travail
La charge de travail est un simple programme Python qui renvoie des informations de base sur la connexion HTTP. Nous déployons cette démo en ligne, ce qui n’est pas une méthode de déploiement typique. Cependant, il permet à la démo d’être entièrement autonome plutôt que d’avoir des dépendances externes pour construire les conteneurs et les stocker. Le code source se trouve à l’annexe 1. Le code Python réel est en italique, et le code YAML décrivant le déploiement ne l’est pas. La charge de travail utilise le port TCP 8000.
Services
Plusieurs types de service sont disponibles. Nous utilisons le type de service « NodePort ». Il expose le service sur les adresses IP externes du cluster sur un numéro de port élevé sélectionné de manière aléatoire. Kubernetes se charge de la connexion à un nœud sur lequel la charge de travail est exécutée.
Entrée
Kubernetes Ingress est un objet logiciel qui décrit le comportement d’une collection de ressources qui rendent un service Kubernetes disponible en dehors du cluster.
Un contrôleur d’entrée combine un logiciel et/ou un matériel instanciant l’objet logiciel d’entrée.
Un CDN est un proxy inverse distribué riche en fonctionnalités, outre la fonction de proxy inverse, les CDN ont généralement des algorithmes de cache flexibles, une diversité géographique, des fonctionnalités de sécurité (ACL (GEO, Method, regex), des pare-feu d’applications Web, le filigrane et d’autres fonctionnalités plus avancées que l’on ne trouve pas dans les proxy inverses simples.
Les API pour la surveillance des objets Kubernetes sont bien définies, et un certain nombre de proxys inverses HTTP et d’équilibreurs de charge ont été étendus pour fonctionner comme contrôleurs d’entrée. Par exemple, NGINX et HAProxy sont des proxys anciens qui ont été étendus pour fonctionner comme contrôleurs d’entrée et ceux comme Traefik et Itsio ont été développés en parallèle avec Kubernetes . Un CDN est une progression naturelle à partir de simples proxies inverses. Dans le cas de cette démo, nous allons créer un contrôleur d’entrée personnalisé qui contrôle Edgio Delivery CDN. Les données généralement requises pour décrire une entrée sont
- Nom d’hôte public : nom d’hôte sur lequel le service Kubernetes sera disponible
- Chemin public : chemin associé au nom d’hôte public sur lequel les services Kubernetes seront disponibles
- Nom du service backend : nom-service défini par une strophe de services Kubernetes
- Port back-end : nom correspondant à la description du port dans la description du service
Mappages des ressources CDN Edgio Delivery :
Kubernetes |
Edgio Delivery CDN |
Nom d’hôte public |
Nom d’hôte publié |
Chemin public |
Chemin d’accès URL publié |
Nom du service back-end Unique au sein du cluster Kubernetes Inconnu/disponible dans le monde extérieur |
Nom d’hôte source Nom de domaine complet Pas réellement un à un |
La logique derrière cela est:
- Écoutez l’événement d’entrée d’espace de noms provenant du cluster
- Si le type d’événement est « ajouté ».
- Obtenez l’adresse IP des nœuds du cluster
- Créez un enregistrement DNS dans vultr
- Créez des règles CDN dans Edgio CDN pointant vers les enregistrements DNS créés et le port alloué par le service NodePort.
- Si le type d’événement est « modifié ».
- Recherchez les règles CDN dans Edgio CDN qui correspondent à l’entrée existante
- Modifiez les règles dans Edgio CDN pour refléter les nouvelles données dans l’événement
- Si le type d’événement est « supprimé ».
- Trouvez les règles CDN dans Edgio CDN qui correspondent à l’entrée supprimée
- Supprimer les enregistrements DNS dans Vultr associés à cette entrée
- Supprimez les règles CDN dans Edgio qui correspondent à l’entrée supprimée
Configuration
Objets
Les objets Kubernetes sont décrits dans les fichiers YAML. Dans Kubernetes, chaque configuration est un objet. Vous pouvez placer toutes les configurations de déploiement dans un seul fichier. Il est courant de les séparer en fonction de la partie du déploiement qu’ils décrivent.
Déploiement
Dans l’Annexe 1, il y a un grand fichier YAML qui est une combinaison de code Python et YAML. Tout ce qui suit « spec.template.spec.containers.command” » est le code Python qui est transformé en conteneur pendant le déploiement. Du point de vue de l’objet Kubernetes, les lignes qui sont importantes pour nous pour la démo sont:
- Type : déploiement : décrit l’objet comme un déploiement
- Metadata.name : le nom est utilisé par l’objet service pour créer le lien entre les deux.
- Spec.selector.matchlabels.app: indique les pods auxquels le déploiement s’appliquera.
- Spec.template.spec.containers.image : pointe vers l’image officielle python 3 du hub docker
- Spec.template.spec.containers.ports.name : une étiquette pour le port à référencer dans le service d’autres objets dans ce cas
- Spec.template.spec.containers.ports.container : répertorie le port TCP exposé à partir du conteneur en cours d’exécution
Service
- Type : déploiement : décrit l’objet comme un déploiement
- Metadata.name : le nom est utilisé par l’objet Ingress pour créer le lien entre les deux.
- Spec.selector.app: pointe vers le nom du déploiement – pywai-inline-service comme nommé dans l’objet de déploiement.
- Spec.selector.type: Nodeport ceci définit ce service comme étant de type Nodeport comme décrit ci-dessus
- Spec.ports.name : le libellé du port à référencer par d’autres objets (Ingress dans ce cas)
- Spec.ports.protocol: définit le protocole IP utilisé – TCP
- Spec.ports.port : définit le port exposé par ce service
- Spec.ports.targetPort : pointe vers le port exposé par le déploiement – pywai-inline-deployment dans ce cas
Entrée
Dans l’Annexe 3, vous verrez le fichier YAML décrivant l’objet Kubernetes pour le contrôleur Edgio Ingress. Les objets concernés sont les suivants :
- Kind : Ingress – indique à Kubernetes qu’il s’agit d’un objet Ingress
- Medatdata.name – tout dans Kubernetes doit avoir un nom
- Metadata.labels.cdn – cette balise est utilisée pour signaler au contrôleur d’entrée que cet objet est destiné au contrôleur d’entrée edgio
- Spec.rules.host – nom d’hôte public pour exposer le service.
- Spec.rules.http.paths.path – chemin associé au service.
- Spec.rules.http.paths.backend.service.name – étiquette du service à exposer
- Spec.rules.http.paths.backend.service.port.name – étiquette du port du service à exposer
Configurer les cartes
Secrets
Kubernetes a un concept intégré de secrets pour le stockage des données sensibles. Cette démo exploite cela pour les noms d’utilisateur et les clés partagées pour Edgio SDK et l’API DNS Vultr
Exemples de code
Le code de cette démonstration inclus dans le git repos
- Edgio Delivery python SDK
- Déploiement de démonstration Kubernetes
- https://github.com/llnw/edgio-delivery-k8s-demo
- Il s’agit d’une série d’objets Kubernetes décrits comme yaml qui montrent comment déployer l’intégration Edgio Delivery
- Démo du contrôleur d’entrée Edgio Delivery
- https://github.com/llnw/edgio-delivery-k8s-ingress-demo
- Il s’agit du code réel qui implémente le contrôleur d’entrée Edgio Delivery
- À long terme, il devrait être exécuté en tant que service dans Kubernetes, mais pour que la démo reste simple, il fonctionne simplement comme un processus séparé
Ajouts et améliorations futurs à la conception actuelle
Dans un prochain article, nous montrerons comment tirer parti d’autres solutions Edgio, par exemple applications. Nous pourrions utiliser le cluster Kubernetes comme un moyen d’exploiter et de synchroniser les configurations entre plusieurs offres Edgio CDN pour différents workflows.
Annexe 1 – pywai-inline-deployment.yaml
ApiVersion : apps/v1
Type : déploiement
métadonnées :
nom : pywai-inline-deployment
spéc. :
sélecteur :
MatchLabels :
app : pywai-inline-deployment
répliques : 1
modèle :
métadonnées :
étiquettes :
app : pywai-inline-deployment
spéc. :
conteneurs :
– nom : python
image : python:3
commande :
– /bin/sh
– “-c”
– |
Cat > /test.py <<EOF
#!/usr/bin/env python3
“””
Serveur HTTP très simple en python pour la journalisation des requêtes
Utilisation : :
./server.py [<port>]
“””
À partir de http.server importer BaseHTTPRequestHandler, HTTPServer
importer la journalisation
importer pprint
Classe S(BaseHTTPRequestHandler) :
def _set_response(self) :
self.send_response(200)
self.send_header(‘Content-type’, « text/html »)
self.end_headers()
def do_GET(self) :
logging.info(“GET request,\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 = (”, port)
httpd = classe_serveur(adresse_serveur, classe_gestionnaire)
logging.info(‘Starting httpd…\n’)
essayez :
httpd.serve_forever()
Sauf KeyboardInterrupt :
réussi
httpd.server_close()
logging.info(‘Stopping httpd…\n’)
si __name__ == «__main__»:
depuis sys import argv
si len(argv) == 2 :
run(port=int(argv[1]))
sinon :
run()
EOF
exec python /test.py 8000
ports :
– nom : http
Container Port : 8000
Annexe 2 – pywai-inline-service.yaml
ApiVersion : v1
Type : service
métadonnées :
nom : pywai-inline-service
spéc. :
sélecteur :
app : pywai-inline-deployment
Type : NodePort
ports :
– nom : http
protocole : TCP
port : 80
TargetPort : 8000
Annexe 3 – pywai-edgio-Ingress.yaml
ApiVersion : Networking.k8s.io/v1
Type : entrée
métadonnées :
nom : external-pywai-inline-ingress
annotations :
kubernetes.io/ingress.class : edgio
étiquettes :
cdn : edgio
spéc. :
règles :
– Hôte : <saisissez le nom abrégé unique> .s.llnwi.net
http :
chemins :
– chemin : /fred
PathType : exact
backend :
service :
nom : external-pywai-inline-service
port :
nom : pywai-port