Dockeren production
Des containers de la cave au grenier!
Ce bouquin n'est pas encore dans les bacs
Docker Paris
www.docker.com@docker
Jérôme Petazzoni (@jpetazzo)
Pingouin grognon de service- “Go away or I will replace you with a very small shell script”
Ces 3 dernières années : dotCloud PAAS- EC2, LXC, Puppet, Python, Shell, ØMQ...
Contributeur Docker occasionel- sécurité, réseau, --privileged
A tendance à mettre un peu tout et n'importe quoi dans des containers- Docker-in-Docker, VPN-in-Docker,
KVM-in-Docker, Xorg-in-Docker...
Plan
Rapide intro à Docker et la version 1.0Ce qui marche bien : installation, build, distributionService discovery, interconnexion de containersOrchestration (faire tourner plusieurs containers)Performance (la mesurer, l'améliorer)Configuration managementLes corvées du sysadmin : logs, backups, accès distant
Docker 1.0 1.1 1.1.1 1.1.2 1.2 est là !
Sortie de Docker 1.0 en juin pour DockerConQuelques fonctionalités récentes au pif :- pause/unpause (pour avoir des snapshots et commits cohérents)
- SELinux (pour ce truc bizarre qu'on appelle “sécurité”)
- grosse amélioration du modèle réseau, avec docker run --net …
Et surtout : le label “prêt pour la prod'”- en plus des traditionnels t-shirts et autres autocollants,
vous pouvez nous acheter du support, de la formation...
Installation
Sur une machine de dev : boot2docker- toute petite VM (25 Mo), marche partout (tous hyperviseurs, dédié...)
- script pour OS X permettant de lancer la CLI en local
- prochaines améliorations : partage des volumes avec docker run -v …
Sur les serveurs : quelle distro choisir ?- n'importe quoi de récent (Ubuntu 14.04 LTS, RHEL 7, Fedora 20...)
- nouvelles distros spécifiques Docker : CoreOS, Project Atomic(prometteuses, mais encore très jeunes)
Build avec Dockerfiles
FROM ubuntu:14.04MAINTAINER Docker Education Team <[email protected]>
RUN apt-get updateRUN apt-get install -y nginxRUN echo 'Hi, I am in your container' \ >/usr/share/nginx/html/index.html
CMD [ "nginx", "-g", "daemon off;" ]
EXPOSE 80
Build avec Dockerfiles
Marche bien dans la plupart des cas- le système de cache permet d'avoir un rebuild complet mais rapide
Inconvénients (c-à-d travaux en cours...)- séparer l'environnement de build et celui de run
(histoire de ne pas déployer une image de 5 Go quand on a juste besoin du binaire/JAR/etc. de 10 Mo qu'elle produit...)
- droits d'accès, identifiants, et autres informations sensibles(que faire si le build a besoin d'accéder à une repo privée?)
Comment contourner ces problèmes- utiliser deux Dockerfiles ; garder privés les Dockerfiles et les images
Distribuer les images
Docker Hub- docker push à gauche, docker pull à droite : problème réglé !
- images publiques et privées ; droits d'accès ; etc.
- pas de version sur site ; mais c'est la demande la plus fréquente(chez les grands comptes)
Héberger votre propre registry (=juste le stockage)- docker run registry # “docker run -P” pour l'exposer sur le réseau
- par défaut : stockage sur le disque local
- peut utiliser un système de stockage “Cloud”(par exemple Swift, GCE, S3, Elliptics...)
Distribuer les images
Bricoler avec docker load/save- load/save va charger/exporter des images sous forme de tarballs
- ces tarballs peuvent être stockés n'importe où
- https://github.com/blake-education/dogestry (much image, such docker, wow)
En cours de développement : plug-ins de transport- il y a des outils (comme git, rsync...) qui gèrent très bien les diffs
- pourrait-on les copier s'en inspirer les réutiliser ?
Service discovery
On a l'embarras du choix :- injecter ce dont on a besoin sous forme de variable d'environnementdocker run -e DB_HOST=… -e DB_PORT=… -e …
- faire in bind-mount d'un fichier de configuration dans le containerdocker run -v /etc/docker/config/myapp.yaml:/config.yaml …
- tout mettre dans une base clé-valeur redondante, à haute dispo(zookeeper, etcd, consul...)
- tout mettre dans le DNS(consul, skydns, skydock, dnsmasq...)
On a testé pour vous :les 4 mécanismes de
Service Discovery pour Docker au banc d'essai !
Mais d'abord, parlons des
links
Docker links
docker run -d --name frontdb mysqlimagedocker run -d --link frontdb:sql webimageCrée des entrées DNS dans les containersInjecte des variables d'environnement dans le 2e :
SQL_PORT=tcp://172.17.0.10:5432SQL_PORT_5432_TCP=tcp://172.17.0.10:5432SQL_PORT_5432_TCP_ADDR=172.17.0.10SQL_PORT_5432_TCP_PORT=5432SQL_PORT_5432_TCP_PROTO=tcp
Les containers doivent être sur le même hôte Docker
Service discovery:variables d'environnementFacile à intégrer dans le code- même Java supporte les variables d'environnement (je crois)
Facile à mettre en place- démarrer les containers, récupérer les ports, injecter les variables
Encore plus facile si on utilise les links- complètement automatique si on travaille en local avec un seul hôte
Mais : statique- quand on déplace un container, on ne peut pas mettre à jour les
variables d'environnement à chaud
Variables d'environnement :
B
Service discovery:bind-mount un fichier de configurationFacile à intégrer dans le code- même Ruby a un parser JSON/YAML potable (je crois)
Facile à mettre en place- comme pour les variables d'environnement, mais on génère un fichier
Vaguement dynamique- on peut mettre à jour le fichier de configuration pendant l'exécution
Mais en fait, non- les services doivent détecter les modifications du fichier, et se relancer
Bind-mount un fichier de configuration :
B
Service discovery:Base clé-valeurPlus difficile à intégrer dans le code- Faire des requêtes HTTP (plutôt qu'un simple getenv) n'est pas très
difficile, mais tout de même plus complexe
Plus difficile à mettre en place- il faut déployer la base clé-valeur, sur plusieurs machines
Dynamique (en théorie)- la plupart des bases clé-valeur permettent d'observer une valeur ou
un groupe de valeurs
Mais pas tant que ça (en pratique)- les services doivent détecter les changements et recharger les clés
Bases clé-valeur :
D
Service discovery:DNSFacile à intégrer dans le code- la plupart du temps, il n'y a rien à faire, ça juste marche
Plus difficile à mettre en place*- il faut mettre en place un DNS facile à mettre à jour
Dynamique- il suffit de mettre à jour les zones DNS
Pas de notification (“push”) de changement, mais...- en cas de problème (provoquant une déconnexion), l'application va
probablement se reconnecter en refaisant une requête DNS
*Sauf sur une machine isolée, quand on utilise les links ; car les links créent automatiquement des entrées DNS.
DNS:
B
Alors, y a rien qui marche (bien) ?
Links, le retour
Les ambassadeurs
machine 1 (base de données)docker run -d --name mabase imagemysqldocker run -d --link mabase:sql ambassadeur
machine 2 (serveur web)docker run -d --name mabase ambassadeurdocker run -d --link mabase:sql imagenginx
serveur DB serveur web
container DBJe suis “mabase” !
container webJe veux parler à “mabase” !
ambassadeurMoi, je parle vraiment
à “mabase” !
ambassadeurJe prétends être “mabase” !
dock
erlin
kdocker
link
?
serveur DB serveur web
container DBJe suis “mabase” !
container webJe veux parler à “mabase” !
ambassadeurMoi, je parle vraiment
à “mabase” !
ambassadeurJe prétends être “mabase” !
dock
erlin
kdocker
link
??
serveur DB serveur web
container DBJe suis “mabase” !
container webJe veux parler à “mabase” !
ambassadeurMoi, je parle vraiment
à “mabase” !
ambassadeurJe prétends être “mabase” !
dock
erlin
kdocker
link
LICORNES
Des licornes ? Sans blague ?
En travaux ; mais vous pouvez déjà jouer avec :- Docksul
https://github.com/progrium/docksul
- Grand Ambassadorhttps://github.com/cpuguy83/docker-grand-ambassador
Ou faites votre propre implémentation, avec :- une base clé-valeur à haute dispo (les revoilà!)
- HAProxy, stunnel, iptables...(générer+relancer à chaque fois qu'on détecte un changement)
Service discovery:links avec ambassadeursFacile à intégrer dans le code- ça reste des variables d'environnement
Facile à mettre en place en dev' ; plus dur en prod'- utilisez des links normaux en dev
- sortez l'artillerie lourde seulement pour la prod
Dynamique- les ambassadeurs peuvent re-router le trafic si besoin
Ambassadeurs:
A
Attention, travaux
(Développement en cours...)
Orchestration
On a (encore) l'embarras du choix- décrire les différents composants dans des fichiers YAML ou autre
(Fig, Maestro-NG, Ansible et autres systèmes de CM)
- requêter une API (Mesos, Helios, Kubernetes)
- implémenter un PAAS ou assimilé (Flynn, Deis, OpenShift, Tsuru)
- OpenStack (parce qu'on peut tout faire avec OpenStack même le café)
TEST :comment déterminer le système d'orchestration Docker qu'il vous faut ?
Voulez-vous* utiliser OpenStack?*ou devez-vous
Oui- si vous voulez un PAAS, gardez un œil sur Solum
(encore mieux : contribuez au développement du projet)
- si vous migrez des VMs vers des containers, utilisez Nova(c'est probablement ce que vous avez déjà ; activez le driver Docker)
- sinon, utilisez Heat(et déclarez simplement des ressources Docker dans vos templates)
Non- tournez la page
Est-ce que vous voulez un PAAS?
Oui- CloudFoundry (Ruby, but réécriture en Go en cours)
- Deis (Python, conçu pour Docker, tourne par-dessus CoreOS)
- Dokku (quelques centaines de ligne de Bash!)
- Flynn (Go, à la pointe de la technologie, mais très jeune)
- Tsuru (Go, plus mûr)
- OpenShift geard (encore du Go!)
Soyez prudents (ou tournez la page)- http://blog.lusis.org/blog/2014/06/14/paas-for-realists/
“Je pense que pour l'instant, il n'y a aucun PAAS privé qui tienne la route.”
Combien de machines vous avez ?
Une seule par application ou par environnement- Fig
Un peu (jusqu'à une dizaine)- Maestro-NG
- votre outil de CM favori (par exemple, Ansible a un module Docker sympa)
Beaucoup (quelques centaines)- Helios (bon compromis, mais encore pas mal d'opérations manuelles)
Moult (des milliers)- Mesos (la version 0.20 du 3 septembre supporte Docker nativement)
- Kubernetes (mais attention, ça pique!)
En travaux : libswarm
Lancez un <truc> qui ...- expose l'API Docker
- communique avec de “vrais” hôtes Docker
- démarre et arrête des hôtes Docker supplémentaires à la demande
- s'occupe de l'ordonnancement, la communication, le scaling ...
N'importe quel client Docker peut parler à ce <truc>- ça ressemble à un hôte Docker
- mais c'est un hôte Docker élastique, évolutif, magique!
https://github.com/docker/libswarm
Performance : la mesurer
Grâce aux cgroups, on a pour chaque container...- l'utilisation CPU
- l'utilisation mémoire détaillée (cache vs. resident set size)
- l'utilisation I/O (par périphérique, par lecture/écriture, en octets et en opérations)
Mais les cgroups ne donnent pas...- l'utilisation réseau (il faut “ruser” avec les namespaces réseau)
https://github.com/google/cadvisor
http://jpetazzo.github.io/2013/10/08/docker-containers-metrics/
Performance : l'améliorer
Il n'y a pas grand chose à faire- CPU : on a déjà des perfs natives
- I/O : les perfs sur les volumes sont natives(assurez-vous de placer les données actives sur des volumes)
- mémoire : pas de surcoût si désactive le comptage de la mémoire(utile pour les clusters de calcul ; probablement pas pour le reste)
- réseau : pas de surcoût pour les containers lancés avec “--net host”(utile si on veut pousser plus de 1 Gb/s)(ou si on a un taux élevé de paquets par seconde : VOIP, jeux...)
Configuration management
On a l'embarras du choix (c'est fou, non?)Si vous n'utilisez pas de CM : continuez !- Si vous utilisez, ou maîtrisez, un système de CM, vous pouvez l'utiliser
pour encoder des petits déploiement (jusqu'à une dizaine de nœuds)
Le CM, c'est bien pour les hôtes DockerMais pour les applis elles-mêmes, Dockerfiles = ♥Si vous voulez vraiment utiliser vos configurations actuelles, voilà comment les intégrer !
Configuration management,pour mélanger VMs et containersFaites une image Docker générique avec votre outil de configuration management favori, prêt à tourner
Lancez des containers à partir de cette image, en indiquant son identité (certificat/hostname/...)
Quand le container démarre, il contacte le serveur (puppetmaster etc.), qui lui donne sa configuration
Le container converge vers l'état vouluInconvénients : c'est lent ; et c'est pas fiable à 100%
Configuration management,pour mélanger VMs et containersFaites une image Docker générique avec votre outil de configuration management favori, prêt à tourner
Lancez des containers à partir de cette image, en indiquant son identité (certificat/hostname/...)
Quand le container démarre, il contacte le serveur (puppetmaster etc.), qui lui donne sa configuration
Le container converge vers l'état vouluInconvénients : c'est lent ; et c'est pas fiable à 100%
EN FAIT, NON
Configuration management,en mode “immutable infrastructure”Fabriquez une image Docker avec votre outil de CM favori, et utilisez la comme base pour les autres
Pour les autres images : FROM jerome/mon_image_puppet_de_base ADD manifests/ /etc/puppet/manifests RUN puppet apply --certname db1138.dystopia.io
Cette image est prête (pas besoin d'étape en plus!)Inconvénient : il faut faire une nouvelle image à chaque modification, même mineure(ça peut être vu comme un avantage)
Configuration management,en mode “immutable infrastructure”Fabriquez une image Docker avec votre outil de CM favori, et utilisez la comme base pour les autres
Pour les autres images : FROM jerome/mon_image_puppet_de_base ADD manifests/ /etc/puppet/manifests RUN puppet apply --certname db1138.dystopia.io
Cette image est prête (pas besoin d'étape en plus!)Inconvénient : il faut faire une nouvelle image à chaque modification, même mineure(ça peut être vu comme un avantage)
UN PEU MIEUX
(MAIS BOF QUAND MÊME)
Les corvées des sysadmins
SauvegardesLogsAccès distant
Et il ne s'agit là que d'un petit échantillon des nombreux méfaits ennuyeux mais nécessaires que les sysadmins doivent commettre de temps à autres...
Sauvegarder au niveau fichiers
Utilisez des volumesdocker run --name mysqldata -v /var/lib/mysql busybox true
docker run --name mysql --volumes-from mysqldata mysql
docker run --rm --volumes-from mysqldata mysqlbackup \tar -cJf- /var/lib/mysql | stream-it-to-the-cloud.py
Bien sûr, vous pouvez utiliser autre chose que tar(par exemple rsync, tarsnap...)
Sauvegarder au niveau applicatif
Utilisez des linksdocker run --name mysql mysql
docker run --rm --link mysql:db mysqlbackup \mysqldump --all-databases | stream-it-to-the-cloud.py
Peut être combiné avec des volumes- mettez le dump SQL sur un volume
- puis sauvegardez le dump avec les outils de la page d'avant
Les logs à l'ancienne
À l'ancienne = et si j'écrivais quarante-douze miyards de fichiers dans /var/lib/tomcat/logs ?
Solution : volumesdocker run --name logs -v /var/lib/tomcat/logs busybox true
docker run --name tomcat --volumes-from logs my_tomcat_image
- Inspecter les logs:docker run --rm --volumes-from logs ubuntu bash
- Envoyer les logs quelquepart :docker run --name logshipper --volumes-from logs sawmill
Les logs à la Docker
À la Docker = j'écris tout sur la sortie standardSolution: Docker CLI/APIdocker run --name tomcat dockerized_tomcat
docker logs tomcat
docker run -v /var/run/docker.sock:/var/run/docker.sock \logshipper docker logs tomcat | pipestash ...
Problème : pas de rotation des logs (pour l'instant)
Accès distant
Si vous avez accès à l'hôte : SSH dessus + nsenterhttps://github.com/jpetazzo/nsenter
Si vous n'avez pas accès : SSHD dans le containerhttps://github.com/phusion/baseimage-docker
Pour en savoir plus sur la question(“Pour ou contre le démon SSH dans le container?”)http://blog.docker.com/2014/06/why-you-dont-need-to-run-sshd-in-docker/
À l'avenir :- lancer un container SSH à part
- se connecter dessus
- rebondir vers le container cible
Dockeren production
Des containers de la cave au grenier!
Ce bouquin n'est pas encore dans les bacs
Merci !Questions ?
www.docker.com@docker