Che cos'è ? Это так называемый Service mesh, технология, которая добавляет уровень абстракции над сетью. Мы перехватываем весь или часть трафика в кластере и производим определенный набор операций с ним. Какой именно? Например, делаем умный роутинг, или реализуем подход circuit breaker, можем организовывать «canary deployment», частично переключая трафик на новую версию сервиса, а можем ограничивать внешние взаимодействия и контролировать все походы из кластера во внешнюю сеть. Есть возможность задавать policy правила для контроля походов между разными микросервисами. Наконец, мы можем получить всю карту взаимодействия по сети и сделать унифицированный сбор метрик полностью прозрачно для приложений.
Puoi leggere del meccanismo di funzionamento in . Istio è davvero uno strumento potente che risolve molte esigenze e problemi. In questo articolo, vorrei rispondere alle domande principali che di solito sorgono all'inizio dell'utilizzo di Istio. Questo ti aiuterà a comprenderlo più rapidamente.

Principio di funzionamento
Istio è composto da due aree principali: control plane e data plane. Il control plane comprende i componenti principali che garantiscono il corretto funzionamento degli altri. Nella versione attuale (1.0), il control plane ha tre componenti principali: Pilot, Mixer, Citadel. Non ci soffermeremo su Citadel, che serve per generare certificati per garantire il funzionamento di mutual TLS tra i servizi. Esaminiamo più nel dettaglio la struttura e la funzione di Pilot e Mixer.

