Calico za umrežavanje u Kubernetesu: uvod i malo iskustva
Svrha članka je upoznati čitatelja s osnovama umrežavanja i upravljanja mrežnim politikama u Kubernetesu, kao i sa Calico dodatkom treće strane koji proširuje standardne mogućnosti. Usput, jednostavnost konfiguracije i neke karakteristike će biti demonstrirane na stvarnim primjerima iz našeg radnog iskustva.
U kontekstu ovog članka, važno je napomenuti da sam K8s nije odgovoran za mrežnu povezanost između kontejnera i čvorova: za to se koriste različiti CNI dodaci (Interfejs za umrežavanje kontejnera). Više o ovom konceptu mi takođe su mi rekli.
Na primjer, najčešći od ovih dodataka je Flannel — pruža potpunu mrežnu povezanost između svih čvorova klastera podizanjem mostova na svakom čvoru, dodjeljujući mu podmrežu. Međutim, potpuna i neregulisana dostupnost nije uvijek korisna. Da bi se osigurala neka vrsta minimalne izolacije u klasteru, potrebno je intervenirati u konfiguraciji firewall-a. U opštem slučaju, stavljen je pod kontrolu istog CNI-ja, zbog čega se bilo kakve intervencije treće strane u iptables mogu pogrešno protumačiti ili potpuno zanemariti.
I „iz kutije“ za organizovanje upravljanja mrežnim politikama u Kubernetes klasteru je obezbeđeno NetworkPolicy API. Ovaj resurs, distribuiran preko odabranih imenskih prostora, može sadržavati pravila za razlikovanje pristupa od jedne aplikacije drugoj. Također vam omogućava da konfigurirate pristupačnost između određenih podova, okruženja (imenskih prostora) ili blokova IP adresa:
Ovo nije najprimitivniji primjer službena dokumentacija može jednom za svagda obeshrabriti želju da se razume logika načina na koji mrežne politike funkcionišu. Ipak, pokušaćemo da razumemo osnovne principe i metode obrade tokova saobraćaja pomoću mrežnih politika...
Logično je da postoje 2 vrste saobraćaja: ulazak u pod (Ingress) i odlazni iz njega (Egress).
Zapravo, politika je podijeljena u ove 2 kategorije na osnovu smjera kretanja.
Sljedeći potrebni atribut je selektor; onaj na koga se pravilo odnosi. Ovo može biti pod (ili grupa podova) ili okruženje (tj. imenski prostor). Važan detalj: oba tipa ovih objekata moraju sadržavati oznaku (etiketa u terminologiji Kubernetes) - to su oni kojima političari operišu.
Pored konačnog broja selektora ujedinjenih nekom vrstom oznake, moguće je pisati pravila poput „Dozvoli/zabrani sve/svako” u različitim varijantama. U tu svrhu koriste se konstrukcije oblika:
Vraćajući se na izbor CNI dodatka za klaster, vrijedi napomenuti da ne podržava svaki mrežni dodatak NetworkPolicy. Na primjer, već spomenuti Flannel ne zna kako da konfiguriše mrežne politike, što direktno je rečeno u zvaničnom repozitoriju. Pominje se i alternativa - projekat otvorenog koda Calico, što značajno proširuje standardni skup Kubernetes API-ja u smislu mrežnih politika.
Upoznavanje Calico: teorija
Dodatak Calico se može koristiti u integraciji sa Flannel (podprojekat kanal) ili nezavisno, pokrivajući i mrežno povezivanje i mogućnosti upravljanja dostupnošću.
Koje mogućnosti pruža korištenje K8s “boxed” rješenja i API seta iz Calico-a?
Evo šta je ugrađeno u NetworkPolicy:
političari su ograničeni okruženjem;
politike se primjenjuju na mahune označene etiketama;
pravila se mogu primijeniti na podove, okruženja ili podmreže;
pravila mogu sadržavati protokole, imenovane ili simboličke specifikacije portova.
Evo kako Calico proširuje ove funkcije:
politike se mogu primijeniti na bilo koji objekt: pod, kontejner, virtuelnu mašinu ili interfejs;
pravila mogu sadržavati određenu radnju (zabrana, dozvola, evidentiranje);
cilj ili izvor pravila može biti port, raspon portova, protokoli, HTTP ili ICMP atributi, IP ili podmreža (4. ili 6. generacija), bilo koji selektori (čvorovi, domaćini, okruženja);
Dodatno, možete regulirati prolaz saobraćaja koristeći DNAT postavke i politike prosljeđivanja prometa.
Prva urezivanja na GitHub-u u Calico repozitoriju datiraju iz jula 2016. godine, a godinu dana kasnije projekat je zauzeo vodeću poziciju u organizaciji Kubernetes mrežnog povezivanja - o tome svjedoče, na primjer, rezultati ankete, koju vodi The New Stack:
Mnoga velika upravljana rješenja sa K8s, kao što su Amazon EKS, Azure AKS, Google GKE a drugi su počeli da ga preporučuju za upotrebu.
Što se tiče performansi, ovdje je sve odlično. U testiranju svog proizvoda, razvojni tim Calico je pokazao astronomske performanse, pokrenuvši više od 50000 kontejnera na 500 fizičkih čvorova sa brzinom kreiranja od 20 kontejnera u sekundi. Nisu identifikovani problemi sa skaliranjem. Takvi rezultati najavljeni su već pri najavi prve verzije. Nezavisne studije koje se fokusiraju na propusnost i potrošnju resursa takođe potvrđuju da su performanse Calico-a gotovo jednako dobre kao i Flannel-ove. Na primjer:
Projekat se razvija veoma brzo, podržava rad u popularnim rešenjima upravljanim K8s, OpenShift, OpenStack, moguće je koristiti Calico prilikom postavljanja klastera koristeći kops, postoje reference na izgradnju servisnih mreža (Evo primera koristi se zajedno sa Istio).
Vježbajte sa Calico
U opštem slučaju korišćenja vanilla Kubernetesa, instaliranje CNI-ja se svodi na korišćenje fajla calico.yaml, preuzeto sa službene web stranice, s pomoću kubectl apply -f.
Po pravilu, trenutna verzija dodatka je kompatibilna sa najnovijim 2-3 verzije Kubernetesa: rad u starijim verzijama nije testiran i nije zagarantovan. Prema programerima, Calico radi na Linux kernelima iznad 3.10 i pokreće CentOS 7, Ubuntu 16 ili Debian 8, na vrhu iptablesa ili IPVS-a.
Izolacija u okruženju
Za opće razumijevanje, pogledajmo jednostavan slučaj kako bismo razumjeli kako se mrežne politike u Calico notaciji razlikuju od standardnih i kako pristup kreiranju pravila pojednostavljuje njihovu čitljivost i fleksibilnost konfiguracije:
U klasteru su raspoređene 2 web aplikacije: u Node.js i PHP, od kojih jedna koristi Redis. Da blokirate pristup Redis-u iz PHP-a, uz održavanje povezanosti sa Node.js, samo primijenite sljedeću politiku:
U suštini smo dozvolili dolazni saobraćaj ka Redis portu iz Node.js. I očito ništa drugo nisu zabranili. Čim se NetworkPolicy pojavi, svi selektori navedeni u njoj počinju da se izoluju, osim ako nije drugačije naznačeno. Međutim, pravila izolacije se ne primjenjuju na druge objekte koje selektor ne pokriva.
Primjer koristi apiVersion Kubernetes iz kutije, ali ništa vas ne sprečava da ga koristite istoimeni izvor iz isporuke Calico. Sintaksa je tamo detaljnija, tako da ćete morati ponovo napisati pravilo za gornji slučaj u sljedećem obliku:
Gore spomenute konstrukcije za dopuštanje ili odbijanje cjelokupnog prometa kroz regularni NetworkPolicy API sadrže konstrukcije sa zagradama koje je teško razumjeti i zapamtiti. U slučaju Calico, da biste promijenili logiku pravila zaštitnog zida na suprotnu, samo promijenite action: Allow na action: Deny.
Izolacija po okolini
Sada zamislite situaciju u kojoj aplikacija generiše poslovnu metriku za prikupljanje u Prometheusu i dalju analizu koristeći Grafanu. Otpremanje može sadržavati osjetljive podatke, koji su prema zadanim postavkama opet javno vidljivi. Sakrijmo ove podatke od znatiželjnih očiju:
Prometheus se, po pravilu, postavlja u zasebno uslužno okruženje - u primjeru će to biti prostor imena poput ovog:
polje metadata.labels ispostavilo se da ovo nije slučajno. Kao što je gore spomenuto, namespaceSelector (kao i podSelector) radi sa oznakama. Stoga, da biste omogućili preuzimanje metrike iz svih podova na određenom portu, morat ćete dodati neku vrstu oznake (ili uzeti iz postojećih), a zatim primijeniti konfiguraciju poput:
Općenito, dodavanjem ovakvih politika za specifične potrebe, možete se zaštititi od zlonamjernih ili slučajnih smetnji u radu aplikacija u klasteru.
Najbolja praksa, prema kreatorima Calico-a, je pristup „Blokiraj sve i eksplicitno otvori šta ti treba“, dokumentiran u službena dokumentacija (drugi slijede sličan pristup - posebno u već pomenuti članak).
Korištenje dodatnih Calico objekata
Dozvolite mi da vas podsjetim da kroz prošireni skup Calico API-ja možete regulirati dostupnost čvorova, ne ograničavajući se na podove. U sljedećem primjeru koristeći GlobalNetworkPolicy mogućnost prosljeđivanja ICMP zahtjeva u klasteru je zatvorena (na primjer, pingovi od modula do čvora, između podova ili od čvora do IP modula):
U gornjem slučaju, još uvijek je moguće da čvorovi klastera „dopru” jedan do drugog preko ICMP-a. I ovo pitanje se rješava sredstvima GlobalNetworkPolicy, primijenjen na entitet HostEndpoint:
Konačno, dat ću vrlo stvaran primjer korištenja Calico funkcija za slučaj interakcije skoro klastera, kada standardni skup politika nije dovoljan. Za pristup web aplikaciji, klijenti koriste VPN tunel, a ovaj pristup je strogo kontroliran i ograničen na određenu listu usluga dozvoljenih za korištenje:
Klijenti se povezuju na VPN preko standardnog UDP porta 1194 i, kada su povezani, primaju rute do podmreža klastera podova i usluga. Cijele podmreže se potiskuju kako ne bi izgubile usluge tokom restartovanja i promjene adrese.
Port u konfiguraciji je standardan, što nameće neke nijanse u procesu konfigurisanja aplikacije i prenosa u Kubernetes klaster. Na primjer, u istom AWS LoadBalancer za UDP pojavio se bukvalno krajem prošle godine na ograničenoj listi regija, a NodePort se ne može koristiti zbog njegovog prosljeđivanja na svim čvorovima klastera i nemoguće je skalirati broj serverskih instanci za u svrhu tolerancije grešaka. Osim toga, morat ćete promijeniti zadani raspon portova...
Kao rezultat pretraživanja mogućih rješenja, odabrano je sljedeće:
Podovi s VPN-om su zakazani po čvoru u hostNetwork, odnosno na stvarnu IP adresu.
Usluga je objavljena napolju kroz ClusterIP. Na čvoru je fizički instaliran port koji je dostupan izvana uz manje rezervacije (uslovno prisustvo prave IP adrese).
Utvrđivanje čvora na kojem se ruža mahuna nalazi izvan okvira naše priče. Reći ću samo da servis možete čvrsto "zakovati" za čvor ili napisati malu pomoćnu uslugu koja će pratiti trenutnu IP adresu VPN servisa i uređivati DNS zapise registrovane kod klijenata - ko ima dovoljno mašte.
Iz perspektive rutiranja, možemo jedinstveno identificirati VPN klijenta po njegovoj IP adresi koju izdaje VPN server. Ispod je primitivan primjer ograničavanja pristupa takvog klijenta uslugama, ilustrovan na gore spomenutom Redis-u:
Ovdje je strogo zabranjeno povezivanje s portom 6379, ali je u isto vrijeme očuvan rad DNS usluge, čije funkcioniranje često pati prilikom sastavljanja pravila. Jer, kao što je prethodno spomenuto, kada se pojavi selektor, na njega se primjenjuje standardna politika odbijanja osim ako nije drugačije navedeno.
Ishodi
Stoga, koristeći napredni API Calico, možete fleksibilno konfigurirati i dinamički mijenjati rutiranje unutar i oko klastera. Općenito, njegova upotreba može izgledati kao gađanje vrabaca iz topa, a implementacija L3 mreže sa BGP i IP-IP tunelima izgleda monstruozno u jednostavnoj Kubernetes instalaciji na ravnoj mreži... Međutim, inače alat izgleda prilično održiv i koristan .
Izolacija klastera radi ispunjavanja sigurnosnih zahtjeva možda nije uvijek izvodljiva, i tu Calico (ili slično rješenje) dolazi u pomoć. Primeri dati u ovom članku (sa manjim modifikacijama) koriste se u nekoliko instalacija naših klijenata u AWS.