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
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.yamlEsporre 80/tcp
ESPORRE 443/tcp
1TP3Indovinate che questo è TCP
Esporre 9901/tcpETICHETTA 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
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.
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
- https://www.envoyproxy.io/docs/envoy/latest/intro/arch_overview/http_connection_management
- https://runnable.com/docker/basic-docker-networking
- https://docs.docker.com/engine/reference/commandline/network_create/
- https://docs.docker.com/v17.09/engine/userguide/networking/
- https://github.com/envoyproxy/envoy/tree/master/examples/front-proxy
- https://www.envoyproxy.io/docs/envoy/latest/intro/arch_overview/http_routing
- https://www.envoyproxy.io/docs/envoy/latest/configuration/http_conn_man/header_sanitizing
- https://www.envoyproxy.io/docs/envoy/latest/api-v2/api/v2/route/route.proto#envoy-api-field-route-routeaction-host-rewrite
- prefix_rewrite sembra interessante - permette di cambiare gli URL delle applicazioni in un percorso diverso da quello esposto al livello del reverse proxy
- https://www.envoyproxy.io/docs/envoy/latest/api-v2/config/filter/network/http_connection_manager/v2/http_connection_manager.proto#envoy-api-enum-config-filter-network-http-connection-manager-v2-httpconnectionmanager-codectype
- ci sono filtri integrati
- https://www.envoyproxy.io/docs/envoy/latest/configuration/http_filters/router_filter#config-http-filters-router
- "Il filtro router implementa l'inoltro HTTP. Sarà usato in quasi tutti gli scenari di proxy HTTP per i quali Envoy è distribuito".
- https://blog.turbinelabs.io/setting-up-ssl-with-envoy-f7c5aa06a5ce
- ha una sezione sul reindirizzamento del traffico insicuro
- https://www.envoyproxy.io/try/migrating-from-nginx-to-envoy
- utile anche come introduzione a Envoy
- https://www.envoyproxy.io/docs/envoy/latest/configuration/access_log#config-access-log-format-dictionaries