Website Logo. Upload to /source/logo.png ; disable in /source/_includes/logo.html

Zuzur’s wobleg

technology, Internet, and a bit of this and that (with some dyslexia inside)

Rancher: Les Outils en Ligne De Commande

| Comments

J’adore les jolis clickodromes, mais en matière d’infrastructure, avoir des outils qu’on peut appeler depuis d’autres outils est absolument indispensable. Par exemple:

  • dans ce qu’on appelle une forge logicielle, on pourrait vouloir faire en sorte qu’un commit dans la branche develop de nos source provoque le déploiement de la nouvelle version du conteneur sur la plate-forme de test
  • dans une infrastructure gérée par un outil comme chef ou terraform, les agents vont avoir besoin de déployer automatiquement un agent, et d’indiquer au serveur la présence de cette nouvelle machine.

On a donc besoin d’outils en ligne de commande, utilisables dans des scripts pour faire ça.

Ca tombe bien, les développeurs de Rancher on prévu le coup. Tous les services sont exposés par une API et l’interface Web est, assez logiquement, une applcation construite autour de cette API, et des programmes sont disponibles pour gérer tout ça depuis la ligne de commande…

composants logiques d’un cluster rancher

Un cluster rancher se compose des systèmes suivant:

  • tout au dessus, un environnement c’est l’ensemble des machines qui, connectées via l’agent rancher au serveur, permettent de lancer des conteneur et de mettre à disposition des services. Un seul serveur Rancher peut, par exemple, gérer un environnement ‘Development’ où seront déployés les conteneurs de la version de développement d’un système, et un autre environnement ‘Production’ où cette fois-ci, c’est la version de production des mêmes services qui seront déployés. Chaque environnement peut utiliser un système de gestion de cluster différent. On peut donc parfaitement imaginer que ‘Development’ soit déployé avec Cattle et que la production utilise Kubernetes ou Docker Swarm. C’est lors de la définition de l’environnement qu’on décide de la façon dont il va être orchestré.
  • des hosts - des machines avec un démon docker qui fait fonctionner l’agent docker pour un environnement donné. De la même façon, on peut parfaitement imaginer que les machines déployées pour ‘Development’ soient des machines moins puissantes que pour ‘Production’ - c’est d’ailleurs ce que je mets souvent en oeuvre pour mes clients.
  • des services (stacks). Un service est un ensemble de conteneurs - le serveur met en place tout le nécessaire, y compris un DNS interne géré à l’aide du service metadata, pour que les conteneurs d’un même service puisse parler entre eux. On peut aussi, grâce à ce serveur DNS avoir accès à des conteneurs déployés sur une autre stack dans le même environnement
  • et enfin, les conteneurs à proprement parler.

Si vous allez dans le menu “Infrastructure” de votre serveur rancher, vous pouvez avoir un aperçu de ces composants.

rancher et rancher-compose

pour contrôler un service déployé dans un cluster rancher - et le cluster lui-même, on dispose de deux commandes. rancher et rancher-compose. On peut les télécharger directement depuis l’interface de rancher, ou, par exemple, elles sont disponibles dans Homebrew sur un mac.

On peut les utiliser depuis n’importe quelle machine qui a accès au serveur. Pour ma part, je les ai installées sur mon poste de travail…

rancher-compose

