Introduction à Docker et Kubernetes

Les systèmes distribués à grande échelle constitués de plusieurs services coopérants revêtent une importance croissante. Ces systèmes fonctionnent sur des clusters de centaines, de milliers ou plus de serveurs. Développer, déployer et entretenir ces systèmes de manière efficace et économique est un défi de taille.

La virtualisation et plus récemment la conteneurisation permettent un partage et une gestion flexibles des ressources. Docker a rendu populaire la conteneurisation. Consultez cet article Envato Tuts + pour une bonne introduction: Le guide de l'auto-stoppeur pour Docker and Modulus.

Google exploite depuis des années son immense logiciel et ses centres de données sur la conteneurisation et a accumulé une lot d'expérience et de savoir-faire. Kubernetes est un projet open source de Google qui apporte toutes ces connaissances aux masses..

Dans cet article, je vais explorer brièvement Docker, puis plonger profondément dans Kubernetes. Je vais utiliser comme exemple un service API REST de devis Python 3. Sautons dans.

Le service de devis

Le service de devis est une API REST qui vous permet d'ajouter des devis et d'obtenir une liste de tous les devis. Il est implémenté en tant que service Web Python 3 utilisant l'excellente bibliothèque hug. Il expose un seul point de terminaison appelé / quotes. Vous pouvez obtenir toutes les citations ou publier une nouvelle citation. Ajoutons quelques citations:

curl http: // localhost: 8000 / quotes -d "quote = La télévision est un chewing-gum pour les yeux. ~ Frank Lloyd Wright" curl http: // localhost: 8000 / quotes -d "quote = Il vaut mieux mourir sur votre pieds que de vivre sur vos genoux. ~ Emiliano Zapata "curl http: // localhost: 8000 / quotes -d" quote = Nous devons faire très attention lorsque nous donnons des conseils à des personnes plus jeunes: parfois, elles le suivent! ~ Edsger W. Dijkstra "

Si vous naviguez jusqu'à http: // localhost: 8000 / quotes tu auras: ["La télévision est un chewing-gum pour les yeux. ~ Frank Lloyd Wright", "Mieux vaut mourir sur ses pieds que vivre sur ses genoux. ~ Emiliano Zapata", "Nous devons faire très attention lorsque nous donnons des conseils à des personnes plus jeunes: parfois ils le suivent! ~ Edsger W. Dijkstra "] Si vous souhaitez seulement voir la documentation générée automatiquement par HUG, accédez à: http: // localhost: 8000

"404": "L'appel d'API que vous avez essayé de créer n'était pas défini. Voici une définition de l'API pour vous aider à démarrer :)", "documentation": "/ quotes": "GET": "examples ": [" http: // localhost: 8000 / quotes "]," sorties ": " type_contenu ":" application / json "," format ":" JSON (notation d'objet sérialisé Javascript) "," POST " : "sorties": "content_type": "application / json", "format": "JSON (Notation d'objets sérialisés Javascript)", "input": "quote": "type": "Texte de base / valeur de chaîne"

Bases de Docker

Je n'expliquerai pas trop Docker et l'appliquerai uniquement au service de devis..

Docker une application Python

Nous avons d’abord besoin d’un fichier Dockerfile. Il effectue les étapes suivantes:

  1. Basé sur la dernière image d'ubuntu
  2. Installe Python 3 et quelques autres dépendances
  3. Copier le répertoire du service de devis
  4. Installe les dépendances quote-service à partir du fichier require.txt
  5. Expose le port 8000
  6. Lancer le service de devis via câlin

DE Ubuntu: le dernier MAINTAINER Gigi Sayfan "[email protected]" Lancez apt-get update -y Lancez apt-get installer -y python3 python3-pip python3-dev build-essential COPY. / quote-service WORKDIR / quote-service Exécuter pip3 installer -r exigences.txt EXPOSE 8000 ENTRYPOINT hug -f app.py

Construire une image

L'étape suivante consiste à créer une image Docker. C'est aussi simple que:

construction de docker .

J'aime aussi baliser les images:

étiquette de docker 715624b7e22a g1g1 / quote-service

g1g1 est mon nom d'utilisateur sur Docker Hub.

Pour vérifier que l'image a été construite avec succès, tapez:

