Prochain webinaire : La sécurité d'entreprise pour Claude Code | 21 avril · 11 h PST. Inscrivez-vous ici →

Conteneurs de serveurs SSH pour le développement sur Kubernetes

Par Chirag Jain

Mis à jour : February 29, 2024

Résumez avec

L'année dernière, nous avons discuté de la course à pied Ordinateurs portables Jupyter hébergés et VS Code (serveur de code) sur vos clusters Kubernetes. Nous avons comparé plusieurs approches et solutions existantes, notamment la location et la gestion de machines virtuelles. Nous avons ensuite décrit nos approches pour résoudre les problèmes d'utilisabilité afin de rendre l'expérience plus agréable et d'abstraire les détails de Kubernetes.

Depuis lors, nous avons reçu de nombreux commentaires de la part de nos clients, principalement concernant l'absence d'une meilleure expérience de développement pour les applications à part entière. Bien que Jupyter Lab soit idéal pour les blocs-notes interactifs et l'édition légère, l'intégrer à toutes les fonctionnalités de l'IDE peut nécessiter de nombreuses manipulations avec les extensions Jupyter et ce n'est peut-être pas une bonne expérience pour les bases de code autres que Python. Pour remédier à ces lacunes, nous avons lancé Serveur de code support qui est plus ou moins VS Code dans le navigateur. Bien qu'il s'agisse d'une solution sans configuration et qu'elle atténue de nombreux problèmes liés à l'expérience des développeurs avec Jupyter Lab, les utilisateurs ont signalé des difficultés lors de l'utilisation des extensions VS Code.

Par exemple, Pylance, l'extension qui fournit une excellente prise en charge du langage Python dans VS Code ne peut pas être installée sur Code Server en raison d'une licence propriétaire Microsoft. Au lieu de cela, les utilisateurs doivent compter sur une combinaison de Jedi et Droit d'auteur qui ne sont toujours pas à la hauteur avec Pylance. Un autre exemple est CoPilot sur Github - bien qu'il soit possible de l'installer sur Code Server, il faut modifier manuellement le fichier d'extension et mettre à jour la version de Code Server.

Bien que l'expérience d'édition de Code Server ne soit pas mauvaise, il y a parfois un décalage notable et du texte brouillé dans le terminal, ce qui peut être gênant. Nous avons toujours su que la connexion de VS Code local à un serveur VS Code distant via SSH ou des tunnels serait une meilleure expérience.

L'objectif est de permettre aux utilisateurs de créer un déploiement exécutant OpenSSH Server dans une image de conteneur basée sur Ubuntu avec la même persistance de disque que Jupyter Lab et de permettre aux utilisateurs de s'y connecter.

Voici à quoi cela ressemble sur la plateforme (médecins) :

Dans cet article, nous verrons comment nous avons implémenté la connexion aux conteneurs via SSH sans fournir d'accès direct au cluster et sans envoyer de trafic en dehors du VPC.

Istio et routage

Lorsque nous déployons des applications, nous configurons généralement un nom de domaine pour accéder à ces services, mais l'achat d'un domaine pour chaque application est extrêmement coûteux. Au lieu de cela, nous achetons un seul domaine (par exemple acmecorp.com), configurons des sous-domaines (docs.acmecorp.com) et/ou des préfixes de chemin (acmecorp.com/blog/), puis utilisons un routeur pour faire correspondre les règles et acheminer le trafic vers différentes applications.

Nous utilisons Istio pour tous nos routages d'entrée. Istio, parmi de nombreuses fonctionnalités, propose des abstractions pratiques pour configurer le sous-jacent Envoyé proxy qui gère réellement tout le routage.

Comprenons comment une requête HTTP est routée

Dans ce qui précède, lorsqu'un utilisateur essaie de récupérer https://myapp.acmecorp.com/api/v1

  1. Tout d'abord, *.acmecorp.com est un DNS résolu sur l'adresse IP publique de l'équilibreur de charge externe. Le port est déduit comme 443 en raison du protocole https.
  2. Une connexion TCP est établie avec l'équilibreur de charge et la charge utile de la requête HTTP est envoyée
  3. L'équilibreur de charge achemine la charge utile de la demande vers les pods d'entrée Istio
  4. Istio Ingress a tout l'air Services virtuelsconfiguration des configurations (et de la passerelle), correspond au nom d'hôte (surtout au sous-domaine myapp), au préfixe du chemin et aux routes vers le service Kubernetes correspondant
  5. Kubernetes achemine la demande vers l'un des points de terminaison (Pod) du service

