Ce este ? Это так называемый Service mesh, технология, которая добавляет уровень абстракции над сетью. Мы перехватываем весь или часть трафика в кластере и производим определенный набор операций с ним. Какой именно? Например, делаем умный роутинг, или реализуем подход circuit breaker, можем организовывать «canary deployment», частично переключая трафик на новую версию сервиса, а можем ограничивать внешние взаимодействия и контролировать все походы из кластера во внешнюю сеть. Есть возможность задавать policy правила для контроля походов между разными микросервисами. Наконец, мы можем получить всю карту взаимодействия по сети и сделать унифицированный сбор метрик полностью прозрачно для приложений.
Puteți citi despre mecanismul de funcționare în . Istio este, într-adevăr, un instrument puternic care permite rezolvarea multor sarcini și probleme. În acest articol, aș dori să răspund la întrebările principale care apar de obicei la începutul lucrului cu Istio. Acest lucru vă va ajuta să vă familiarizați mai repede cu el.

Principiul de funcționare
Istio este compus din două zone principale - control plane și data plane. Control plane conține componentele principale care asigură funcționarea corectă a celorlalte. În versiunea curentă (1.0), control plane are trei componente principale: Pilot, Mixer, Citadel. Nu vom discuta despre Citadel, care este necesar pentru generarea certificatelor pentru a asigura funcționarea mutual TLS între servicii. Să ne uităm mai detaliat la structura și scopul lui Pilot și Mixer.

