Nota traducătorului.: acest articol, scris de un inginer SRE de la LinkedIn, detaliază „magia internă” din Kubernetes — mai precis, interacțiunea dintre CRI, CNI și kube-apiserver, — ceea ce se întâmplă atunci când unui pod îi este necesar un IP.
Una dintre cerințele de bază este că fiecare pod trebuie să aibă propriul său IP, iar orice alt pod din cluster trebuie să poată comunica cu el prin această adresă. Există numeroși „provideri” de rețea (Flannel, Calico, Canal etc.) care ajută la implementarea acestui model de rețea.
Când am început să lucrez cu Kubernetes, nu înțelegeam foarte bine cum obțin pod-urile IP-urile lor. Chiar și cu cunoștințele despre cum funcționează componentele individuale, era greu să-mi imaginez cum colaborează acestea. De exemplu, știam pentru ce sunt folosite pluginurile CNI, dar nu îmi imaginam cum sunt apelate. Așa că am decis să scriu acest articol pentru a împărtăși cunoștințele despre diferitele componente de rețea și modul în care colaborează în clusterul Kubernetes, care permit fiecărui pod să obțină un IP unic.
Există diverse moduri de a organiza interacțiunea de rețea în Kubernetes — similar cu diferitele opțiuni de runtime pentru containere. În această publicație va fi folosit pentru organizarea rețelei în cluster, iar ca mediu de execuție — . De asemenea, presupun că știți cum funcționează interacțiunea de rețea între containere, așa că voi menționa doar pe scurt, exclusiv pentru context.
Câteva concepte de bază
Containere și rețea: o scurtă prezentare
Există multe publicații excelente pe internet care explică modul în care containerele se leagă între ele prin rețea. Așa că voi oferi doar o prezentare generală a conceptelor de bază și mă voi limita la o abordare care presupune crearea unui pod Linux și encapsularea pachetelor. Detaliile sunt omise, deoarece tema interacțiunii rețelei containerelor merită un articol separat. Vor fi incluse linkuri către unele articole în special relevante și informative.
Containere pe același host
O metodă de organizare a comunicării prin adrese IP între containerele care funcționează pe același host presupune crearea unei punți Linux. Pentru aceasta, în Kubernetes (și Docker) se creează dispozitive virtuale . Un capăt al dispozitivului veth este conectat la spațiul de nume de rețea al containerului, iar celălalt la în rețeaua host-ului.
Toate containerele de pe un singur host au un capăt veth conectat la punte, prin care pot comunica între ele prin adrese IP. Puntea Linux are, de asemenea, o adresă IP și servește ca gateway pentru traficul de ieșire (egress) din pod-uri, destinat altor noduri.

Containere pe diferite host-uri
Încapsularea pachetelor este una dintre metodele prin care containerele de pe noduri diferite pot comunica între ele prin adrese IP. În Flannel, această capacitate este asigurată de tehnologia , care „învelește” pachetul inițial într-un pachet UDP și apoi îl trimite la destinație.
În clusterul Kubernetes, Flannel creează un dispozitiv vxlan și completează corespunzător tabelul de rutare pe fiecare dintre noduri. Fiecare pachet destinat unui container de pe un alt host trece prin dispozitivul vxlan și este încapsulat într-un pachet UDP. La destinație, pachetul înfășurat este extras și redirecționat către pod-ul corespunzător.

