Exécution d’applications tierces dans des conteneurs
Pour exécuter vos propres applications sur Junos OS Evolved, vous avez la possibilité de les déployer en tant que conteneur Docker. Le conteneur s’exécute sur Junos OS Evolved et les applications s’exécutent dans le conteneur, ce qui les isole du système d’exploitation hôte. Les conteneurs sont installés dans une partition distincte montée sous /var/extensions. Les conteneurs persistent malgré les redémarrages et les mises à niveau logicielles.
Les conteneurs Docker ne sont pas intégrés dans Junos OS Evolved, ils sont créés et gérés entièrement via Linux à l’aide de commandes Docker. Pour plus d’informations sur les conteneurs et les commandes Docker, consultez la documentation officielle de Docker : https://docs.docker.com/get-started/
Les conteneurs ont des limites par défaut pour les ressources qu’ils peuvent utiliser à partir du système :
-
Storage – La taille de la partition /var/extensions est basée sur la plate-forme : 8 Go ou 30 % de la taille totale de /var, selon la plus petite des deux.
-
Memory – Les conteneurs n’ont pas de limite de mémoire physique par défaut. Cela peut être modifié.
-
CPU – Les conteneurs n’ont pas de limite de CPU par défaut. Cela peut être modifié.
Vous pouvez modifier les limites de ressources sur les conteneurs si nécessaire. Reportez-vous à la section Modification des limites de ressources pour les conteneurs.
Déploiement d’un conteneur Docker
Pour déployer un conteneur Docker :
Gestion d’un conteneur Docker
Les conteneurs Docker sont gérés via un flux de travail Docker Linux standard. Utilisez les docker ps
commandes , ps
ou top
Linux pour afficher les conteneurs Docker en cours d’exécution, et utilisez les commandes Docker pour gérer les conteneurs. Pour plus d’informations sur les commandes Docker, consultez : https://docs.docker.com/engine/reference/commandline/cli/
Les fonctionnalités de haute disponibilité de Junos OS Evolved ne sont pas prises en charge pour les applications personnalisées dans les conteneurs Docker. Si une application dispose d’une fonctionnalité de haute disponibilité, vous devez exécuter l’application sur chaque RE pour vous assurer qu’elle peut se synchroniser. Une telle application devra avoir la logique métier requise pour se gérer et communiquer avec toutes les instances.
Activation de Netlink ou de PacketIO dans un conteneur
Vous devez fournir des arguments supplémentaires aux commandes Docker si votre conteneur nécessite des fonctionnalités supplémentaires telles que Netlink ou PacketIO. Vous devrez également activer nlsd
le service pour activer la fonctionnalité Netlink sur certaines versions. L’exemple suivant montre comment activer les fonctionnalités Netlink ou PacketIO pour un conteneur en ajoutant des arguments à une commande Docker :
Créez un volume persistant de nom en lecture seule au démarrage des services Docker. Le montage du volume permet de monter les
jnet
bibliothèques nécessaires à la fonctionnalité PacketIO et Netlink sur les ports WAN/données :--mount source=jnet,destination=/usr/evo
Partagez l’espace de noms Network et IPC de l’hôte avec le conteneur. Les conteneurs nécessitant les fonctionnalités PacketIO et Netlink sur des ports WAN/de données devront se trouver dans l’espace de noms du réseau hôte et de l’IPC :
--network=host --ipc=host
Démarrez automatiquement le conteneur au redémarrage du système :
--restart=always
Activez la fonctionnalité d’administration réseau, requise par les bibliothèques Netlink et PacketIO :
--cap-add=NET_ADMIN
Activez les variables d’environnement requises pour Netlink et PacketIO sur les ports WAN/de données :
--env-file=/run/docker/jnet.env
Montez le périphérique jtd0 de l’hôte au conteneur pour faciliter la gestion de PacketIO :
--device=/dev/jtd0
Montez le répertoire /dev/shm de l’hôte dans le conteneur pour Netlink et PacketIO sur les ports WAN/données :
-v /dev/shm:/dev/shm
Si la gestion des groupes multicast est requise par l’application de conteneur, montez le répertoire /dev/mcgrp de l’hôte vers le conteneur :
-v /dev/mcgrp:/dev/mcgrp
Après la version 24.1R1 de Junos OS Evolved, les conteneurs de l’espace de noms du réseau hôte qui souhaitent disposer d’une résolution DNS doivent transmettre l’option
--dns ::1
à ladocker run
commande. Ceci n’est pas requis pour Junos OS Evolved version 23.4 et antérieure :--dns ::1
Si votre conteneur nécessite un traitement lié à Netlink, vous devez également activer le processus d’API asynchrone Netlink (
nlsd
) dans Junos OS Evolved avec la configuration CLI suivante :[edit] user@host# set system processes nlsd enable
Les applications natives Linux ou basées sur des conteneurs qui nécessitent les fonctionnalités PacketIO et Netlink doivent être liées dynamiquement. Nous vous recommandons d’utiliser des conteneurs Docker basés sur Ubuntu, car ce sont les seuls conteneurs officiellement qualifiés par Juniper Networks. Les conteneurs basés sur Ubuntu doivent utiliser le glibc
compatible avec le système d’exploitation Junos Evolved de glibc
base .
Sélection d’un VRF pour un conteneur Docker
Pour Junos OS Evolved versions 23.4R1 et antérieures, les conteneurs héritent du VRF (Virtual Routing and Forwarding) du processus Docker. Pour exécuter des conteneurs dans un VRF distinct, une instance de processus Docker doit être démarrée dans le VRF correspondant. L’instance docker@vrf.service
permet de démarrer un processus dans le VRF correspondant. Si le VRF n’est pas spécifié, la valeur par défaut du VRF est vrf0
.
Le docker.service
s’exécute vrf:none
par défaut.
Pour Junos OS Evolved versions 24.1R1 et ultérieures, nous vous recommandons de lier une tâche spécifique dans le conteneur à un VRF Linux spécifique à l’aide de la ip vrf exec task
commande. Cela nécessite que le conteneur soit démarré avec l’option --privileged
, et qu’une version compatible du iproute2
conteneur soit installée. Le conteneur doit également partager l’espace de noms du réseau avec l’hôte. Vous pouvez également utiliser l’option SO_BINDTODEVICE
socket pour lier le socket d’une tâche ou d’une application spécifique dans le conteneur à un périphérique VRF Linux spécifique, auquel cas iproute2
ce n’est pas nécessaire.
La ip vrf show
commande répertorie tous les VRF Linux disponibles. Si vous choisissez de lier les sockets d'une tâche dans le conteneur à un VRF à l'aide iproute2
de , nous vous recommandons d'écraser certaines variables env à l'aide --env-file=/run/docker-vrf0/jnet.env
de , afin libnli.so
qu'il ne soit pas préchargé pour éviter qu'il n'interfère avec iproute2
.
Vous pouvez lancer un conteneur et lier le socket associé à la tâche du conteneur au vrf vrf0
par défaut à l'aide des commandes suivantes :
[vrf:none] user@host:~# docker -H unix:///run/docker-vrf0.sock run --rm -it –-privileged --network=host --ipc=host --cap-add=NET_ADMIN --mount source=jnet,destination=/usr/evo --device=/dev/jtd0 -v /dev/mcgrp:/dev/mcgrp -v /dev/shm:/dev/shm --env-file=/run/docker-vrf0/jnet.env --dns ::1 debian:stretch bash # explicitly preload libsi.so and avoid libnli.so. Bind ping’s socket to vrf0 (default) VRF [vrf:none] user@host: my-container/# LD_PRELOAD=libsi.so.0 ip vrf exec vrf0 ping 1.2.3.4
Avec cette approche, différentes sockets associées à différentes tâches dans le conteneur peuvent être associées à différents VRF au lieu de toutes les sockets liées à un seul VRF.
Le processus Docker d’un VRF spécifique écoute sur la socket correspondante située dans /run/docker-vrf.sock.
Il s’agit du VRF tel qu’on le voit sur Linux et non du VRF Junos OS Evolved. L’utilitaire evo_vrf_name
(disponible à partir de Junos OS Evolved version 24.1) peut être utilisé pour trouver le VRF Linux qui correspond à un VRF Junos OS Evolved.
Le client Docker est associé au processus Docker spécifique au VRF à l’aide des arguments suivants :
--env-file /run/docker-vrf/jnet.env --host unix:///run/docker-vrf.sock or export DOCKER_HOST=unix:///run/docker-vrf.sock
Par exemple, pour exécuter un conteneur dans vrf0
, entrez la commande Docker et les arguments suivants :
[vrf:none] user@host:~# docker -H unix:///run/docker-vrf0.sock run --rm -it --network=host --ipc=host --cap-add=NET_ADMIN --mount source=jnet,destination=/usr/evo --device=/dev/jtd0 -v /dev/mcgrp:/dev/mcgrp -v /dev/shm:/dev/shm --env-file=/run/docker-vrf0/jnet.env --dns ::1 debian:stretch ip link 1002: et-01000000000: BROADCAST,MULTICAST,UP mtu 1514 state UP qlen 1 link/ether ac:a:a:18:01:ff brd ff:ff:ff:ff:ff:ff 1001: mgmt-0-00-0000: BROADCAST,MULTICAST,UP mtu 1500 state UP qlen 1 link/ether 50:60:a:e:08:bd brd ff:ff:ff:ff:ff:ff 1000: lo0_0: LOOPBACK,UP mtu 65536 state UP qlen 1 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
Un conteneur ne peut être associé qu’à un seul VRF.
Modification des limites de ressources pour les conteneurs
Les limites de ressources par défaut pour les conteneurs sont contrôlées par le biais d’un fichier situé dans /etc/extensions/platform_attributes. Le texte suivant s’affiche à l’ouverture de ce fichier :
## Edit to change upper cap of total resource limits for all containers. ## applies only to containers and does not apply to container runtimes. ## memory.memsw.limit_in_bytes = EXTENSIONS_MEMORY_MAX_MIB + EXTENSIONS_MEMORY_SWAP_MAX_MIB:-0 ## please start extensions-cglimits.service to apply changes to CPU and Memory values here ## please restart var-extensions.mount to apply changes to partition resize here ## make sure the docker daemon is stopped before changing mount size ## For changing EXTENSIONS_FS_DEVICE_SIZE_MIB, please also remove file rm /var/extensions_fs ## make sure to create a backup before partition resize ## check current defaults, after starting extensions-cglimits.service ## $ /usr/libexec/extensions/extensions_cglimits get ## you can also set current values like this as an alternative to starting extensions-cglimits.service ## $ /usr/libexec/extensions/extensions_cglimits set ## if you set one of the memory values, set the other one as well – mandated by cgroup ## device size limit will be ignored once extensionsfs device is created #EXTENSIONS_FS_DEVICE_SIZE_MIB= #EXTENSIONS_CPU_QUOTA_PERCENTAGE= #EXTENSIONS_MEMORY_MAX_MIB= #EXTENSIONS_MEMORY_SWAP_MAX_MIB=
Pour modifier les limites de ressources pour les conteneurs, ajoutez des valeurs aux EXTENSIONS
entrées au bas du fichier. Assurez-vous de le faire avant de démarrer le processus Docker.
-
EXTENSIONS_FS_DEVICE_SIZE_MIB=
Contrôle l’espace de stockage maximal que les conteneurs peuvent utiliser. Entrez la valeur en mégaoctets. La valeur par défaut est 8000 ou 30 % de la taille totale de /var, selon la valeur la plus petite. Assurez-vous d’ajouter cette entrée avant de démarrer le processus Docker pour la première fois. Si vous devez modifier cette valeur ultérieurement, vous devrez supprimer la partition existante, ce qui peut entraîner une perte de données sur cette partition. Si cette partition de stockage doit être modifiée après le démarrage du service Docker, le processus Docker doit d’abord être arrêté avec lasystemctl stop docker
commande, et la partition existante peut être supprimée à l’aide de lasystemctl stop var-extensions.mount
commande suivie de larm /var/extensions_fs
commande. Une fois cet attribut modifié, redémarrez le processus Docker et la nouvelle partition avec la taille spécifiée sera créée. Vous pouvez également redémarrervar-extensions.mount
avec lasystemctl restart var-extensions.mount
commande pour obtenir le même résultat. Nous vous suggérons de faire une sauvegarde de la partition pour éviter de perdre des données importantes. Nous vous déconseillons d’augmenter cette valeur au-delà de 30 % de la partition /var , car cela pourrait affecter le fonctionnement normal de Junos OS Evolved. -
EXTENSIONS_CPU_QUOTA_PERCENTAGE=
contrôle l’utilisation maximale de l’UC que les conteneurs peuvent utiliser. Entrez une valeur en pourcentage de l’utilisation du processeur. La valeur par défaut est de 20 %, mais peut varier en fonction de la plateforme. -
EXTENSIONS_MEMORY_MAX_MIB=
Contrôle la quantité maximale de mémoire physique que les conteneurs peuvent utiliser. Entrez la valeur en mégaoctets. La valeur par défaut est 2000 mais elle peut varier en fonction de la plateforme. Si cela doit être modifié, la valeurEXTENSIONS_MEMORY_SWAP_MAX_MIB=
d’échange doit également être spécifiée. Notez que Linuxcgroup
ne permet pas de définir des valeurs déraisonnables pour les limites de mémoire et de processeur. Si les valeurs définies ne sont pas reflétées dans lecgroup
, la raison la plus probable est que les valeurs sont incorrectes (éventuellement très élevées ou très faibles). -
EXTENSIONS_MEMORY_SWAP_MAX_MIB=
Contrôle la quantité maximale de mémoire d’échange que les conteneurs peuvent utiliser. Entrez la valeur en mégaoctets. La valeur par défaut est de 15 % de l’espace d’échange disponible, mais elle peut varier en fonction de la plateforme. Les deux etEXTENSION_MEMORY_MAX_MIB=
EXTENSIONS_MEMORY_SWAP_MAX_MIB=
doivent être définis si l’un ou l’autre est en cours de modification. La valeur recommandée pour le swap est de 15 % deEXTENSION_MEMORY_MAX_MIB=
. La valeur réellecgroup
de swap seraitEXTENSION_MEMORY_MAX_MIB
+EXTENSIONS_MEMORY_SWAP_MAX_MIB
.
Par défaut, celles-ci sont définies sur des valeurs spécifiques à la plate-forme, nous vous recommandons donc de définir les valeurs avant de démarrer les conteneurs.
Avant de modifier les limites de ressources pour les conteneurs, renseignez-vous sur les exigences en matière de processeur et de mémoire pour la mise à l’échelle que vous devez prendre en charge dans votre configuration. Faites preuve de prudence lorsque vous augmentez les limites de ressources pour les conteneurs afin d’éviter qu’elles ne mettent votre système à rude épreuve.