Pilot è il componente di gestione principale che distribuisce tutte le informazioni sui servizi nel nostro cluster, i loro endpoint e le regole di routing (ad esempio, regole per il Canary deployment o le regole del circuit breaker).
Mixer è un componente facoltativo del control plane che fornisce la possibilità di raccogliere metriche, log e qualsiasi informazione sulle interazioni di rete. Inoltre, monitora il rispetto delle policy e dei limiti di frequenza.
Il data plane viene implementato tramite contenitori sidecar proxy. Di default, utilizza un potente . Può essere sostituito con un'altra implementazione, come nginx (nginmesh).
Per rendere Istio completamente trasparente per le applicazioni, esiste un sistema di inject automatico. L'ultima implementazione è adatta per le versioni di Kubernetes 1.9+ (mutational admission webhook). Per le versioni 1.7 e 1.8 di Kubernetes, è possibile utilizzare Initializer.
I contenitori sidecar si connettono a Pilot tramite il protocollo GRPC, che consente di ottimizzare il modello di push delle modifiche nel cluster. GRPC è stato introdotto in Envoy a partire dalla versione 1.6, e in Istio è utilizzato dalla versione 0.8 ed è rappresentato dal pilot-agent, un wrapper in golang sopra envoy, che configura i parametri di avvio.
Pilot e Mixer sono componenti completamente stateless, mantenendo tutto lo stato in memoria. La configurazione per loro è definita come Kubernetes Custom Resources, che vengono salvate in etcd.
Istio-agent riceve l'indirizzo di Pilot e apre uno stream GRPC verso di esso.
Come ho già detto, Istio implementa tutte le funzionalità in modo completamente trasparente per le applicazioni. Vediamo come. L'algoritmo è il seguente:
- Deployamo una nuova versione del servizio.
- A seconda dell'approccio di iniezione, il contenitore sidecar viene aggiunto con il contenitore istio-init e il contenitore istio-agent (envoy) durante l'applicazione della configurazione, oppure possono già essere stati manualmente inseriti nella descrizione dell'entity Pod di Kubernetes.
- Il contenitore istio-init è uno script che applica le regole iptables per il pod. Ci sono due varianti per configurare l'instradamento del traffico verso il contenitore istio-agent: utilizzare regole di redirect iptables, oppure . Al momento della scrittura dell'articolo, viene utilizzato per default l'approccio con le regole di redirect. In istio-init è possibile configurare quale traffico deve essere intercettato e inviato a istio-agent. Ad esempio, per intercettare tutto il traffico in entrata e in uscita, è necessario impostare i parametri.
-ie-bsu*. È possibile specificare porte specifiche da intercettare. Se si desidera non intercettare una determinata sottorete, è possibile indicarla tramite un flag.-x. - Dopo l'esecuzione dei contenitori init, vengono avviati quelli principali, incluso pilot-agent (envoy). Questo si connette a Pilot già distribuito tramite GRPC e riceve informazioni su tutti i servizi esistenti e le politiche di routing nel cluster. Sulla base delle informazioni ricevute, configura i cluster e specifica gli endpoint delle nostre applicazioni nel cluster Kubernetes. È importante notare che envoy configura dinamicamente gli listeners (coppie IP, porta) che inizia a monitorare. Pertanto, quando le richieste entrano nel pod, vengono reindirizzate tramite le regole di redirect iptables nel sidecar, e envoy è già in grado di gestire queste connessioni e capire dove deve inoltrare il traffico. In questa fase avviene anche l'invio delle informazioni a Mixer, che vedremo dopo, e l'invio di span di tracciamento.
Il risultato è una rete di proxy server envoy, che possiamo configurare da un unico punto (Pilot). Tutte le richieste in entrata e in uscita passano attraverso envoy. Tuttavia, solo il traffico TCP viene intercettato. Questo significa che l'IP del servizio Kubernetes viene risolto tramite kube-dns in UDP senza modifiche. Solo dopo la risoluzione avviene l'intercettazione della richiesta in uscita e la sua elaborazione da parte di envoy, che decide a quale endpoint deve essere inviata la richiesta (o non inviata, nel caso di politiche di accesso o attivazione dell'algoritmo del circuit breaker).
Ora che abbiamo chiarito Pilot, dobbiamo capire come funziona Mixer e a cosa serve. Puoi leggere la documentazione ufficiale su di esso. .
Il Mixer, nella sua forma attuale, è composto da due componenti: istio-telemetry e istio-policy (fino alla versione 0.8 era un unico componente, istio-mixer). Entrambi rappresentano il mixer, ognuno responsabile per il proprio compito. Istio telemetry riceve informazioni sui Report dai contenitori sidecar tramite GRPC riguardo a chi si sta connettendo e con quali parametri. Istio-policy gestisce le richieste di Check per verificare il rispetto delle regole Policy. I controlli delle Policy non vengono effettuati per ogni richiesta, ma sono memorizzati nella cache lato client (nel sidecar) per un certo periodo. I Report vengono inviati come richieste batch. Vedremo più tardi come configurarlo e quali parametri inviare esattamente.
Il Mixer è progettato come un componente ad alta disponibilità, che garantisce un funzionamento continuo nella raccolta e nell'elaborazione dei dati di telemetry. Il sistema si configura quindi come un buffer multilivello. Inizialmente, i dati vengono memorizzati sul lato dei contenitori sidecar, poi sul lato del mixer e infine inviati ai cosiddetti mixer backend. Di conseguenza, se uno dei componenti del sistema fallisce, il buffer cresce e, dopo il ripristino del sistema, viene svuotato. I mixer backend rappresentano i punti finali per l'invio dei dati di telemetria: statsd, newrelic, ecc. È possibile scrivere il proprio backend, è abbastanza semplice, e vedremo come farlo.

In sintesi, il funzionamento di istio-telemetry è il seguente.
- Il servizio 1 invia una richiesta al servizio 2.
- All'uscita dal servizio 1, la richiesta viene incapsulata nel suo sidecar.
- Il sidecar envoy monitora il percorso della richiesta verso il servizio 2 e prepara le informazioni necessarie.
- Poi le invia a istio-telemetry tramite una richiesta Report.
- Istio-telemetry determina se inviare questo Report ai backend, a quali esattamente e quali dati devono essere inviati.
- Istio-telemetry invia i dati di Report al backend se necessario.
Ora vediamo come implementare un sistema Istio composto solo dai componenti principali (Pilot e sidecar envoy).
Per iniziare, diamo un'occhiata alla configurazione principale (mesh) che legge Pilot:
apiVersion: v1
kind: ConfigMap
metadata:
name: istio
namespace: istio-system
labels:
app: istio
service: istio
data:
mesh: |-
# non abilitiamo ancora l'invio delle informazioni di tracing (pilot configurerà gli envoy in modo che l'invio non avvenga)
enableTracing: false
# non specifichiamo ancora gli endpoint del mixer, per evitare che i contenitori sidecar inviino informazioni lì
#mixerCheckServer: istio-policy.istio-system:15004
#mixerReportServer: istio-telemetry.istio-system:15004
# impostiamo l'intervallo di tempo per il quale l'envoy interrogherà nuovamente il Pilot (questo è per la vecchia versione dell'envoy proxy)
rdsRefreshDelay: 5s
# configurazione predefinita per l'envoy sidecar
defaultConfig:
# simile a rdsRefreshDelay
discoveryRefreshDelay: 5s
# lasciamo il percorso di configurazione e l'eseguibile envoy per il modo predefinito
configPath: "/etc/istio/proxy"
binaryPath: "/usr/local/bin/envoy"
# nome predefinito del container sidecar avviato (utilizzato, ad esempio, nei nomi dei servizi durante l'invio di tracing span)
serviceCluster: istio-proxy
# tempo che l'envoy attenderà prima di terminare forzatamente tutte le connessioni stabilite
drainDuration: 45s
parentShutdownDuration: 1m0s
# sono utilizzate di default le regole REDIRECT di iptables. Puoi cambiarle in TPROXY.
#interceptionMode: REDIRECT
# Porta su cui verrà avviata la pannello di amministrazione di ciascun container sidecar (envoy)
proxyAdminPort: 15000
# indirizzo a cui verranno inviati i trace secondo il protocollo zipkin (all'inizio abbiamo disabilitato l'invio stesso, quindi questo campo non verrà utilizzato attualmente)
zipkinAddress: tracing-collector.tracing:9411
# indirizzo statsd per inviare metriche dai contenitori envoy (disabilitato)
# statsdUdpAddress: aggregator:8126
# disabilitiamo il supporto per l'opzione Mutual TLS
controlPlaneAuthPolicy: NONE
# indirizzo su cui istio-pilot ascolterà per comunicare informazioni sulla scoperta di servizi a tutti i contenitori sidecar
discoveryAddress: istio-pilot.istio-system:15007
Tutti i componenti principali di controllo (control plane) saranno collocati nel namespace istio-system in Kubernetes.
Minimamente dobbiamo implementare solo Pilot. Per fare ciò, utilizzeremo
E configureremo manualmente l'iniezione del container sidecar.
Inizializzazione del container:
initContainers:
- name: istio-init
args:
- -p
- "15001"
- -u
- "1337"
- -m
- REDIRECT
- -i
- '*'
- -b
- '*'
- -d
- ""
image: istio/proxy_init:1.0.0
imagePullPolicy: IfNotPresent
resources:
limits:
memory: 128Mi
securityContext:
capabilities:
add:
- NET_ADMIN
E sidecar:
name: istio-proxy
args:
- "bash"
- "-c"
- |
exec /usr/local/bin/pilot-agent proxy sidecar
--configPath
/etc/istio/proxy
--binaryPath
/usr/local/bin/envoy
--serviceCluster
service-name
--drainDuration
45s
--parentShutdownDuration
1m0s
--discoveryAddress
istio-pilot.istio-system:15007
--discoveryRefreshDelay
1s
--connectTimeout
10s
--proxyAdminPort
"15000"
--controlPlaneAuthPolicy
NONE
env:
- name: POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
- name: POD_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
- name: INSTANCE_IP
valueFrom:
fieldRef:
fieldPath: status.podIP
- name: ISTIO_META_POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
- name: ISTIO_META_INTERCEPTION_MODE
value: REDIRECT
image: istio/proxyv2:1.0.0
imagePullPolicy: IfNotPresent
resources:
requests:
cpu: 100m
memory: 128Mi
limits:
memory: 2048Mi
securityContext:
privileged: false
readOnlyRootFilesystem: true
runAsUser: 1337
volumeMounts:
- mountPath: /etc/istio/proxy
name: istio-envoy
Per avviare tutto con successo, è necessario creare un ServiceAccount, ClusterRole, ClusterRoleBinding, CRD per Pilot, le cui descrizioni possono essere trovate. .
Di conseguenza, il servizio in cui iniettiamo il sidecar con envoy deve avviarsi con successo, ricevere tutte le informazioni di discovery dal pilota e gestire le richieste.
È importante comprendere che tutti i componenti del control plane sono applicazioni stateless e possono essere facilmente scalati orizzontalmente. Tutti i dati sono archiviati in etcd sotto forma di risorse personalizzate di Kubernetes.
Istio offre anche (per ora in modo sperimentale) la possibilità di eseguire al di fuori del cluster e di visualizzare e condividere la service discovery tra più cluster di Kubernetes. Maggiori dettagli possono essere letti. .
In caso di installazione multi-cluster, considerare le seguenti limitazioni:
- Il Pod CIDR e il Service CIDR devono essere unici per tutti i cluster e non devono sovrapporsi.
- Tutti i Pod CIDR devono essere accessibili da qualsiasi Pod CIDR tra i cluster.
- Tutti i server API di Kubernetes devono essere accessibili l'uno all'altro.
Queste sono informazioni preliminari che ti aiuteranno a iniziare a lavorare con Istio. Tuttavia, ci sono ancora molte insidie. Ad esempio, particolarità del routing del traffico esterno (verso l'esterno del cluster), approcci al debug dei sidecar, profiling, configurazione del mixer e scrittura di un mixer backend personalizzato, configurazione del meccanismo di tracing e il suo funzionamento attraverso envoy.
Tutto questo sarà trattato nei prossimi articoli. Fai le tue domande, cercherò di affrontarle.
Fonte: habr.com