C'est ce qu'on appelle le routage de couche 7 car nous utilisons des champs réels de la spécification HTTP pour effectuer le routage.

Routage dans le contexte de SSH

SSH utilise un protocole personnalisé qui utilise le protocole TCP pour le transport. Une simple connexion SSH ressemble à ce qui suit

ssh user@somemachine.acmecorp.com -p 22

Ici, nous essayons de nous connecter à somemachine.acmecorp.com sur le port 22. Ici, somemachine.acmecorp.com:22 doit se résoudre en une combinaison unique d'adresse IP et de port pour atteindre la destination. Mais n'oubliez pas que dans notre configuration, tous les sous-domaines sont configurés pour pointer vers le même équilibreur de charge. Cela signifie que abc.acmecorp.com, xyz.acmecorp.com, somemachine.acmecorp.com sont tous résolus sur la même adresse IP, puis Istio/Envoy est censé examiner le sous-domaine et décider où acheminer. Mais dans le cas du SSH, cela n'est pas possible car après avoir résolu l'adresse IP et établi une connexion TCP, Istio ne voit que l'adresse IP et le numéro de port de l'équilibreur de charge. Le contenu réel des paquets est crypté par SSH. Alors, comment pouvons-nous acheminer vers plusieurs destinations SSH différentes dans le cluster ?

Option 1 : utiliser des ports uniques sur le même LoadBalancer

Comme nous devons uniquement garantir des combinaisons uniques d'adresses IP et de ports, nous pouvons simplement attribuer différents ports de l'équilibreur de charge à des conteneurs SSH uniques

Nous pouvons ensuite configurer Correspondance de port de route TCP à l'aide d'Istio

Ici, tout le trafic TCP arrivant sur le port 22 du LoadBalancer atteindra le service A et tout le trafic TCP sur le port 23 atteindra le service B.

Bien que cela fonctionne bien, il y a quelques limites

  • Un maximum de 65 535 conteneurs SSH peuvent être atteints avec un seul équilibreur de charge. Ce n'est pas grave car, en réalité, nous ne nous attendons pas à ce que ces nombreux conteneurs SSH soient déployés en même temps.
  • Le problème le plus délicat est d'ouvrir et de libérer des ports de manière dynamique et précise sur l'équilibreur de charge externe sans jamais perturber le trafic normal. Bien que cela soit certainement possible, tout bogue ou problème de concurrence peut entraîner de sérieux temps d'arrêt pour d'autres applications. Sans oublier que l'ouverture de ports arbitraires constitue un risque de sécurité majeur pour nombre de nos clients.

Option 2 : utiliser un nouvel équilibreur de charge pour chaque conteneur SSH

Dans ce cas, nous avons explicitement pointé abc.acmecorp.com et xyz.acmecorp.com vers deux équilibreurs de charge externes différents au lieu du caractère générique *.acmecorp.com. Maintenant, ils pointent chacun vers une adresse IP unique et peuvent être routés par deux adresses différentes. Passerelle Istio (relié un à un équilibreur de charge externe). La limitation évidente est que le provisionnement d'un nouvel équilibreur de charge par conteneur SSH devient prohibitif.

Existe-t-il un moyen de tirer parti du routage au niveau HTTP tout en ne fonctionnant qu'avec le trafic TCP ? Entrez HTTP CONNECT !

Proxy à l'aide de HTTP CONNECT

Le CONNEXION HTTP Cette méthode permet d'établir un « tunnel » entre deux destinations via un proxy. Imaginez l'époque des standards téléphoniques : vous vouliez appeler un numéro mais vous n'avez pas de ligne directe pour le joindre. Au lieu de cela, un opérateur facilite la connexion en votre nom, puis se déplace pour permettre aux deux parties de communiquer.

Telephone switchboard - Wikipedia

Nous vous recommandons de regarder la vidéo suivante pour une bonne explication : https://www.youtube.com/watch?v=PAJ5kK50qp8

Heureusement, dans notre cas, nous utilisons déjà un proxy capable d'utiliser CONNECT - Envoy Proxy. Voyons comment cela fonctionnerait dans notre cas d'utilisation :

  1. Le client ouvre une connexion à acmecorp.com:80, l'équilibreur de charge externe qui achemine le trafic vers Envoy.
  2. Le client envoie une requête HTTP CONNECT

CONNECTEZ svc-a.ns.cluster.svc.local:80 HTTP/1.1
Hébergeur : svc-a.ns.cluster.svc.local