docker ps --all 

Vous devriez voir la nouvelle image:

NOM DES PORTS DE STATUT 715624b7e22a g1g1 / quote-service "/ bin / sh -c 'hug -f a" Il y a 4 heures Up 35 minutes 0.0.0.0:8000->8000/tcp agitated_northcutt

Pousser une image sur le hub Docker

Lorsque vous créez une image, vous pouvez également la transférer vers Docker Hub, de sorte qu'elle puisse être utilisée par d'autres personnes (ou par vous-même sur une autre machine)..

docker push g1g1 / quote-service

Notez que vous devez créer un compte sur Docker Hub et vous connecter localement à l'aide de:

connexion docker

Lancer une application Dockerized

D'accord. Exécutons l'image du service de devis et exposons le port 8000 à l'hôte..

docker run -i -t -p 8000 g1g1 / quote-service

Tu devrais voir: / ################################################ ####################### \ '.---- "… -------…" .----. : / ::::: -: ---------: - ::::: //… + :::: ---- ## / - / oo +: - ## - --- :::: // '// :: ------- / oosoo ------- ::: //. ## ## ## ## ##### .-: ------./++ o / o -.------ :: - ' ## ## ## ## ## ----.-./ + o +:… ----. .: ///. ######## ## ## ## '----.- :::::: ------' .- :::: //. ## ## ## ## ## ####: // ::--. -:… -----… ": - ::::::: -. ' ## ## ## ## ## ##: / ::::::::::: -:- ". :::::-. ## ## #### ###### .--:::::::… :::."… ::… :: EMBRACEZ LES API DU FUTUR :: -.: - - :: :: - VERSION 1.9.6 :: - - :: -::- -:: - ############################################### ########################## Copyright (C) 2015 Timothy Edmund Crosley sous licence MIT

Servir sur le port 8000… "C'est assez cool. Avant d'essayer d'accéder à votre impressionnant service de devis sur le port 8000, vous devrez peut-être effectuer un travail supplémentaire, selon votre environnement..

Si vous utilisez Mac OS X avec VirtualBox et docker-machine, vous devrez peut-être publier le port 8000 sur VirtualBox pour le rendre accessible sur l'hôte..

En supposant que vous ayez essayé de naviguer vers http: // localhost: 8000 / quotes. Oh non. Erreur Interne du Serveur! Qu'est-il arrivé?

Regardons le code:

redis_host = os.environ.get ('QUOTE_STORE_SERVICE_HOST', 'localhost') redis_server = redis.StrictRedis (hôte = redis_host, port = 6379, db = 0)

Le service de devis tente de se connecter à un serveur Redis. L'adresse de l'hôte peut être configurée en tant que variable d'environnement. Si elle n'est pas définie, elle sera définie par défaut sur localhost. Malheureusement, redis n'est pas installé par défaut et ne s'exécute pas à l'intérieur du conteneur. Réglons-le temporairement. Pour obtenir un accès shell dans le conteneur, tapez la commande suivante:

docker exec -it 715624b7e22a / bin / bash

Ensuite, vous obtiendrez un accès shell au conteneur et vous pourrez installer redis:

root @ 715624b7e22a: / quote-service # apt-get install redis-server

Enfin, lancez redis: root @ 715624b7e22a: / quote-service # serveur redis [25] 29 novembre 00: 14: 24.546 # Avertissement: aucun fichier de configuration n'a été spécifié, à l'aide de la configuration par défaut. Afin de spécifier un fichier de configuration, utilisez redis-server /path/to/redis.conf _._ _.- "__" -._ _.- ". '_." -._ Redis 2.8.4 (00000000 / 0) 64 bits .- ".-."\ / .,"-._ (' , .- | , ) Fonctionnement en mode autonome |-._-… - __… -.-._ | ' .-'| Port: 6379 | -._ . / .-'| PID: 25 -._ -. -./ _.- '_.-' |-.-._ -..-'_.-'_.-' | | -._-._ _.-'_.- '| http://redis.io -._ -._-.__.-'_.- '_.-' |-._-._ -..-'_.-'.-'| | -._-._ .-'.-'| -._ -.-.__.-'_.- '_.-' -. -.__.- '_.-' -._ _.- "-.__.- '

