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

Il principio di funzionamento
Istio è composto da due aree principali: il control plane e il data plane. Il control plane include 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 tratteremo Citadel, poiché è necessario per la generazione dei certificati per garantire il funzionamento del mutual TLS tra i servizi. Diamo un'occhiata più da vicino alla struttura e alla funzionalità di Pilot e Mixer.

Pilot è il principale componente di gestione, che distribuisce tutte le informazioni su ciò che abbiamo nel cluster: servizi, i loro endpoint e le regole di routing (ad esempio, regole per il Canary deployment o regole per il circuit breaker).
Mixer è un componente opzionale del control plane che offre la possibilità di raccogliere metriche, log e qualsiasi informazione sulle interazioni di rete. Inoltre, si occupa di monitorare il rispetto delle regole della Policy e dei limiti di rate.
Il data plane viene implementato tramite container sidecar proxy. Per impostazione predefinita, viene utilizzato un potente . Può essere sostituito con un'altra implementazione, come nginx (nginmesh).
Affinché Istio funzioni in modo 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 di Kubernetes 1.7 e 1.8, è possibile utilizzare l'Initializer.
I container sidecar si connettono a Pilot tramite il protocollo GRPC, che consente di ottimizzare il modello di push delle modifiche avvenute nel cluster. GRPC è stato utilizzato in Envoy a partire dalla versione 1.6, ed è utilizzato in Istio dalla versione 0.8, ed è rappresentato da pilot-agent - un wrapper su golang per 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 sotto forma di Kubernetes Custom Resources, che vengono salvate in etcd.
Istio-agent riceve l'indirizzo di Pilot e apre uno stream GRPC a esso.
Come ho già detto, Istio implementa tutta la funzionalità in modo completamente trasparente per le applicazioni. Vediamo come. L'algoritmo è il seguente:
- Deployiamo una nuova versione del servizio.
- A seconda dell'approccio di inserimento del contenitore sidecar, vengono aggiunti il contenitore istio-init e il contenitore istio-agent (envoy) durante l'applicazione della configurazione, oppure possono già essere stati inseriti manualmente nella descrizione dell'entità Pod di Kubernetes.
- Il contenitore istio-init è uno script che applica le regole iptables per il pod. Ci sono due opzioni per configurare l'incapsulamento del traffico nel contenitore istio-agent: utilizzare le regole di redirect di iptables oppure . Al momento della scrittura dell'articolo, per impostazione predefinita viene utilizzato l'approccio con le regole di redirect. Nel contenitore istio-init c'è la possibilità di configurare quale traffico deve essere intercettato e diretto all'istio-agent. Ad esempio, per intercettare tutto il traffico in entrata e in uscita, è necessario impostare i parametri
-ie-ba valore*. È possibile specificare porte specifiche che devono essere intercettate. Per non intercettare una determinata sottorete, è possibile indicarla con il flag-x. - Dopo l'esecuzione dei contenitori init, vengono avviati i contenitori principali, incluso pilot-agent (envoy). Si collega 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 definisce direttamente gli endpoint delle nostre applicazioni nel cluster Kubernetes. È importante notare un aspetto cruciale: envoy configura dinamicamente i listeners (coppie IP, porta) che inizia ad ascoltare. Pertanto, quando le richieste entrano nel pod, vengono reindirizzate tramite le regole di redirect iptables nel sidecar, envoy può già gestire con successo queste connessioni e comprendere dove deve indirizzare il traffico successivamente. In questa fase avviene anche l'invio di informazioni a Mixer, che esamineremo più avanti, e l'invio degli span di tracciamento.
Alla fine otteniamo una rete intera di server proxy envoy, che possiamo configurare da un'unica posizione (Pilot). Tutte le richieste in entrata e in uscita passano attraverso envoy. Inoltre, viene intercettato solo il traffico TCP. Ciò significa che l'IP del servizio Kubernetes viene risolto tramite kube-dns utilizzando UDP senza alcuna modifica. Solo dopo la risoluzione avviene l'intercettazione della richiesta in uscita e l'elaborazione da parte di envoy, che decide già a quale endpoint deve inviare la richiesta (o non inviare, nel caso di politiche di accesso o dell'attivazione dell'algoritmo del circuit breaker).
Abbiamo chiarito il funzionamento di Pilot, ora 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 un mixer, ciascuno dei quali è responsabile del proprio compito. Istio telemetry riceve via GRPC dai container sidecar informazioni su chi va dove e con quali parametri. Istio-policy riceve richieste di controllo per verificare la conformità alle regole della Policy. I controlli della Policy vengono eseguiti, ovviamente, non su ogni richiesta, ma vengono memorizzati nella cache sul client (nel sidecar) per un certo periodo di tempo. I report vengono inviati in batch. Vedremo più tardi come configurare e quali parametri inviare esattamente.
Il mixer è previsto come componente ad alta disponibilità, che garantisce un funzionamento continuo per la raccolta e l'elaborazione dei dati di telemetria. Risultando, alla fine, un buffer multi-level. I dati vengono inizialmente memorizzati nella cache lato container sidecar, poi lato 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, lo schema di lavoro con istio-telemetry è il seguente.
- Il servizio 1 invia una richiesta al servizio 2.
- All'uscita dal servizio 1, la richiesta viene incapsulata nel suo stesso sidecar.
- Il sidecar envoy monitora il transito della richiesta nel servizio 2 e prepara le informazioni necessarie.
- Successivamente, le invia a istio-telemetry tramite una richiesta di report.
- Istio-telemetry determina se è necessario inviare questo report ai backend, quali esattamente e quali dati devono essere inviati.
- Istio-telemetry invia i dati di report al backend se necessario.
Ora vediamo come distribuire in un sistema Istio composto solo dai componenti principali (Pilot e sidecar envoy).
Iniziamo a dare 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: |-
# per ora non abilitiamo l'invio delle informazioni di tracing (il pilot configurerà gli envoy in modo che l'invio non avvenga)
enableTracing: false
# per ora non specifichiamo gli endpoint del mixer, affinché i contenitori sidecar non inviino informazioni lì
#mixerCheckServer: istio-policy.istio-system:15004
#mixerReportServer: istio-telemetry.istio-system:15004
# impostiamo un intervallo di tempo con cui l'envoy interrogherà nuovamente il Pilot (questo è per la vecchia versione del proxy envoy)
rdsRefreshDelay: 5s
# configurazione predefinita per il sidecar envoy
defaultConfig:
# similmente a rdsRefreshDelay
discoveryRefreshDelay: 5s
# lasciamo predefinito (percorso alla configurazione e binario envoy)
configPath: "/etc/istio/proxy"
binaryPath: "/usr/local/bin/envoy"
# nome predefinito del contenitore sidecar in esecuzione (usato, ad esempio, nei nomi dei servizi quando si inviano tracing span)
serviceCluster: istio-proxy
# tempo che l'envoy attenderà prima di terminare forzatamente tutte le connessioni stabilite
drainDuration: 45s
parentShutdownDuration: 1m0s
# per impostazione predefinita vengono utilizzate le regole di REDIRECT iptables. Può essere modificato in TPROXY.
#interceptionMode: REDIRECT
# Porta su cui verrà avviata la pannello di amministrazione di ogni contenitore sidecar (envoy)
proxyAdminPort: 15000
# indirizzo a cui saranno inviati i trace secondo il protocollo zipkin (inizialmente abbiamo disabilitato l'invio stesso, quindi questo campo non verrà utilizzato ora)
zipkinAddress: tracing-collector.tracing:9411
# indirizzo statsd per inviare metriche dei 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 discovery del servizio a tutti i contenitori sidecar
discoveryAddress: istio-pilot.istio-system:15007
Tutti i principali componenti di gestione (control plane) saranno collocati nel namespace istio-system in Kubernetes.
Minimamente dobbiamo distribuire solo il Pilot. Per questo utilizzeremo
E configureremo manualmente l'iniezione del contenitore sidecar.
Contenitore di inizializzazione:
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 far funzionare tutto correttamente, è necessario creare un ServiceAccount, un ClusterRole, un ClusterRoleBinding e una CRD per Pilot, le cui descrizioni possono essere trovate .
Di conseguenza, il servizio in cui iniettiamo il sidecar con envoy deve avviarsi correttamente, ricevere tutte le informazioni di discovery dal pilota e gestire le richieste.
È importante capire che tutti i componenti del control plane sono applicazioni stateless e possono essere scalati orizzontalmente senza problemi. Tutti i dati sono memorizzati in etcd sotto forma di descrizioni personalizzate delle risorse Kubernetes.
Inoltre, Istio (finora in modo sperimentale) offre la possibilità di essere eseguito al di fuori del cluster e di visualizzare e condividere la service discovery tra più cluster Kubernetes. Maggiori informazioni sono disponibili .
In un'installazione multicluster si devono 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 Kubernetes devono essere accessibili l'uno all'altro.
Queste sono informazioni iniziali che ti aiuteranno ad avvicinarti al lavoro con Istio. Tuttavia, ci sono ancora molte insidie. Ad esempio, le peculiarità del routing del traffico esterno (fuori dal cluster), approcci per il debugging dei sidecar, profiling, configurazione del mixer e scrittura di un backend mixer personalizzato, configurazione del meccanismo di tracing e il suo funzionamento tramite envoy.
Esamineremo tutto questo nei prossimi articoli. Inviate le vostre domande, cercherò di rispondere.
Fonte: habr.com