qui demande à Envoy d'établir une connexion TCP à svc-a.ns.cluster.svc.local:80 en leur nom

  1. Une fois la connexion établie, A 200 OK est renvoyé au client.
  2. Après cette étape, Envoy cesse de se soucier du contenu du trafic et agit comme un « tunnel » permettant au trafic de circuler entre le client et le pod. Il peut s'agir de tout ce qui fonctionne au-dessus de TCP, y compris, mais sans s'y limiter, SSH.

Notez que svc-a.ns.cluster.svc.local:80 est un service Kubernetes qui ne pointe vers aucune adresse IP publique. Il ne peut être résolu que dans le cluster Kubernetes. Comme Envoy se trouve à l'intérieur du cluster, nous pouvons le configurer pour atteindre les modules situés derrière lui.

Il ne reste plus qu'à configurer Envoy pour effectuer ce routage. Malheureusement, Istio ne dispose pas d'abstractions de haut niveau pour le configurer facilement. Nous devons plutôt appliquer des correctifs à la configuration d'Envoy en utilisant Filtres Envoy

Filtres Envoy

Comprendre les fonctionnalités d'Envoy et les filtres Envoy est hors de portée de cet article de blog, mais considérez-le simplement comme un moyen pratique de modifier les règles de routage d'Istio à l'aide de petits correctifs. Pour activer le routage basé sur CONNECT, nous devons

  1. Avoir un port exposé au public sur Équilibreur de charge pour accepter le trafic TCP (par exemple 2222) et configurer le trafic correspondant Passerelle Istio pour accepter le trafic HTTP. Nous avons choisi de nous en tenir au port 80 car nous l'utilisons déjà pour le trafic HTTP normal et le trafic SSH va être chiffré de toute façon.
  2. Configurez le port exposé publiquement sur Gateway pour accepter les demandes de type CONNECT. Nous avons constaté que cette option est déjà activée pour les requêtes adressées au port 80. Pour tout autre port, vous pouvez appliquer un filtre Envoy comme suit :
Par exemple, activez CONNECT sur le port 2222APIVersion : networking.istio.io/v1alpha3
type : EnvoyFilter
spécification :
Correctifs de configuration :
- Appliquer à : NETWORK_FILTER
match :
contexte : GATEWAY
auditeur :
Chaîne de filtres :
filtre :
nom : envoy.filters.network.http_connection_manager
Numéro du port : 2222
patch :
opération : MERGE
valeur :
configuration_saisie :
« @type » : ->-
Tapez .googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
options_de_protocol_http2 :
allow_connect : vrai
upgrade_configs :
- type_de mise à niveau : CONNEXION
Sélecteur de charge de travail :
étiquettes :
application : tfy-istio-ingress
  1. Pour chaque conteneur SSH, configurez le routage basé sur CONNECT :

Version de l'API : networking.istio.io/v1alpha3
type : EnvoyFilter
métadonnées :
nom : svc-a-ns-ssh-envoy-filter
espace de noms : istio-system
spécification :
Correctifs de configuration :
- Appliquer à : NETWORK_FILTER
match :
contexte : GATEWAY
auditeur :
Chaîne de filtres :
filtre :
nom : envoy.filters.network.http_connection_manager
Numéro de port : 80
patch :
opération : MERGE
valeur :
configuration_saisie :
« @type » : ->-
Tapez .googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
configuration_route :
nom : local_route
hôtes_virtuels :
- domaines :
- svc-a.ns.svc.cluster.local : 80
nom : svc-a-ns-ssh-vh
itinéraires :
- match :
connect_matcher : {}
itinéraire :
cluster : >-
sortant|80||svc-a.ns.svc.cluster.local
upgrade_configs :
- connect_config : {}
activé : vrai
type_de mise à niveau : CONNEXION
Sélecteur de charge de travail :
étiquettes :
Adresse : tfy-istio-ingress

C'est un YAML très effrayant, mais nous ne faisons que modifier l'écouteur sur le port 80 de la passerelle pour qu'il corresponde à la requête CONNECT à svc-a.ns.svc.cluster.local:80 et les acheminer vers outbound|80||svc-a.ns.svc.cluster.local, c'est-à-dire le port 80 du service Kubernetes svc-a.ns.svc.cluster.local où notre serveur OpenSSH attend pour les connexions SSH à l'intérieur du conteneur.

Lancer CONNECT côté client SSH

