Impostare envoy come front proxy su Docker con comunicazione ad altri container Docker

Ho già dei container esistenti che voglio usare envoy come proxy e gestore https davanti. Sto imparando a usare envoy e sto condividendo qui alcuni dei miei apprendimenti, poiché la documentazione è un po' confusa per iniziare.

Il mio contenitore già esistente si chiama "taxgod" - esegue un'applicazione Crystal sulla porta 3000 (http). Voglio fare il proxy alla porta 80 sull'host per http, e alla porta 443 per https.

Userò un certificato falso a scopo dimostrativo. La creazione del certificato è al di fuori dello scopo di questo articolo.

Il contenitore envoy sarà chiamato penvoyage (picockpit envoy )

Costruire penvoyage

immagine

La cartella penvoyage usata per la costruzione contiene

  • Dockerfile
  • envoy.yaml
  • example.crt (certificato)
  • example.key (chiave per il certificato)

Dockerfile

DA envoyproxy/envoy:latest
COPIA envoy.yaml /etc/envoy/envoy.yaml
COPIA example.crt /etc/example-com.crt
COPIA example.key /etc/example-com.key
#VOLUME /etc/envoy/envoy.yaml

Esporre 80/tcp
ESPORRE 443/tcp
1TP3Indovinate che questo è TCP
Esporre 9901/tcp

ETICHETTA versione="0.2.0″ \
       description="penvoyage è il proxy di envoy per PiCockpit" \
       maintainer=""

Fai attenzione ai caratteri ", WordPress potrebbe rovinarli!

Entrerò presto in envoy.yaml in modo più dettagliato. È sufficiente dire che si trova in questa cartella e sarà copiato nell'immagine del contenitore appena creato.

Per costruire il contenitore eseguire (dalla directory contenente la directory penvoyage):

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

Il vostro output dovrebbe terminare con le linee

Taggato con successo jasmine/penvoyage:0.2.0
Taggato con successo jasmine/penvoyage:latest

Creare la rete docker

docker network create -d bridge my-bridge-network

Useremo questa rete per collegare entrambi i contenitori l'uno all'altro, in modo che si vedano a vicenda.

I contenitori possono parlare tra loro usando i loro nomi di contenitori, quando sono sulla stessa rete di contenitori.

Per esempio si può fare

ping taxgod

dove taxgod è il nome del contenitore.

Per aggiungere un contenitore a una rete dopo che è stato eseguito, fare come segue:

docker network connect my-bridge-network taxgod

In questo caso my-bridge-network è la rete, e taxgod è il contenitore da collegare ad essa.

Per vedere come un contenitore che viene eseguito è collegato ad una particolare rete, vedi sotto.

Per vedere quali contenitori sono su una particolare rete Docker, eseguite il seguente comando:

docker network inspect my-bridge-network

Eseguire l'immagine del contenitore penvoyage

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