rancher-compose est l’équivalent de la commande docker-compose de docker. docker-compose permet de déployer une stack sur un seul démon docker (donc une machine), rancher-compose permet de spécifier à la fois les conteneur qu’on va démarrer et leurs paramètres et de spécifier la façon dont rancher doit les orchestrer. Ce qui est intéressant, c’est que si on part d’une stack existante basée sur docker-compose ou qu’on trouve un docker-compose.yml dans un repository git, on peut directement la déployer sur rancher avec `rancher-compose.

rancher

rancher permet de controler l’ensemble de l’environnement - services, stacks, etc… on peut faire la même chose qu’avec rancher-compose sur une stack, mais on peut aussi contrôller, stopper, et créer des services. Il va un peu plus loin que rancher-compose et je pense qu’à l’avenir, les deux commandes ne feront plus qu’une.

Authentification par clés

Pour vous authentifier auprès du serveur, ces outils utilisent un login et un mot de passe qu’il génère lui même. Un administrateur de l’environnement peut en créer autant qu’il veut. Ensuite il faut les mettre dans l’environnement de votre shell, dans les variables RANCHER_URL, RANCHER_ACCESS_KEY et RANCHER_SECRET_KEY.

Dans le menu “API -> Keys” du serveur:

on peut créer des clés pour l’accès à l’API rancher depuis un autre programme (API keys) et, après avoir clické sur “Advanced options”, des clés d’environnement. C’est de ce type de clés qu’on a besoin pour utiliser les outils en ligne de commande de rancher. Une clé d’API ne vous permet pas de modifier l’environnement - c’est à dire créer et supprimer des services dans l’environnement.

Pour le moment, rancher et rancher-compose ne permette que d’utiliser ces variables d’environnement et des options en ligne de commande pour les spécifier. Comme je commence à avoir pas mal de projets avec rancher, je stocke des petits scripts qui mettent l’environnement du shell à jour dans ~/.rancher - un par environnement rancher - et je les source dans le shell pour travailler dessus. C’est vraiment un pis-aller, et j’espère que rancher proposera bientôt la possibilité d’avoir, à l’instar des outils AWS, des profiles différents stockés dans un seul endroit. Pour le moment, il faut se contenter de ça…

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
$ mkdir -p ~/.rancher
$ cat <<EOF > ~/.rancher/test.sh
#!/bin/sh
export RANCHER_URL=https://test.domaine.com:4430
export RANCHER_ACCESS_KEY=xxxxxxxxxxxxxxxxxxxxx
export RANCHER_SECRET_KEY=yyyyyyyyyyyyyyyyyyyyyyyyyyyy
EOF
$ . ~/.rancher/test.sh # les variables sont dans le shell local
$ rancher ps -s -c # montre les services système aussi bien que les conteneurs utilisateurs, avec les conteneurs sur lesquels  ils sont déployés
ID        NAME                                 IMAGE                                                      STATE     HOST      IP              DOCKER         DETAIL
1i893     dnsupdate-rfc2136-rfc2136dns-1       rancher/external-dns:v0.6.2                                healthy   1h2       10.42.34.224    3f6171c85f46
1i894     bind9-bind9-1                        digitallumberjack/docker-bind9:v1.2.0                      healthy   1h2       10.42.121.56    cb428be7b285
1i895     scheduler-scheduler-1                rancher/scheduler:v0.7.5                                   healthy   1h2       10.42.224.198   2ccb9e08c9a5
1i896     rancher-server                       rancher/server:stable                                      running   1h2       172.17.0.2      7039a54daee9
1i897     rancher-nginx                        nginx:alpine                                               running   1h2       172.17.0.3      48d8c574e654
1i904     network-services-network-manager-2   rancher/network-manager:v0.6.6                             running   1h2                       14317dd6a0a3
1i905     ipsec-ipsec-cni-driver-1             rancher/net:v0.11.2                                        running   1h2                       2418b4f41ecc
1i906     network-services-metadata-1          rancher/metadata:v0.9.1                                    running   1h2       172.17.0.4      0a29e5a1fb49
1i907     ipsec-ipsec-1                        rancher/net:holder                                         running   1h2       10.42.80.206    2d37f517ebda
1i909     ipsec-ipsec-router-1                 rancher/net:v0.11.2                                        running   1h2                       dcd453a3a589
1i910     network-services-metadata-dns-1      rancher/dns:v0.14.2                                        running   1h2                       a25c286f3884
1i914     healthcheck-healthcheck-2            rancher/healthcheck:v0.2.3                                 healthy   1h2       10.42.63.227    9953bd46ed61
1i940     rancher-agent                        rancher/agent:v1.2.2                                       running   1h2                       26813ab35c47
...

On remarque qu’on retrouve les conteneurs rancher-server, rancher-agent et rancher-nginx qu’on a déployés dans le billet précédent. On voit tous les conteneurs qui fonctionnent sur le host 1h2, on a leur id rancher (par exemple 1i894), et leur id dans docker (cb428be7b285). Les conteneurs de rancher ont une addresse IP dans le réseau 10.42/16. On ne peut pas atteindre ces addresses depuis la machine. Les tables de routage du host n’ont aucune idée de comment atteindre ce réseau. Et rappelez-vous qu’il peut y avoir plusieurs machines dans le cluster. Par contre, grâce au service ipsec fourni par rancher et cattle, chaque conteneur de l’infrastructure pourra se connecter à un service qui écoute sur une de ces adresses.

On peut d’ailleurs essayer tout de suite :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
$ rancher exec -it ipsec /bin/sh
Containers:
[1] ipsec-ipsec-cni-driver-1 ()
[2] ipsec-ipsec-1 (10.42.80.206)
[3] ipsec-ipsec-router-1 ()
Select: 2
# cat /etc/lsb-release
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=16.04
DISTRIB_CODENAME=xenial
DISTRIB_DESCRIPTION="Ubuntu 16.04.1 LTS"
# ping 10.42.63.227
PING 10.42.63.227 (10.42.63.227) 56(84) bytes of data.
64 bytes from 10.42.63.227: icmp_seq=1 ttl=64 time=0.273 ms
64 bytes from 10.42.63.227: icmp_seq=2 ttl=64 time=0.095 ms
64 bytes from 10.42.63.227: icmp_seq=3 ttl=64 time=0.078 ms
64 bytes from 10.42.63.227: icmp_seq=4 ttl=64 time=0.084 ms
64 bytes from 10.42.63.227: icmp_seq=5 ttl=64 time=0.091 ms
^C
--- 10.42.63.227 ping statistics ---
5 packets transmitted, 5 received, 0% packet loss, time 3999ms
rtt min/avg/max/mdev = 0.078/0.124/0.273/0.074 ms
# ping healthcheck.healthcheck.rancher.internal
PING healthcheck.healthcheck.rancher.internal (10.42.63.227) 56(84) bytes of data.
64 bytes from 10.42.63.227: icmp_seq=1 ttl=64 time=0.090 ms
64 bytes from 10.42.63.227: icmp_seq=2 ttl=64 time=0.087 ms
64 bytes from 10.42.63.227: icmp_seq=3 ttl=64 time=0.088 ms
64 bytes from 10.42.63.227: icmp_seq=4 ttl=64 time=0.090 ms
64 bytes from 10.42.63.227: icmp_seq=5 ttl=64 time=0.081 ms
^C
--- healthcheck.healthcheck.rancher.internal ping statistics ---
5 packets transmitted, 5 received, 0% packet loss, time 4001ms
rtt min/avg/max/mdev = 0.081/0.087/0.090/0.006 ms

On a demandé à rancher d’exécuter /bin/sh dans le service ipsec

  • la commande rancher s’est connectée au serveur
  • après avoir validé l’accès, le serveur s’est connecté, rancher a découvert que plusieurs conteneurs fonctionnent dans la stack ipsec, et vous demande sur lequel vous voulez vous connecter - dans cet exemple, c’est le n°2 qui nous intéresse
  • le serveur se connecte ensuite via l’agent au serveur docker sur le host(1h2) où fonctionne le conteneur ipsec-ipsec-1.
  • docker exécute ensuite la commande /bin/sh dans le conteneur, et comme on a passé le flag -it, a gardé l’entrée standard ouverte et alloué un pseudo-terminal. On peut donc taper une commande depuis le conteneur, comme si on s’était loggé dessus par ssh - encore un truc sympa avec docker et rancher.
  • on tombe dans un vrai système unix, on est root (mais ça peut se changer quand on fabrique le conteneur) et on a accès à toutes les commandes qui sont installées dessus. En l’occurence, cette image est basée sur une Ubuntu Xenial. On peut faire toutes les modifications que l’on souhaite sur un conteneur qui fonctionne - ça arrive souvent quand on débugge, par exemple une configuration haproxy, MAIS toute modification sur un conteneur qui fonctionne sera irrémédiablement perdue (à moins d’acrobaties avec les volumes de docker, directement sur le host) si jamais le service est redémarré. C’est le principe de docker. On repart toujours d’un état reproductible automatiquement, et donc d’images qu’on a poussées dans le démon docker - ou dans un registry quand on commence à travailler sérieusement.
  • on a pingué le service healthcheck par l’adresse qu’on avait trouvé dans la sortie de rancher ps
  • on a aussi confirmé que rancher fournit un service DNS en utilisant le nom healthcheck.healthcheck.rancher.internal. Chaque service peut être addressé ainsi: <service>.<stack>.rancher.internal. Je n’en suis pas sûr, mais je pense qu’on peut changer ce schéma dans la configuration de rancher, au besoin.

Rappelez vous que dans le billet sur nginx et la terminaison SSL, on avait mis ce paramètre dans la configuration de nginx:

1
2
# This allows the ability for the execute shell window to remain open for up to 15 minutes. Without this parameter, the default is 1 minute and will automatically close.
proxy_read_timeout 900s;

Et oui ! on peut rester 15 minutes connecté sans rien faire avant que nginx ne referme la connexion. En production, je vous conseille de baisser fortement ce paramètre - 1 ou 2 minutes pas plus.

On est donc prêts à déployer enfin notre premier service dans Rancher. Pour le fun, je me propose de vous montrer comment déployer un petit blog avec octopress, avec du load balancing, et une terminaison SSL avec letsencrypt, le tout mis à jour automatiquement1… dans le prochain billet


  1. oui, en effet c’est encore un magnifique exemple de canon à mouches, mais vous verrez, c’est intéressant ! enfin, moi, je trouve ça intéressant ;-)

Comments