IT & Engineering
Devgun : créer des environnements de développement avec Kubernetes
Lorsque nous avons commencé à créer des environnements de développement locaux, nous nous sommes tournés vers des outils courants comme Vagrant. Mais, comme pour la plupart des environnements construits avec Vagrant, les temps de compilation sont longs. Par conséquent, les images Vagrant ont une longue durée de vie et ont tendance à dériver avec le temps.
Nos services et notre infrastructure changent constamment, la compilation Vagrant était donc presque toujours cassée. Nous voulions éviter le traditionnel « rite de passage des nouvelles recrues », qui implique souvent des jours de travail pour que Vagrant réussisse à compiler une nouvelle machine virtuelle de développement.
Dans l’idéal, les nouvelles recrues peuvent être productives dans les heures qui suivent leur embauche, et non des jours ou des semaines plus tard.
À tout cela s’ajoutait le fait que nous avons beaucoup de microservices qui doivent s’exécuter dans l’environnement de développement et s’intégrer de manière transparente.
Les objectifs du projet étaient simples :
- Configurer et détruire un environnement de développement rapidement et de manière reproductible.
- Configuration et destruction de l’environnement de développement en une seule étape.
- Démarrer et arrêter les services, ainsi que leurs dépendances, à volonté.
Évaluer les plateformes d’orchestration
Puisque nos microservices s’exécutaient déjà dans des conteneurs, nous savions qu’il fallait choisir un système d’orchestration.
Plusieurs membres de notre équipe de développement s’intéressaient à Mesos Marathon, nous l’avons donc testé en premier. Malheureusement, les exigences en matière de mémoire et de matériel pour exécuter Marathon dans un petit environnement de développement local étaient beaucoup trop restrictives pour nous. Au moment de nos tests, Minimesos était également incapable de connecter correctement les conteneurs dans Marathon au réseau local, ce qui constituait un obstacle majeur pour notre projet. Ces problèmes ont montré clairement que Mesos ne serait pas adapté à nos besoins.
Ensuite, nous avons évalué Kubernetes et Minikube car nous étions attirés par la communauté très active autour de ces projets. Nous avons constaté que l’empreinte mémoire était minime, et la mise en réseau fonctionnait parfaitement. La plupart des fonctionnalités qui nous intéressaient fonctionnaient de base, et l’exécution de nos applications tierces dans Minikube s’est révélée plus simple que prévu.
En choisissant Minikube comme plateforme, nous avons pu avancer rapidement sur le projet et consacrer la majeure partie de notre temps à développer ce qui allait devenir Devgun.
Créer une interface en ligne de commande (CLI)
Pour atteindre les objectifs de notre projet, nous avons décidé de créer une interface en ligne de commande tout-en-un écrite en Golang. Nous voulions une CLI qui puisse être distribuée sous forme de binaire unique à notre équipe de développement, nous en avons donc créé une appelée Devgun.