Questo lo farà:

  • -rimuovere il contenitore dopo lo spegnimento
  • -it attach to the container (così si può vedere l'output di envoy)
  • -p 80:80 mappa la porta 80 alla porta 80 all'interno del contenitore (nel file Docker ho definito che questa è la porta tcp)
  • ripetere per la porta 443 e la porta 9901
  • collegare il contenitore a my-bridge-network
  • costruire il contenitore dall'immagine jasmine/penvoyage:latest (:latest è implicito qui)

Cosa farà questo contenitore?

Proxy delle connessioni verso l'host (nel mio caso su IP 192.168.1.2) al contenitore taxgod, sulla porta 3000.

Agirà come un proxy https con i certificati di esempio, e farà il proxy delle connessioni allo stesso contenitore taxgod, sulla porta 3000.

envoy.yaml

Nota bene: yaml usa gli spazi bianchi per la struttura, molto probabilmente WordPress lo rovinerà. Quindi usa questo come riferimento, piuttosto che un copia e incolla!


risorse statiche:
   ascoltatori:
   - indirizzo:
       indirizzo_presa:
         indirizzo: 0.0.0.0
         valore della porta: 80
     catene_di_filtri:
     - filtri:
       - nome: envoy.http_connection_manager
         config:
           tipo di codec: auto
           prefisso statico: ingress_http
           route_config:
             nome: local_route
             virtual_hosts:
             - nome: local_service
               domini: ["*"]
               percorsi:
               - match: { prefix: "/" }
                 route: { cluster: target_taxgod }
           http_filters:
           - nome: envoy.router
   - indirizzo:
       indirizzo_presa:
         indirizzo: 0.0.0.0
         valore_porta: 443
     catene_di_filtri:
     - tls_context:
         common_tls_context:
           tls_certificati:
           - certificate_chain: { filename: "/etc/example-com.crt" }
             private_key: { nome file: "/etc/example-com.key" }
       filtri:
       - nome: envoy.http_connection_manager
         config:
           prefisso statico: ingress_https
           route_config:
             virtual_hosts:
             - nome: default
               domini: ["*"]
               percorsi:
               - match: { prefix: "/" }
                 route: { cluster: target_taxgod }
           http_filters:
           - nome: envoy.router
   gruppi:
   - nome: target_taxgod
     connect_timeout: 0.25s
     tipo: strict_dns
     lb_policy: round_robin
     ospiti:
     - indirizzo_presa:
         indirizzo: taxgod
         valore_porta: 3000
admin:
   percorso_log_accesso: "/tmp/envoy.log"
   indirizzo:
     indirizzo_presa:
       indirizzo: 0.0.0.0
       valore_porta: 9901


Breve spiegazione del file yaml di envoy:

Ci sono due sezioni principali, static_resources e admin

admin è per l'amministrazione di envoy e fuori dallo scopo di questo articolo. In un ambiente di produzione avrete probabilmente bisogno di proteggerlo in modo appropriato. NON COPIATE E INCOLLATE QUELLA PARTE!!!

static_resources definisce una configurazione statica per envoy (envoy può anche essere impostato usando le sue API)

negli ascoltatori, definiamo su quali porte vogliamo ascoltare e cosa dovrebbe accadere alle connessioni.

  • indirizzo - definisce l'indirizzo e la porta su cui ascoltare
    • envoy.http_connection_manager - gestisce le connessioni http, legge le intestazioni e così via. è un filtro predefinito
    • stat_prefix: definisce un nome leggibile per i log/statistiche
    • domini: ["*"] - corrisponde a tutti i domini
    • route: { cluster: target_taxgod } - indirizzerà il traffico al nostro cluster target_taxgod (corrisponderà a /, cioè a tutto il sito)

l'indirizzo e la sua sottoconfigurazione sono ripetuti due volte, uno per la porta 80 e uno per la porta 443. Per la porta 443 aggiungiamo anche il tls_context e il common_tls_context nelle filter_chains per iniettare i certificati.

Si noti che è ancora envoy.http_connection_managerNON https_connection_manager per la porta 443.

nei cluster definiamo i nostri endpoint a cui vogliamo essere in grado di connetterci / proxy del traffico.

  • il cluster ha un nome
  • un timeout di connessione
  • lb_policy - la politica di bilanciamento del carico. C'è un solo host, quindi riceverà tutto il traffico (round_robin significa che ogni host riceverà il traffico a turno)
  • negli host, il socket_address è impostato come indirizzo taxgod - questo è il nome Docker del contenitore, e la porta come port_value 3000

La porta 3000 è la porta interna del contenitore taxgod, non è la porta a cui si lega sull'host esterno!

Spero che questo post del blog aiuti le persone che cercano di impostare una configurazione di https:// in envoy.

Messaggi di errore

immagine

Envoy nessun sano a monte messaggio di errore

il contenitore envoy non è sulla stessa rete Docker come contenitore di destinazione, poiché non può vederlo, non può connettersi ad esso.

immagine

Envoy errore di connessione a monte o disconnessione/ripristino prima delle intestazioni errore

Prova a rimuovere

http2_protocol_options: {}

dal tuo envoy.yaml

Risorse utili