Configuration d'envoy comme proxy frontal sur Docker avec communication vers d'autres conteneurs Docker

J'ai déjà des conteneurs existants pour lesquels je veux utiliser envoy comme proxy et gestionnaire https. J'apprends à utiliser envoy, et je partage ici certaines de mes connaissances, car la documentation est un peu confuse au départ.

Mon conteneur existant s'appelle "taxgod". Il exécute une application Crystal sur le port 3000 (http). Je veux le proxyer sur le port 80 de l'hôte pour http, et le port 443 pour https.

Je vais utiliser un faux certificat à des fins de démonstration. La création de certificats n'entre pas dans le cadre de cet article.

Le conteneur d'envoi va s'appeler penvoyage (picockpit envoyé )

Pénétration des bâtiments

image

Le dossier penvoyage utilisé pour la construction contient

  • Dockerfile
  • envoy.yaml
  • example.crt (certificat)
  • example.key (clé pour le certificat)

Dockerfile

FROM envoyproxy/envoy:latest
COPIE envoy.yaml /etc/envoy/envoy.yaml
COPIE exemple.crt /etc/example-com.crt
COPY exemple.key /etc/example-com.key
#VOLUME /etc/envoy/envoy.yaml

EXPOSE 80/tcp
EXPOSE 443/tcp
#Educated devine que c'est TCP
EXPOSE 9901/tcp

LABEL version="0.2.0″ \
       description="penvoyage est un proxy d'envoi pour PiCockpit" ;)
       maintainer=""

Faites attention aux caractères ", WordPress pourrait les abîmer !

J'entrerai bientôt dans le fichier envoy.yaml de manière un peu plus détaillée. Il suffit de dire qu'il se trouve dans ce dossier et qu'il sera copié dans l'image du conteneur nouvellement créé.

Pour construire le conteneur, exécutez (à partir du répertoire contenant le répertoire penvoyage) :

docker build -t jasmine/penvoyage:0.2.0 -t jasmine/penvoyage:latest penvoyage

Votre sortie devrait se terminer par les lignes

Successfully tagged jasmine/penvoyage:0.2.0
Vous avez réussi à étiqueter jasmine/penvoyage:latest

Créer le réseau docker

docker network create -d bridge my-bridge-network

Nous utiliserons ce réseau pour attacher les deux conteneurs l'un à l'autre, afin qu'ils se voient mutuellement.

Les conteneurs peuvent communiquer entre eux en utilisant leurs noms de conteneurs, lorsqu'ils se trouvent sur le même réseau de conteneurs.

Par exemple, vous pouvez faire

ping taxgod

où taxgod est le nom du conteneur.

Pour ajouter un conteneur à un réseau après son exécution, procédez comme suit :

docker network connect my-bridge-network taxgod

Dans ce cas, my-bridge-network est le réseau, et taxgod est le conteneur qui doit y être connecté.

Pour voir comment un conteneur qui est exécuté est connecté à un réseau particulier, voir ci-dessous.

Pour voir quels conteneurs se trouvent sur un réseau Docker particulier, exécutez la commande suivante :

docker network inspect my-bridge-network

Exécuter l'image du conteneur penvoyage

docker run -rm -it -p 80:80 -p 443:443 -p 9901:9901 -network=my-bridge-network jasmine/penvoyage

Ce sera :

  • -rm retirer le conteneur après l'avoir éteint
  • -it attacher au conteneur (pour que vous puissiez voir la sortie de envoy)
  • -p 80:80 mappe le port 80 vers le port 80 à l'intérieur du conteneur (dans le fichier Docker, j'ai défini ce port comme étant le port tcp).
  • répétez pour le port 443 et le port 9901
  • attachez le conteneur à mon réseau de ponts
  • construire le conteneur à partir de l'image jasmine/penvoyage:latest (:latest est implicite ici)

À quoi servira ce conteneur ?

Il va proxyer les connexions à l'hôte (dans mon cas sur l'IP 192.168.1.2) vers le conteneur taxgod, sur le port 3000.

Il agira comme un proxy https avec les exemples de certificats, et enverra les connexions au même conteneur taxgod, sur le port 3000.

envoy.yaml

Veuillez noter : yaml utilise les espaces pour la structure, il est fort probable que WordPress s'y prenne mal. Utilisez donc ceci comme une référence, plutôt qu'un copier-coller !