Notă: Aceasta este doar una dintre metodele de organizare a interacțiunii de rețea între containere.
Ce este CRI?
este un plugin care permite kubelet-ului să utilizeze diferite medii de execuție a containerelor. API-ul CRI este încorporat în diverse medii de execuție, astfel încât utilizatorii pot alege runtime-ul după cum doresc.
Ce este CNI?
reprezintă o soluție de rețea universală pentru containerele Linux. De asemenea, include , care răspund de diferite funcții în configurarea rețelei pod-ului. Pluginul CNI este un fișier executabil, conform specificației (unele pluginuri le vom discuta mai jos).
Alocarea subrețelelor nodurilor pentru atribuirile IP pod-urilor
Deoarece fiecare pod din cluster trebuie să aibă o adresă IP, este important să ne asigurăm că această adresă este unică. Acest lucru se realizează prin alocarea fiecărui nod a unei subrețele unice, din care apoi se atribuie adrese IP pod-urilor de pe acest nod.
Controlerul IPAM al nodului
Când nodeipam este transmis ca parametru al flag-ului --controllers , acesta alocă fiecărui nod o subnetă separată (podCIDR) din CIDR-ul cluster-ului (adică intervalul de adrese IP pentru rețeaua cluster-ului). Deoarece aceste podCIDR-uri nu se suprapun, devine posibil să se aloce fiecărui pod o adresă IP unică.
Unui nod Kubernetes îi este atribuit podCIDR-ul în momentul înregistrării sale inițiale în cluster. Pentru a modifica podCIDR-ul nodurilor, acestea trebuie deregistrate și apoi înregistrate din nou, în intervalul respectiv fiind necesare modificările corespunzătoare în configurația stratului de control Kubernetes. Se poate afișa podCIDR-ul unui nod folosind următoarea comandă:
$ kubectl get no -o json | jq '.spec.podCIDR'
10.244.0.0/24
Kubelet, mediu de execuție a containerelor și pluginuri CNI: cum funcționează toate acestea
Planificarea unui pod pe un nod implică efectuarea unei serii de acțiuni pregătitoare. În această secțiune, mă voi concentra doar asupra celor care sunt direct legate de configurarea rețelei pod-ului.
Planificarea unui pod pe un anumit nod declanșează următoarea succesiune de evenimente:

Informații utile: .
Interactiunea dintre mediul de execuție a containerelor și pluginurile CNI
Fiecare furnizor de rețea dispune de propriul plugin CNI. Runtime-ul containerului îl lansează pentru a configura rețeaua pentru pod în procesul de inițiere a acestuia. În cazul containerd, lansarea pluginului CNI este gestionată de pluginul .
Fiecare furnizor are propriul său agent. Acesta este instalat pe toate nodurile Kubernetes și se ocupă de configurarea rețelei pentru pod-uri. Acest agent vine fie împreună cu configurația CNI, fie îl creează singur pe nod. Configurația ajută pluginul CRI să știe ce plugin CNI să apeleze.
Locația configurației CNI poate fi configurată; implicit, aceasta se află în /etc/cni/net.d/<config-file>. Administratorii cluster-ului sunt, de asemenea, responsabili pentru instalarea pluginurilor CNI pe fiecare nod al cluster-ului. Locația acestora este de asemenea configurabilă; directorul implicit este /opt/cni/bin.
În cazul în care folosim containerd, căile pentru configurație și binarele pluginului pot fi specificate în secțiunea [plugins."io.containerd.grpc.v1.cri".cni] în .
Având în vedere că folosim Flannel ca furnizor de rețea, haideți să discutăm puțin despre configurarea sa:
- Flanneld (demonul Flannel) este de obicei instalat în cluster ca DaemonSet cu
install-cnica modul . Install-cnicreează (/etc/cni/net.d/10-flannel.conflist) pe fiecare nod.- Flanneld creează un dispozitiv vxlan, extrage metadatele de rețea de la API-ul serverului și monitorizează actualizările pod-urilor. Pe măsură ce acestea sunt create, el distribuie rutele pentru toate pod-urile din întregul cluster.
- Aceste rute permit pod-urilor să se conecteze între ele prin adrese IP.
Pentru informații mai detaliate despre modul de funcționare al Flannel, vă recomand să folosiți linkurile de la sfârșitul articolului.
Iată schema de interacțiune între pluginul Containerd CRI și pluginurile CNI:

După cum se poate observa mai sus, kubelet apelează pluginul Containerd CRI pentru a crea un pod, iar acesta apelează pluginul CNI pentru configurarea rețelei pod-ului. În acest proces, pluginul de rețea CNI apelează alte pluginuri CNI de bază pentru a configura diferite aspecte ale rețelei.
Interacțiunea dintre pluginurile CNI
Există diferite pluginuri CNI, ale căror sarcină este să ajute la configurarea interacțiunii de rețea între containere pe host. În acest articol, ne vom axa pe trei dintre ele.
Pluginul CNI Flannel
Atunci când se folosește Flannel ca furnizor de rețea, componenta Containerd CRI apelează , folosind fișierul de configurare CNI /etc/cni/net.d/10-flannel.conflist.
$ cat /etc/cni/net.d/10-flannel.conflist
{
"name": "cni0",
"plugins": [
{
"type": "flannel",
"delegate": {
"ipMasq": false,
"hairpinMode": true,
"isDefaultGateway": true
}
}
]
}
Pluginul CNI Flannel funcționează împreună cu Flanneld. În timpul inițializării, Flanneld extrage podCIDR și alte detalii legate de rețea din API-ul serverului și le salvează într-un fișier /run/flannel/subnet.env.
FLANNEL_NETWORK=10.244.0.0/16
FLANNEL_SUBNET=10.244.0.1/24
FLANNEL_MTU=1450
FLANNEL_IPMASQ=false
Pluginul CNI Flannel folosește datele din /run/flannel/subnet.env pentru a configura și apela pluginul CNI bridge.
Pluginul CNI Bridge
Acest plugin este apelat cu următoarea configurație:
{
"name": "cni0",
"type": "bridge",
"mtu": 1450,
"ipMasq": false,
"isGateway": true,
"ipam": {
"type": "host-local",
"subnet": "10.244.0.0/24"
}
}
La prima apelare, acesta creează un bridge Linux cu "name": "cni0", așa cum este specificat în configurare. Apoi, pentru fiecare pod se creează un pereche veth. Un capăt al acestuia se conectează la spațiul de nume de rețea al containerului, iar celălalt intră în bridge-ul Linux în rețeaua host-ului. leagă toate containerele host-ului la bridge-ul Linux din rețeaua host-ului.
După finalizarea configurării perechii veth, pluginul Bridge apelează pluginul IPAM local pentru host (host-local). Tipul pluginului IPAM poate fi configurat în fișierul CNI, pe care pluginul CRI îl folosește pentru a apela pluginul CNI Flannel.
Pluginurile IPAM locale pentru host CNI
Pluginul Bridge CNI apelează cu următoarea configurație:
{
"name": "cni0",
"ipam": {
"type": "host-local",
"subnet": "10.244.0.0/24",
"dataDir": "/var/lib/cni/networks"
}
}
Plugin IPAM de tipul host-local (IP Aadresă Mmanagement — gestionarea IP-urilor) returnează un IP pentru container din subrețea și păstrează IP-ul rezervat pe gazdă în directorul specificat în secțiunea dataDir — /var/lib/cni/networks/<network-name=cni0>/<ip>. Acest fișier conține ID-ul containerului la care i-a fost atribuit acest IP.
La apelarea pluginului IPAM host-local, acesta returnează următoarele date:
{
"ip4": {
"ip": "10.244.4.2",
"gateway": "10.244.4.3"
},
"dns": {}
}
Rezumat
Kube-controller-manager atribuie fiecărui nod un podCIDR. Podurile fiecărui nod primesc IP-uri din intervalul de adrese rezervat în podCIDR. Deoarece podCIDR-urile nodurilor nu se suprapun, toate podurile primesc IP-uri unice.
Administratorul clusterului Kubernetes configurează și instalează kubelet, mediul de execuție a containerelor, agentul furnizorului de rețea și copiază pluginurile CNI pe fiecare nod. În timpul pornirii, agentul furnizorului de rețea generează configurația CNI. Când un pod este planificat pe un nod, kubelet apelează pluginul CRI pentru a-l crea. Apoi, dacă se folosește containerd, pluginul Containerd CRI apelează pluginul CNI specificat în configurația CNI pentru a configura rețeaua podului. Drept urmare, podul primește un IP.
Mi-a luat ceva timp să înțeleg toate subtilitățile și nuanțele acestor interacțiuni. Sper că experiența obținută vă va ajuta și pe voi să înțelegeți mai bine cum funcționează Kubernetes. Dacă am greșit în vreun fel, vă rog să mă contactați la sau la adresa . Nu ezitați să mă contactați dacă doriți să discutăm despre aspectele acestei articole sau despre orice altceva. Mă bucur să discut cu voi!
Linkuri
Containere și rețea
Cum funcționează Flannel
CRI și CNI
P.S. de la traducător
Citiți și în blogul nostru:
- «»;
- „Ghidul ilustrat pentru configurarea rețelei în Kubernetes”: , ;
- «».
Sursa: habr.com