À lui seul, le client SSH ne sait rien de HTTP CONNECT. Au lieu de cela, il propose une Commande proxy option qui permet à d'autres programmes de faciliter la connexion SSH. Ici, nous utilisons Tunnel proxy projet qui facilite les choses. La configuration dans ~/.ssh/config ressemble à ce qui suit

Héberger svc-a-ns
Utilisateur jovyan
Nom d'hôte svc-a.ns.svc.cluster.local
Portée 80
ServerAliveInterval 100
Fichier d'identité ~/.ssh/my-private-key
ProxyCommand proxytunnel -v -p ssh.acmecorp.com:80 -o %h -d %h : %p

Une fois cela fait, les utilisateurs peuvent désormais se connecter et configurer facilement leur flux de travail de développement préféré, qu'il s'agisse de Neovim, VS Code, JetBrains IDE, etc.

Limites et solutions potentielles

Bien que cette fonctionnalité améliore considérablement l'expérience des développeurs en termes d'édition et d'exécution du code, certaines limites s'appliquent toujours car nous fonctionnons toujours dans un conteneur.

  • Docker ne fonctionne pas car nous sommes déjà dans un conteneur. Théoriquement, il est possible de faire fonctionner certaines choses avec DIND, mais elle comporte ses défis.
  • Modifications apportées au système de fichiers racine du conteneur / ne persistent pas lors des redémarrages du conteneur. Nous proposons un moyen d'étendre notre image de serveur SSH et de partir de ces images personnalisées.
  • Les Kubernetes Pods sont conçus pour être éphémères et peuvent être déplacés, mais cela n'est pas souhaitable pour un environnement de développement. Nous configurons les budgets d'interruption des modules pour empêcher leur déplacement.
  • Même si le proxy est transparent, le trafic circule toujours via l'équilibreur de charge et les pods Istio Envoy. Cela signifie que faire quelque chose d'étrange en cours de développement, comme télécharger/télécharger de gros fichiers, peut consommer de la bande passante et des ressources et affecter le reste du trafic. Il est préférable d'utiliser un ensemble distinct de pods LoadBalancer, Gateway et Envoy pour la connexion aux conteneurs SSH.

Conteneurs de serveurs SSH sur Kubernetes chez TrueFoundry

True Foundry est un PaaS de déploiement ML/LLM sur Kubernetes destiné à accélérer les flux de travail des développeurs tout en leur offrant une flexibilité totale dans les tests et le déploiement de modèles tout en garantissant une sécurité et un contrôle complets à l'équipe Infra. Grâce à notre plateforme, nous permettons aux équipes de déployer et surveiller des modèles en 15 minutes avec une fiabilité à 100 %, une évolutivité et la possibilité de revenir en arrière en quelques secondes, ce qui leur permet de réduire les coûts et de mettre les modèles en production plus rapidement, ce qui permet de réaliser une véritable valeur commerciale.

Le moyen le plus rapide de créer, de gérer et de faire évoluer votre IA

INSCRIVEZ-VOUS
Table des matières

Gouvernez, déployez et suivez l'IA dans votre propre infrastructure

Réservez un séjour de 30 minutes avec notre Expert en IA

Réservez une démo

Le moyen le plus rapide de créer, de gérer et de faire évoluer votre IA

Démo du livre

Découvrez-en plus

October 5, 2023
|
5 min de lecture

<Webinar>Vitrine GenAI pour les entreprises

Best Fine Tuning Tools for Model Training
May 3, 2024
|
5 min de lecture

Les 6 meilleurs outils de réglage pour la formation des modèles en 2026

May 25, 2023
|
5 min de lecture

LLMs open source : Embrace or Perish

August 27, 2025
|
5 min de lecture

Cartographie du marché de l'IA sur site : des puces aux plans de contrôle

 Best AI Gateways in 2026
April 22, 2026
|
5 min de lecture

5 meilleures passerelles IA en 2026

comparaison
April 22, 2026
|
5 min de lecture

Intégration de Cline avec TrueFoundry AI Gateway

Outils LLM
Detailed Guide to What is an AI Gateway?
April 22, 2026
|
5 min de lecture

Qu'est-ce qu'AI Gateway ? Concepts de base et guide

Aucun article n'a été trouvé.
April 22, 2026
|
5 min de lecture

LLM Embeddings 101 : un guide complet 2024

Terminologie LLM
Aucun article n'a été trouvé.

Blogs récents

Faites un rapide tour d'horizon des produits
Commencer la visite guidée du produit
Visite guidée du produit