Pilot este componenta principală de control care răspândește informațiile despre ce avem în cluster - servicii, endpoint-uri și reguli de routing (de exemplu, reguli pentru Canary deployment sau reguli circuit breaker).
Mixer este o componentă opțională a control plane care oferă posibilitatea de a colecta metrici, jurnale și orice informație despre interacțiunile în rețea. De asemenea, monitorizează conformitatea regulilor Policy și respectarea limitelor de rată.
Data plane este implementat cu ajutorul containerelor sidecar proxy. În mod implicit, se folosește un puternic . Acesta poate fi înlocuit cu o altă implementare, de exemplu nginx (nginmesh).
Pentru ca Istio să funcționeze complet transparent pentru aplicații, există un sistem de injectare automată. Ultima realizare se potrivește cu versiunile Kubernetes 1.9+ (mutational admission webhook). Pentru versiunile Kubernetes 1.7, 1.8 există posibilitatea de a folosi Initializer.
Containerele sidecar se conectează la Pilot prin protocolul GRPC, care permite optimizarea modelului de push al modificărilor care au loc în cluster. GRPC a început să fie folosit în Envoy începând cu versiunea 1.6, iar în Istio este utilizat din versiunea 0.8 și este reprezentat de pilot-agent - un wrapper Golang peste envoy, care configurează parametrii de lansare.
Pilot și Mixer sunt componente complet stateless, toată starea fiind păstrată în memorie. Configurarea pentru acestea este definită sub formă de Kubernetes Custom Resources, care sunt salvate în etcd.
Istio-agent primește adresa Pilot și deschide un stream GRPC către acesta.
Așa cum am menționat, Istio implementează toată funcționalitatea complet transparent pentru aplicații. Să vedem cum. Algoritmul este următorul:
- Deploim o nouă versiune a serviciului.
- În funcție de abordarea injectării, containerul istio-init și containerul istio-agent (envoy) sunt adăugate în etapa de aplicare a configurației, sau pot fi deja inserate manual în descrierea entității Pod din Kubernetes.
- Containerul istio-init este un script care aplică regulile iptables pentru pod. Există două variante pentru configurarea îndoirii traficului în containerul istio-agent: utilizarea regulilor de redirect iptables, sau . La momentul redactării acestui articol, abordarea implicită folosită este cea cu reguli de redirect. În istio-init există opțiunea de a configura ce tip de trafic trebuie interceptat și direcționat către istio-agent. De exemplu, pentru a intercepta tot traficul de intrare și cel de ieșire, trebuie să setați parametrii
-iși-bto the value*. Pot fi specificate porturi anume care trebuie interceptate. Pentru a nu intercepta o anumită subrețea, aceasta poate fi specificată prin intermediul unui flag-x. - După executarea containerelor init, sunt lansate containerele principale, inclusiv pilot-agent (envoy). Acesta se conectează la Pilot-ul deja desfășurat prin GRPC și primește informații despre toate serviciile existente și politicile de routing din cluster. Pe baza datelor primite, acesta configurează cluster-urile și definește direct endpoint-urile aplicațiilor noastre din cluster-ul Kubernetes. De asemenea, este important de menționat un aspect crucial: envoy configurează dinamic listener-ele (perechi IP, port) pe care începe să le asculte. Prin urmare, atunci când solicitatri intră în pod, acestea sunt redirecționate prin regulile de redirect iptables către sidecar, iar envoy poate déjà să proceseze aceste conexiuni și să înțeleagă către ce trebuie să proxizeze ulterior traficul. Tot în această etapă se trimite informația către Mixer, pe care o vom analiza ulterior, și se transmit spans de tracing.
În final, obținem o rețea întreagă de servere proxy envoy, pe care le putem configura dintr-un singur punct (Pilot). Toate solicitările inbound și outbound trec prin envoy. În plus, doar traficul TCP este interceptat. Asta înseamnă că IP-ul serviciului Kubernetes este rezolvat prin kube-dns prin UDP fără a fi modificat. Apoi, după rezolvare, se face interceptarea solicitării de ieșire și procesarea de către envoy, care decide pe ce endpoint trebuie trimisă solicitarea (sau să nu fie trimisă, în cazul politicilor de acces sau activarea algoritmului circuit breaker).
Am înțeles cum funcționează Pilot, acum trebuie să înțelegem cum funcționează Mixer și de ce este acesta necesar. Puteți citi documentația oficială despre acesta. .
Mixer, în forma actuală, este compus din două componente: istio-telemetry și istio-policy (până la versiunea 0.8, era o singură componentă, istio-mixer). Ambele reprezintă un mixer, fiecare având propria responsabilitate. Istio telemetry primește informații despre cine merge unde și cu ce parametri prin intermediul GRPC de la containerele sidecar. Istio-policy primește cereri de verificare pentru a se asigura că se respectă regulile Policy. Verificările policy nu se efectuează pentru fiecare cerere, ci sunt stocate pe client (în sidecar) pentru o perioadă determinată. Cererile de raportare sunt trimise în loturi. Cum se configurează și ce parametrii trebuie trimiși, vom analiza puțin mai târziu.
Mixer este conceput ca un component cu disponibilitate înaltă, care asigură funcționarea neîntreruptă a colectării și procesării datelor de telemetrie. Sistemul rezultă, în final, ca un buffer multi-strat. Inițial, datele sunt bufferizate de partea containerelor sidecar, apoi de partea mixer-ului și, în cele din urmă, sunt trimise către așa-numitele backend-uri mixer. Așadar, dacă vreo componentă a sistemului cedează, buffer-ul crește, iar după restabilirea sistemului, se golește. Backend-urile mixer reprezintă punctele finale pentru trimiterea datelor de telemetrie: statsd, newrelic etc. Poți scrie propriul tău backend, este destul de simplu, iar noi vom vedea cum se face acest lucru.

