Come avviare Istio utilizzando Kubernetes in produzione. Parte 1

Che cos'è Istio? Это так называемый Service mesh, технология, которая добавляет уровень абстракции над сетью. Мы перехватываем весь или часть трафика в кластере и производим определенный набор операций с ним. Какой именно? Например, делаем умный роутинг, или реализуем подход circuit breaker, можем организовывать «canary deployment», частично переключая трафик на новую версию сервиса, а можем ограничивать внешние взаимодействия и контролировать все походы из кластера во внешнюю сеть. Есть возможность задавать policy правила для контроля походов между разными микросервисами. Наконец, мы можем получить всю карту взаимодействия по сети и сделать унифицированный сбор метрик полностью прозрачно для приложений.

Puoi leggere del meccanismo di funzionamento in documentazione ufficiale. 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.

Come avviare Istio utilizzando Kubernetes in produzione. Parte 1

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.

Come avviare Istio utilizzando Kubernetes in produzione. Parte 1

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 proxy server envoy. 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:

  1. Deployamo una nuova versione del servizio.
  2. 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.
  3. 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 TPROXY. 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. -i e -b su *. È possibile specificare porte specifiche da intercettare. Se si desidera non intercettare una determinata sottorete, è possibile indicarla tramite un flag. -x.
  4. 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. qui.

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.

Come avviare Istio utilizzando Kubernetes in produzione. Parte 1

In sintesi, il funzionamento di istio-telemetry è il seguente.

  1. Il servizio 1 invia una richiesta al servizio 2.
  2. All'uscita dal servizio 1, la richiesta viene incapsulata nel suo sidecar.
  3. Il sidecar envoy monitora il percorso della richiesta verso il servizio 2 e prepara le informazioni necessarie.
  4. Poi le invia a istio-telemetry tramite una richiesta Report.
  5. Istio-telemetry determina se inviare questo Report ai backend, a quali esattamente e quali dati devono essere inviati.
  6. 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 questa configurazione.

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. qui.

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. qui.

In caso di installazione multi-cluster, considerare le seguenti limitazioni:

  1. Il Pod CIDR e il Service CIDR devono essere unici per tutti i cluster e non devono sovrapporsi.
  2. Tutti i Pod CIDR devono essere accessibili da qualsiasi Pod CIDR tra i cluster.
  3. 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

Acquista hosting affidabile per siti web con protezione DDoS, server VPS VDS 🔥 Acquista hosting affidabile per siti web con protezione DDoS, server VPS VDS | ProHoster