ressources_statiques :
   des auditeurs :
   - l'adresse :
       adresse_socle :
         adresse : 0.0.0.0
         valeur_du_port : 80
     chaînes de filtres :
     - filtres :
       - nom : envoy.http_connection_manager
         config :
           codec_type : auto
           stat_prefix : ingress_http
           route_config :
             nom : local_route
             virtual_hosts :
             - nom : local_service
               domaines : ["*"]
               routes :
               - match : { préfixe : "/" }
                 route : { cluster : target_taxgod }
           http_filters :
           - nom : envoy.router
   - l'adresse :
       adresse_socle :
         adresse : 0.0.0.0
         port_value : 443
     chaînes de filtres :
     - tls_context :
         common_tls_context :
           tls_certificats :
           - certificate_chain : { filename : "/etc/example-com.crt" }
             private_key : { filename : "/etc/example-com.key" }
       filtres :
       - nom : envoy.http_connection_manager
         config :
           stat_prefix : ingress_https
           route_config :
             virtual_hosts :
             - nom : default
               domaines : ["*"]
               routes :
               - match : { préfixe : "/" }
                 route : { cluster : target_taxgod }
           http_filters :
           - nom : envoy.router
   clusters :
   - nom : target_taxgod
     connect_timeout : 0.25s
     type : strict_dns
     lb_policy : round_robin
     hôtes :
     - adresse_socle :
         adresse : taxgod
         valeur_du_port : 3000
admin :
   access_log_path : "/tmp/envoy.log"
   l'adresse :
     adresse_socle :
       adresse : 0.0.0.0
       valeur_du_port : 9901


Brève explication du fichier yaml de l'envoyeur :

Il y a deux sections principales, static_resources et admin.

admin est pour l'administration d'envoy et en dehors de la portée de cet article. Dans un environnement de production, vous devrez probablement le sécuriser de manière appropriée. NE COPIEZ PAS ET COLLEZ CETTE PARTIE ! !!

static_resources définit une configuration statique pour envoy (envoy peut également être configuré en utilisant son API).

dans les listeners, nous définissons les ports sur lesquels nous voulons écouter, et ce qui doit arriver aux connexions.

  • address - définit l'adresse et le port sur lesquels écouter
    • envoy.http_connection_manager - gère les connexions http, lit les en-têtes, et ainsi de suite. c'est un filtre prédéfini
    • stat_prefix : définit un nom lisible par l'homme pour les logs / statistiques
    • domaines : ["*"] - correspond à tous les domaines
    • route : { cluster : target_taxgod } - routera le trafic vers notre cluster target_taxgod (correspondra à /, c'est-à-dire tout ce qui se trouve sur le site)

l'adresse et sa sous-configuration sont répétées deux fois, une pour le port 80, et une pour le port 443. Pour le port 443, nous ajoutons également le tls_context et le common_tls_context dans les filter_chains pour injecter les certificats.

Notez que c'est toujours gestionnaire de connexions http envoyées, PAS https_connection_manager pour le port 443.

dans les clusters, nous définissons les points d'extrémité auxquels nous voulons pouvoir nous connecter ou vers lesquels le trafic doit être acheminé.

  • le cluster a un nom
  • un délai de connexion
  • lb_policy - la politique d'équilibrage de la charge. Il n'y a qu'un seul hôte, il recevra donc tout le trafic (round_robin signifie que chaque hôte recevra le trafic à tour de rôle).
  • dans les hôtes, la socket_address est définie comme address taxgod - c'est le nom Docker du conteneur, et le port comme port_value 3000

Le port 3000 est le port interne du conteneur taxgod, ce n'est pas le port auquel vous le liez sur l'hôte externe !

J'espère que ce billet de blog aidera les personnes qui essaient de mettre en place une installation https:// dans envoy.

Messages d'erreur

image

Envoyée pas d'amont sain message d'erreur

le conteneur de l'envoyé n'est pas sur le même réseau Docker comme votre conteneur cible, puisqu'il ne peut pas le voir, il ne peut pas s'y connecter.

image

Envoyée erreur de connexion en amont ou déconnexion/réinitialisation avant les en-têtes erreur

Essayez de supprimer

http2_protocol_options : {}

de votre envoy.yaml

Ressources utiles