[25] Le 29 novembre 00: 14: 24.547 # Le serveur a démarré, Redis version 2.8.4 [25] Le 29 novembre 00: 14: 24.547 # WARNING surcommit_memory a la valeur 0! L'enregistrement en arrière-plan peut échouer dans des conditions de mémoire insuffisante. Pour résoudre ce problème, ajoutez 'vm.overcommit_memory = 1' à /etc/sysctl.conf, puis redémarrez ou exécutez la commande 'sysctl vm.overcommit_memory = 1' pour que cela prenne effet. [25] 29 nov 00: 14: 24,547 * DB chargé depuis le disque: 0,000 secondes [25] 29 nov 00: 14: 24,547 * Le serveur est maintenant prêt à accepter les connexions sur le port 6379 "Vous pouvez désormais ajouter des devis et obtenir des citations à travers le http: // localhost: 8000 / quotes point final.

Le placement de l’application (service de devis) et de la base de données (redis) fonctionne dans un pincement pour un serveur. Mais, évidemment, cela n'échelle pas. Entrez Kubernetes.

Les bases de Kubernetes

Kubernetes, a.k.a. K8s, est un cadre d'opinion pour gérer et orchestrer plusieurs conteneurs. Il a sa propre façon de faire les choses, ce qui est généralement très bon. Il est encore en développement, donc il y a encore quelques aspérités ici et là. Kubernetes a beaucoup de concepts et est très flexible. Je vais expliquer et démontrer les concepts en les appliquant au service de devis..

Mise en place d'un cluster

Il existe de nombreuses façons de configurer un cluster Kubernetes. Kubernetes peut fonctionner sur du métal nu, sur le moteur de conteneur Google, sur AWS, sur du métal nu (avec Linux) et localement sur tout système d'exploitation utilisant des machines virtuelles. Dans le cadre de cet article, j'ai créé un cluster composé d'un maître et de deux sbires à l'aide du cluster k8s de l'interface graphique de CoreOS OSX. Sur Mac OS X, il fournit un joli petit menu où vous pouvez accéder à de nombreux outils de gestion de cluster..

Suivez les instructions et vous serez prêt à partir en un rien de temps.

Si vous n'utilisez pas Mac OSX ou si vous vous moquez bien de l'interface graphique, vous pouvez utiliser ce projet pour configurer un cluster de test dans une VM Vagrant..

Je vais utiliser la ligne de commande à partir de maintenant.

L'outil de ligne de commande kubectl

kubectl est le couteau suisse de Kubernetes. Vous pouvez entièrement contrôler et gérer votre cluster dans le confort de votre console en utilisant uniquement kubectl.

Voici la liste des commandes: get Afficher une ou plusieurs ressources, décrire Afficher les détails d'une ressource spécifique, créer Créer une ressource par mise à jour de nom de fichier ou stdin Mettre à jour une ressource par nom de fichier ou stdin. delete Supprime une ressource par nom de fichier, stdin, ressource et ID, ou par sélecteur de ressources et d'étiquettes. namespace SUPERCEDED: Définir et afficher le journal actuel de l'espace de noms Kubernetes. Imprimez les journaux d'un conteneur dans un conteneur. rolling-update Effectue une mise à jour progressive du ReplicationController donné. redimensionner Définit une nouvelle taille pour un contrôleur de réplication. exec Exécute une commande dans un conteneur. port-forward Transfère un ou plusieurs ports locaux vers un pod. proxy Exécuter un proxy sur le serveur d'exécution Kubernetes API. Exécuter une image particulière sur le cluster. stop Arrête gracieusement une ressource par identifiant ou nom de fichier. expose Prenez une application répliquée et exposez-la en tant qu'étiquette de service Kubernetes. Mettez à jour les étiquettes sur une ressource. config config modifie les fichiers kubeconfig informations-cluster Afficher les informations sur le cluster api-versions Imprimez les versions d'API disponibles. version Affiche les informations de version du client et du serveur. help Aide à propos d'une commande