Devgun ne fait aucune supposition sur l’environnement de développement. Il télécharge automatiquement tous les outils dont il a besoin, notamment Minikube, kubectl et les outils spécifiques à Mailgun, dans le répertoire /.devgun/bin. Il vous suffit d’ajouter votre chemin d’accès une fois la configuration initiale terminée. Le fait de tout installer dans un seul répertoire rend la désinstallation aussi simple que rm -rf ~/devgun.
Nous avons compilé tous les fichiers manifestes Kubernetes dans le binaire statique à l’aide du projet go-bindata, ce qui permet de télécharger un seul fichier et de l’exécuter pour installer un environnement de développement.
L’exécution de Devgun ressemble à ceci :
$ devgun startrnPulling kubectl [done] rnPulling minikube [done] rnWriting Minikube configuration [done after 0.702698 seconds] rnBooting Minikube environment [done after 77.297039 seconds] rnWaiting for Kubernetes.. [done] rnINFO[0148] Setting up minikube routes -- enter your sudo password if prompted rnModifying routes [done after 0.012867 seconds] rnAdding kube-dns resolver entry [done after 0.002070 seconds] rnApplying kube-dns-external configuration [done after 0.212881 seconds] rnEnabling Heapster [done after 37.506335 seconds] rn========================================================rnMinikube is now configured and running....rnrn# Set up path for our bin directory with dev toolsrnexport PATH="$PATH:/Users/thrawn/.devgun/bin"rnrnNext you should choose a mailgun service to start using <code data-enlighter-language="generic" class="EnlighterJSRAW">devgun service start</code>rnrn* Use <code data-enlighter-language="generic" class="EnlighterJSRAW">devgun service list</code> to see a list of services to startrn* Use <code data-enlighter-language="generic" class="EnlighterJSRAW">devgun service start</code> to start a service and its dependenciesrn* Use <code data-enlighter-language="generic" class="EnlighterJSRAW">kubectl get pods</code> to list running podsrn* Use <code data-enlighter-language="generic" class="EnlighterJSRAW">kubectl describe pod <pod-name></code> to inspect a pod and see the pod logrn* Use <code data-enlighter-language="generic" class="EnlighterJSRAW">kubectl log <pod-name></code> to see the container logsrn========================================================rn
En plus de créer un environnement Kubernetes, Devgun ajoute également quelques routes réseau au poste local. Par exemple, sur OS X, les routes suivantes sont ajoutées :
route -n add 172.17.0.0/16
route -n add 10.0.0.0/24
Cela permet à notre équipe de développement d’exécuter et de tester des applications sur leurs postes locaux avec une connectivité complète aux conteneurs du cluster K8, comme si elles s’exécutaient dans le cluster lui-même. Nous activons également la recherche DNS en utilisant la fonctionnalité de résolution intégrée à OS X. Nous créons /etc/resolver/local avec le contenu suivant :
search cluster.local svc.cluster.local default.svc.cluster.local
nameserver 172.17.0.3
Cela permet la résolution DNS des services Kubernetes.
$ devgun service start etcdrnStarting service: etcd [done after 7.084730 seconds]rnrn$ ping etcdrnPING etcd.default.svc.cluster.local (172.17.0.4): 56 data bytes rn64 bytes from 172.17.0.4: icmp_seq=0 ttl=63 time=0.220 ms rn^Crn--- etcd.default.svc.cluster.local ping statistics ---rn1 packets transmitted, 1 packets received, 0.0% packet loss rnround-trip min/avg/max/stddev = 0.220/0.220/0.220/0.000 ms
Gérer les services personnalisés et tiers avec une spécification
Puisque Devgun doit gérer un mélange de services personnalisés et tiers, nous avons développé un fichier de spécification YAML personnalisé que nous définissons pour chaque service. Le fichier de spécification ressemble à ceci :
ervice: rn name: scoutrn resources:rn <<: *k8s_deploy_resourcesrn depends_on:rn - name: vulcandrn - name: cassandrarn - name: kafka-pixyrn - name: kafkarn - name: etcdrn - name: metricsrn hooks:rn pre:rn start:rn - exec: >rn cqlsh -e "CREATE KEYSPACE IF NOT EXISTS scout WITH REPLICATION={'class':'SimpleStrategy','replication_factor':1}" $POD_IPrn where: service:cassandra:cassandra
Il définit un service personnalisé appelé « scout », qui lit les événements de Kafka et enregistre des statistiques sur les événements dans Cassandra. La spécification indique à Devgun de quels services personnalisés et tiers il dépend, et quels hooks exécuter sur les différents conteneurs avant de démarrer le service scout.
La clé resources fait référence aux fichiers manifestes Kubernetes (comme ConfigMap, les déploiements et les descriptions de services) définis ailleurs dans le fichier de spécification, que Devgun utilise pour démarrer les conteneurs dans K8.
Et maintenant… les développements futurs
Lorsque nous avons conçu Devgun, nous sommes partis de la base, sans prendre en compte les scénarios de développement et de déploiement plus larges. Maintenant que nous avons eu le temps d’utiliser Devgun, nous nous demandons si nos abstractions sont correctes.
Nous avons commencé à nous poser des questions : quelle expérience voulons-nous offrir à notre équipe de développement lorsqu’elle se prépare à créer et à déployer un nouveau service ? Où s’arrêtent les responsabilités du développement et où commencent celles des opérations ? Quelle part des opérations pouvons-nous automatiser, et quelle part nécessite une intervention humaine ? Comment faciliter la transmission d’informations entre le développement et les opérations ?
Nous avons commencé à définir des scénarios et des personas qui façonneront l’évolution future de Devgun. Dans mon prochain article, je partagerai une partie de notre travail et de nos réflexions sur la façon dont l’expérience de développement pourrait évoluer à mesure que nous continuons à travailler avec Kubernetes et Devgun. Inscrivez-vous à notre blog pour ne rien manquer.