În concluzie, schema de lucru cu istio-telemetry este următoarea.
- Serviciul 1 trimite o cerere către serviciul 2.
- La ieșirea din serviciul 1, cererea este înfășurată în sidecar-ul său.
- Sidecar-ul envoy urmărește cum decurge cererea către serviciul 2 și pregătește informațiile necesare.
- Apoi, acestea sunt trimise către istio-telemetry printr-o cerere de raport.
- Istio-telemetry determină dacă acest raport trebuie trimis către backend-uri, către care anume și ce date trebuie trimise.
- Istio-telemetry trimite datele de raport către backend, dacă este necesar.
Acum să vedem cum se desfășoară implementarea în sistemul Istio, constând doar din componentele de bază (Pilot și sidecar envoy).
Pentru început, să examinăm configurația principală (mesh) pe care o citește Pilot:
apiVersion: v1
kind: ConfigMap
metadata:
name: istio
namespace: istio-system
labels:
app: istio
service: istio
data:
mesh: |-
# momentan nu activăm trimiterea informațiilor de tracing (pilotul va configura envoy astfel încât trimiterea să nu aibă loc)
enableTracing: false
# deocamdată nu specificăm endpoint-urile mixer, astfel încât containerele sidecar să nu trimită informații către ele
#mixerCheckServer: istio-policy.istio-system:15004
#mixerReportServer: istio-telemetry.istio-system:15004
# stabilim un interval de timp cu care envoy va interoga Pilot (acesta este pentru vechea versiune a envoy proxy)
rdsRefreshDelay: 5s
# configurația implicită pentru envoy sidecar
defaultConfig:
# similar cu rdsRefreshDelay
discoveryRefreshDelay: 5s
# lăsăm la valorile implicite (calea către configurație și binarul envoy)
configPath: "\/etc\/istio\/proxy"
binaryPath: "\/usr\/local\/bin\/envoy"
# numele implicit al containerului sidecar pornit (utilizat, de exemplu, în numele serviciului la trimiterea span-urilor de tracing)
serviceCluster: istio-proxy
# timpul pe care îl va aștepta envoy înainte de a închide forțat toate conexiunile deschise
drainDuration: 45s
parentShutdownDuration: 1m0s
# în mod implicit se folosesc regulile REDIRECT iptables. Poate fi schimbat pe TPROXY.
#interceptionMode: REDIRECT
# Portul pe care va fi pornită panoul administrativ pentru fiecare container sidecar (envoy)
proxyAdminPort: 15000
# adresa la care vor fi trimise trace-urile prin protocolul zipkin (la început am dezactivat trimiterea în sine, deci acest câmp nu va fi folosit în prezent)
zipkinAddress: tracing-collector.tracing:9411
# adresa statsd pentru trimiterea metrilor containerelor envoy (dezactivată)
# statsdUdpAddress: aggregator:8126
# dezactivăm suportul pentru opțiunea Mutual TLS
controlPlaneAuthPolicy: NONE
# adresa pe care va asculta istio-pilot pentru a informa toate containerele sidecar despre descoperirea serviciilor
discoveryAddress: istio-pilot.istio-system:15007
Toate componentele principale de control (control plane) vor fi plasate în namespace-ul istio-system în Kubernetes.
Minim, trebuie să desfășurăm doar Pilot. Pentru aceasta vom folosi
Și vom configura manual injectarea containerului sidecar.
Containerul de inițializare:
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
Și sidecar-ul:
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
Pentru ca totul să funcționeze cu succes, trebuie să creați un ServiceAccount, ClusterRole, ClusterRoleBinding și CRD pentru Pilot, descrierile cărora pot fi găsite .
În cele din urmă, serviciul în care injectăm sidecar cu envoy trebuie să se lanceze cu succes, să primească toate informațiile de descoperire de la pilot și să proceseze cererile.
Este important să înțelegem că toate componentele control plane sunt aplicații stateless și pot fi scalate orizontal fără probleme. Toate datele sunt stocate în etcd sub formă de descrieri personalizate ale resurselor Kubernetes.
De asemenea, Istio (deocamdată experimental) are posibilitatea de a funcționa în afara cluster-ului și de a vizualiza și împărtăși descoperirea serviciului între mai multe clustere Kubernetes. Mai multe informații pot fi citite aici .
Când configurați o instalare multicluaster, trebuie să luați în considerare următoarele limitări:
- CIDR-ul Pod și CIDR-ul Serviciilor trebuie să fie unice în toate clusterele și nu trebuie să se suprapună.
- Toate CIDR-urile Pod trebuie să fie accesibile din orice CIDR Pod între clustere.
- Toate serverele API Kubernetes trebuie să fie accesibile între ele.
Acestea sunt informațiile inițiale care vă vor ajuta să începeți lucrul cu Istio. Cu toate acestea, există multe capcane. De exemplu, specificitățile rutării traficului extern (în afara cluster-ului), abordările pentru depanarea sidecar-urilor, profilarea, configurarea mixerului și scrierea unui backend mixer personalizat, configurarea mecanismului de trasare și modul său de funcționare cu envoy.
Toate acestea le vom analiza în publicațiile următoare. Adresați-vă întrebările dvs., voi încerca să le clarific.
Sursa: habr.com