N'hésitez pas à utiliser la commande help ou la documentation pour étudier ce que chacun fait. Nombre d'entre eux sont utilisés pour effectuer des opérations manuelles mieux exécutées à l'aide de fichiers de configuration dans un système distribué à grande échelle, évolutif, mais cela est indispensable pour une exploration et un dépannage rapides. Les commandes les plus courantes que je vais beaucoup utiliser sont: obtenir, créer, supprimer et démarrer.

Pods

Un pod est l'unité de base de déploiement et de gestion de Kubernetes. Un pod est un groupe d'un ou plusieurs conteneurs. Vous pouvez spécifier un pod à l'aide d'un fichier YAML dédié ou dans le cadre d'un service Kubernetes (voir ci-dessous). Un pod est toujours déployé sur un seul hôte et tous les conteneurs d'un pod peuvent se connecter via localhost. Tous les conteneurs du pod sont toujours démarrés, arrêtés et mis à l'échelle ensemble.

Pour extraire tous les pods du cluster, tapez:

kubectl get pods

Le résultat sera quelque chose comme: NOM READY STATUS RESTAURTS ÂGE quote-frontend-4kyns 1/1 En cours d'exécution 0 1h quote-frontend-v4xk1 1/1 En cours d'exécution 0 1h quote-store-controller-y4ya1 1/1 En cours d'exécution 0 23h ### Volumes

Les conteneurs ne sont pas supposés conserver un état persistant. Lorsqu'un conteneur tombe en panne ou redémarre, son système de fichiers local est effacé. Si vous souhaitez conserver l'état persistant, vous devez utiliser des volumes persistants. Comme tout dans Kubernetes est basé sur des pods, vous devez également définir des volumes dans un pod. Voici un fichier de définition de pod avec un volume persistant: apiVersion: v1 genre: métadonnées du pod: nom: étiquettes de magasin de devis: application: quote-api rôle: spécification de stockage persistant: conteneurs: - nom: image redis: redis volumeMounts: - nom: quote-store-volume mountPath: / data / redis volumes: - nom: quote-store-volume emptyDir: Notez que les volumes persistants sont limités au nœud et survivront aux crashs et redémarrages de conteneurs, mais ne pas échecs nœud / hôte. Vous devez toujours effectuer le travail de réplication et de sauvegarde des données importantes..

Contrôleurs de réplication

L'une des caractéristiques les plus importantes de Kubernetes est sa capacité à gérer et à augmenter facilement le nombre de pods. En règle générale, votre système contient différents types de pods et vous voulez pouvoir spécifier le nombre de pods de chaque type qui devraient être opérationnels..

Dites bonjour aux contrôleurs de réplication. Un contrôleur de réplication possède un modèle de pod qui définit un groupe de conteneurs, un ensemble d'étiquettes permettant d'identifier ces pods et le nombre de pods souhaités. Le contrôleur de réplication s'assure que le nombre de pods en cours identifiés par ses étiquettes correspond toujours au nombre souhaité. Si un pod se termine, le contrôleur de réplication en crée immédiatement un nouveau..

Les contrôleurs de réplication prennent en charge plusieurs cas d'utilisation intéressants, tels que la haute disponibilité, la mise à l'échelle élastique et les mises à jour progressives. Par exemple, vous pouvez ajouter et supprimer des pods de la domination d’un contrôleur de réplication en modifiant leur libellé..

Les contrôleurs de réplication sont bien sûr spécifiés dans un fichier YAML. Voici un exemple: "apiVersion: v1 kind: ReplicationController

métadonnées: nom: devis-frontend spéc: répliques: 2 # sélecteur identifie l'ensemble de pods que ce contrôleur de réplication # est chargé de gérer le sélecteur: app: quote-api rôle: frontend # podTemplate définit le "cookie cutter" utilisé pour créer # nouveaux pods si nécessaire template: métadonnées: labels: # Important: ces labels doivent correspondre au sélecteur ci-dessus # Le serveur api applique cette contrainte. app: quote-api rôle: frontend spec: containers: - nom: quote-service image: g1g1 / quote-service env: - name: GET_HOSTS_FROM # valeur: dns valeur: env ports: - conteneurPort: 8000 "La spécification du modèle pour le Le conteneur quote-service utilise l’image g1g1 / quote-service que j’avais transmise précédemment à Docker Hub. env section où le partage d'informations entre les modules peut s'effectuer via des variables DNS ou d'environnement.

Pour créer un contrôleur de réplication, tapez:

kubectl create -f

Pour afficher les contrôleurs de réplication actuels du cluster, tapez:

kubectl get rc

Vous devriez voir quelque chose comme: CONTROLEUR CONTENEUR (S) SELECTEUR D'IMAGE (S) REPLICAS AGE devis-frontend devis-service g1g1 / quote-service app = quote-api, role = frontal 2 1h devis maître-contrôleur-contrôleur-redis app = quote-api, role = persistant -stockage 1 1d ### Prestations de service

Un service expose son pod au reste du cluster et éventuellement en externe via des variables d'environnement ou DNS. Par exemple, le service de devis est composé de deux types de pods: un pod de magasin redis et un pod frontal. Le conteneur frontal doit pouvoir trouver le conteneur de magasin et les clients doivent pouvoir accéder à un seul point de terminaison public pour accéder au service..

Le service Kubernetes est implémenté dans un autre fichier YAML. Chaque composant de votre système auquel d'autres composants doivent accéder doit avoir son propre fichier de service. Voici les deux fichiers de service pour les composants du service de devis:

srv-quote-frontend.yaml

apiVersion: v1 type: métadonnées de service: nom: spécification quote-frontend: type: ports NodePort: - port: 8000 # le port que ce service doit servir # le conteneur sur chaque pod auquel se connecter, peut être un nom # (par exemple 'www') ou un nombre (par exemple 80) targetPort: 80 protocole: TCP # comme le sélecteur dans le contrôleur de réplication, # mais cette fois-ci, il identifie l'ensemble de pods pour équilibrer la charge du trafic. sélecteur: application: quote-api rôle: frontend #### srv-quote-store.yaml apiVersion: v1 genre: métadonnées de service: nom: citation-store spec: ports: - port: 6379 # le port que ce service doit desservir sur targetPort: 6379 # exactement comme le sélecteur du contrôleur de réplication, # mais cette fois, il identifie le ensemble de pods pour équilibrer la charge du trafic. sélecteur: application: quote-api rôle: persistent-storage L'hôte et le port de chaque service sont mis à la disposition de chaque conteneur du cluster. Par exemple, si vous exécutez un shell interactif sur l'un des conteneurs frontend:

kubectl quote-frontend-4kyns exec -i -t bash

Ensuite, vous pouvez vérifier que l'environnement contient les informations d'hôte et de port nécessaires pour vous connecter au magasin de devis.. root @ quote-frontend-4kyns: / quote-service # env | grep MAGASIN QUOTE_STORE_PORT_6379_TCP_ADDR = 10.100.234.192 QUOTE_STORE_PORT_6379_TCP_PROTO = tcp QUOTE_STORE_SERVICE_PORT = 6379 = 6379 QUOTE_STORE_PORT_6379_TCP_PORT QUOTE_STORE_PORT = tcp: //10.100.234.192: 6379 QUOTE_STORE_PORT_6379_TCP = tcp: //10.100.234.192: 6379 QUOTE_STORE_SERVICE_HOST = 10.100.234.192 Juste pour rafraîchir votre mémoire, c’est exactement ce que fait le client: redis_host = os.environ.get ('QUOTE_STORE_SERVICE_HOST', 'localhost') redis_server = redis.StrictRedis (hôte = redis_host, port = 6379, db = 0) ## Conclusion

Docker et Kubernetes sont des technologies passionnantes. Cet article a à peine effleuré la surface de ce qui est possible. Les avantages sont énormes, mais l'infrastructure, les outils et les meilleures pratiques continuent d'évoluer. Si vous êtes même connecté à distance à des systèmes distribués à grande échelle, je vous encourage à au moins rester au fait de ces technologies et, idéalement, à vous y mettre et à essayer de les utiliser. Il existe de nombreuses façons d'expérimenter et d'apprendre sans la migration en bloc de toute votre infrastructure de production..

Pour ce qui est de Kubernetes, il existe quelques autres alternatives pour la gestion et l’orchestration de conteneurs multiples, telles que la société en place Mesos et la composition de Docker. Je crois que Kubernetes est plus solide sur le plan architectural, a beaucoup de dynamisme et est meilleur que les alternatives.