
Účelom článku je oboznámiť čitateľa so základmi sieťovania a správy sieťových politík v Kubernetes, ako aj s doplnkom Calico tretej strany, ktorý rozširuje štandardné možnosti. Jednoduchosť konfigurácie a niektoré funkcie budú demonštrované na skutočných príkladoch z našich prevádzkových skúseností.
Rýchly úvod do sieťového zariadenia Kubernetes
Klaster Kubernetes si nemožno predstaviť bez siete. O ich základoch sme už zverejnili materiály: “"A"".
V kontexte tohto článku je dôležité poznamenať, že samotný K8 nie je zodpovedný za sieťovú konektivitu medzi kontajnermi a uzlami: CNI pluginy (Container Networking Interface). Viac o tomto koncepte my .
Napríklad najbežnejším z týchto doplnkov je — poskytuje plnú sieťovú konektivitu medzi všetkými uzlami klastra zdvihnutím mostov na každom uzle a priradením podsiete. Úplná a neregulovaná dostupnosť však nie je vždy výhodná. Na zabezpečenie určitej minimálnej izolácie v klastri je potrebné zasiahnuť do konfigurácie firewallu. Vo všeobecnom prípade je pod kontrolou toho istého CNI, a preto môžu byť akékoľvek zásahy tretích strán do iptables interpretované nesprávne alebo môžu byť úplne ignorované.
A poskytuje sa „out of the box“ na organizovanie správy sieťových politík v klastri Kubernetes . Tento zdroj, distribuovaný cez vybrané menné priestory, môže obsahovať pravidlá na rozlíšenie prístupu z jednej aplikácie k druhej. Umožňuje vám tiež konfigurovať dostupnosť medzi konkrétnymi modulmi, prostrediami (priestormi názvov) alebo blokmi adries IP:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: test-network-policy
namespace: default
spec:
podSelector:
matchLabels:
role: db
policyTypes:
- Ingress
- Egress
ingress:
- from:
- ipBlock:
cidr: 172.17.0.0/16
except:
- 172.17.1.0/24
- namespaceSelector:
matchLabels:
project: myproject
- podSelector:
matchLabels:
role: frontend
ports:
- protocol: TCP
port: 6379
egress:
- to:
- ipBlock:
cidr: 10.0.0.0/24
ports:
- protocol: TCP
port: 5978Toto nie je najprimitívnejší príklad môže raz a navždy odradiť túžbu pochopiť logiku fungovania sieťových politík. Ešte sa však pokúsime pochopiť základné princípy a metódy spracovania dopravných tokov pomocou sieťových politík...
Je logické, že existujú 2 typy premávky: vstup do modulu (Ingress) a výstup z neho (Egress).

V skutočnosti je politika rozdelená do týchto 2 kategórií na základe smeru pohybu.
Ďalším povinným atribútom je selektor; ten, na koho sa pravidlo vzťahuje. Môže to byť modul (alebo skupina modulov) alebo prostredie (t. j. priestor názvov). Dôležitý detail: oba typy týchto objektov musia obsahovať označenie (štítok v terminológii Kubernetes) – s tými politici operujú.
Okrem konečného počtu selektorov spojených nejakým štítkom je možné napísať pravidlá ako „Povoliť/zakázať všetko/všetkým“ v rôznych variáciách. Na tento účel sa používajú konštrukcie formulára:
podSelector: {}
ingress: []
policyTypes:
- Ingress— v tomto príklade sú všetky moduly v prostredí blokované pred prichádzajúcou premávkou. Opačné správanie je možné dosiahnuť pomocou nasledujúcej konštrukcie:
podSelector: {}
ingress:
- {}
policyTypes:
- IngressPodobne pre odchádzajúce:
podSelector: {}
policyTypes:
- Egress- vypnúť. A tu je to, čo treba zahrnúť:
podSelector: {}
egress:
- {}
policyTypes:
- EgressKeď sa vrátime k výberu doplnku CNI pre klaster, stojí za zmienku nie každý sieťový doplnok podporuje NetworkPolicy. Napríklad už spomínaný Flannel nevie konfigurovať sieťové politiky, ktoré v oficiálnom úložisku. Spomína sa tam aj alternatíva – Open Source projekt , ktorý výrazne rozširuje štandardnú sadu Kubernetes API z hľadiska sieťových politík.

Spoznávanie Calico: teória
Doplnok Calico je možné použiť v integrácii s Flannel (podprojekt ) alebo nezávisle, pokrývajú možnosti sieťového pripojenia a správy dostupnosti.
Aké príležitosti poskytuje používanie „krabicového“ riešenia K8 a sady API od Calico?
Tu je to, čo je zabudované do NetworkPolicy:
- politici sú limitovaní prostredím;
- pravidlá sa aplikujú na pody označené štítkami;
- pravidlá možno aplikovať na moduly, prostredia alebo podsiete;
- pravidlá môžu obsahovať protokoly, pomenované alebo symbolické špecifikácie portov.
Tu je návod, ako Calico rozširuje tieto funkcie:
- politiky možno aplikovať na akýkoľvek objekt: pod, kontajner, virtuálny stroj alebo rozhranie;
- pravidlá môžu obsahovať konkrétnu akciu (zákaz, povolenie, protokolovanie);
- cieľom alebo zdrojom pravidiel môže byť port, rozsah portov, protokolov, atribútov HTTP alebo ICMP, IP alebo podsieť (4. alebo 6. generácia), ľubovoľné selektory (uzly, hostitelia, prostredia);
- Okrem toho môžete regulovať prechod návštevnosti pomocou nastavení DNAT a pravidiel presmerovania návštevnosti.
Prvé commity na GitHub v repozitári Calico sa datujú do júla 2016 a o rok neskôr projekt zaujal vedúcu pozíciu v organizácii sieťovej konektivity Kubernetes – svedčia o tom napríklad výsledky prieskumu, :

Mnoho veľkých riadených riešení s K8, ako napr , , a iní ho začali odporúčať na použitie.
Čo sa týka výkonu, tu je všetko skvelé. Pri testovaní svojho produktu preukázal vývojový tím Calico astronomický výkon, keď spustil viac ako 50000 500 kontajnerov na 20 fyzických uzloch s rýchlosťou vytvárania XNUMX kontajnerov za sekundu. Neboli zistené žiadne problémy s mierkou. Takéto výsledky už pri ohlásení prvej verzie. Nezávislé štúdie zamerané na priepustnosť a spotrebu zdrojov tiež potvrdzujú, že výkon Calico je takmer taký dobrý ako výkon Flannel. :

Projekt sa vyvíja veľmi rýchlo, podporuje prácu v populárnych riešeniach spravovaných K8s, OpenShift, OpenStack, je možné použiť Calico pri nasadzovaní klastra pomocou , existujú odkazy na výstavbu sietí Service Mesh ( používané v spojení s Istio).
Cvičte s Calico
Vo všeobecnom prípade použitia vanilla Kubernetes inštalácia CNI spočíva v použití súboru calico.yaml, , s помощью kubectl apply -f.
Aktuálna verzia pluginu je zvyčajne kompatibilná s poslednými dvoma alebo tromi verziami Kubernetes; kompatibilita so staršími verziami nie je testovaná ani zaručená. Podľa vývojárov Calico beží na jadre. Linux nad 3.10 pod kontrolou CentOS 7, Ubuntu 16 alebo Debian 8, cez iptables alebo IPVS.
Izolácia v prostredí
Pre všeobecné pochopenie sa pozrime na jednoduchý prípad, aby sme pochopili, ako sa sieťové politiky v zápise Calico líšia od štandardných a ako prístup k vytváraniu pravidiel zjednodušuje ich čitateľnosť a flexibilitu konfigurácie:

V klastri sú nasadené 2 webové aplikácie: v Node.js a PHP, z ktorých jedna používa Redis. Ak chcete zablokovať prístup k Redis z PHP a zároveň zachovať konektivitu s Node.js, stačí použiť nasledujúcu politiku:
kind: NetworkPolicy
apiVersion: networking.k8s.io/v1
metadata:
name: allow-redis-nodejs
spec:
podSelector:
matchLabels:
service: redis
ingress:
- from:
- podSelector:
matchLabels:
service: nodejs
ports:
- protocol: TCP
port: 6379V podstate sme povolili prichádzajúcu prevádzku na port Redis z Node.js. A nič iné zjavne nezakazovali. Akonáhle sa zobrazí NetworkPolicy, všetky v ňom uvedené selektory začnú byť izolované, pokiaľ nie je uvedené inak. Pravidlá izolácie sa však nevzťahujú na iné objekty, na ktoré sa selektor nevzťahuje.
Príklad používa apiVersion Kubernetes je po vybalení, ale nič vám nebráni v jeho používaní . Syntax je tam podrobnejšia, takže budete musieť prepísať pravidlo pre vyššie uvedený prípad v nasledujúcom tvare:
apiVersion: crd.projectcalico.org/v1
kind: NetworkPolicy
metadata:
name: allow-redis-nodejs
spec:
selector: service == 'redis'
ingress:
- action: Allow
protocol: TCP
source:
selector: service == 'nodejs'
destination:
ports:
- 6379 Vyššie uvedené konštrukcie na povolenie alebo odmietnutie všetkej premávky cez bežné API NetworkPolicy obsahujú konštrukcie so zátvorkami, ktoré je ťažké pochopiť a zapamätať si. V prípade Calico, ak chcete zmeniť logiku pravidla brány firewall na opačnú, stačí zmeniť action: Allow na action: Deny.
Izolácia prostredím
Teraz si predstavte situáciu, keď aplikácia generuje obchodné metriky na zber v Prometheus a ďalšiu analýzu pomocou Grafany. Nahraný súbor môže obsahovať citlivé údaje, ktoré sú opäť predvolene verejne prístupné. Skryjme tieto údaje pred zvedavými očami:

Prometheus je spravidla umiestnený v samostatnom servisnom prostredí - v príklade to bude menný priestor, ako je tento:
apiVersion: v1
kind: Namespace
metadata:
labels:
module: prometheus
name: kube-prometheus Pole metadata.labels ukázalo sa, že to nebola náhoda. Ako je spomenuté vyššie, namespaceSelector (ako aj podSelector) pracuje so štítkami. Preto, aby ste umožnili prevzatie metrík zo všetkých modulov na konkrétnom porte, budete musieť pridať nejaký druh označenia (alebo prevziať z existujúcich) a potom použiť konfiguráciu ako:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-metrics-prom
spec:
podSelector: {}
ingress:
- from:
- namespaceSelector:
matchLabels:
module: prometheus
ports:
- protocol: TCP
port: 9100A ak použijete zásady Calico, syntax bude vyzerať takto:
apiVersion: crd.projectcalico.org/v1
kind: NetworkPolicy
metadata:
name: allow-metrics-prom
spec:
ingress:
- action: Allow
protocol: TCP
source:
namespaceSelector: module == 'prometheus'
destination:
ports:
- 9100Vo všeobecnosti, pridaním týchto druhov politík pre špecifické potreby sa môžete chrániť pred škodlivými alebo náhodnými zásahmi do prevádzky aplikácií v klastri.
Najlepšou praxou je podľa tvorcov Calico prístup „Zablokujte všetko a explicitne otvorte, čo potrebujete“, zdokumentovaný v (iní majú podobný prístup - najmä v ).
Používanie ďalších Calico objektov
Dovoľte mi pripomenúť, že prostredníctvom rozšírenej sady Calico API môžete regulovať dostupnosť uzlov, nielen podov. V nasledujúcom príklade s použitím GlobalNetworkPolicy schopnosť odovzdávať požiadavky ICMP v klastri je zatvorená (napríklad ping z modulu do uzla, medzi modulmi alebo z uzla do modulu IP):
apiVersion: crd.projectcalico.org/v1
kind: GlobalNetworkPolicy
metadata:
name: block-icmp
spec:
order: 200
selector: all()
types:
- Ingress
- Egress
ingress:
- action: Deny
protocol: ICMP
egress:
- action: Deny
protocol: ICMP Vo vyššie uvedenom prípade je stále možné, aby sa uzly klastra navzájom „dosiahli“ prostredníctvom protokolu ICMP. A tento problém je vyriešený prostriedkami GlobalNetworkPolicy, aplikovaný na účtovnú jednotku HostEndpoint:
apiVersion: crd.projectcalico.org/v1
kind: GlobalNetworkPolicy
metadata:
name: deny-icmp-kube-02
spec:
selector: "role == 'k8s-node'"
order: 0
ingress:
- action: Allow
protocol: ICMP
egress:
- action: Allow
protocol: ICMP
---
apiVersion: crd.projectcalico.org/v1
kind: HostEndpoint
metadata:
name: kube-02-eth0
labels:
role: k8s-node
spec:
interfaceName: eth0
node: kube-02
expectedIPs: ["192.168.2.2"]Prípad VPN
Nakoniec uvediem veľmi reálny príklad použitia funkcií Calico pre prípad interakcie blízko klastra, keď štandardná sada politík nestačí. Na prístup k webovej aplikácii klienti používajú tunel VPN a tento prístup je prísne kontrolovaný a obmedzený na konkrétny zoznam povolených služieb:

Klienti sa pripájajú k VPN cez štandardný UDP port 1194 a po pripojení dostávajú trasy do klastrových podsietí podov a služieb. Celé podsiete sú posunuté, aby nedošlo k strate služieb počas reštartov a zmien adries.
Port v konfigurácii je štandardný, čo spôsobuje určité nuansy v procese konfigurácie aplikácie a jej prenosu do klastra Kubernetes. Napríklad v tom istom AWS sa LoadBalancer pre UDP objavil doslova na konci minulého roka v obmedzenom zozname regiónov a NodePort nemožno použiť z dôvodu jeho presmerovania na všetky uzly klastra a nie je možné škálovať počet inštancií servera pre na účely odolnosti voči chybám. Navyše budete musieť zmeniť predvolený rozsah portov...
Ako výsledok hľadania možných riešení bolo zvolené nasledovné:
- Pody s VPN sú naplánované pre každý uzol
hostNetwork, teda do skutočnej IP. - Služba je zverejnená vonku cez
ClusterIP. Na uzle je fyzicky nainštalovaný port, ktorý je zvonku prístupný s menšími výhradami (podmienená prítomnosť skutočnej IP adresy). - Určenie uzla, na ktorom struková ruža, je nad rámec nášho príbehu. Poviem len, že službu môžete napevno prepojiť s uzlom alebo napísať malú postrannú službu, ktorá bude sledovať aktuálnu IP adresu služby VPN a upravovať záznamy DNS zaregistrované u klientov - kto má dostatok fantázie.
Z hľadiska smerovania môžeme klienta VPN jednoznačne identifikovať podľa jeho IP adresy vydanej serverom VPN. Nižšie je uvedený primitívny príklad obmedzenia prístupu takéhoto klienta k službám, znázornený na vyššie uvedenom Redis:
apiVersion: crd.projectcalico.org/v1
kind: HostEndpoint
metadata:
name: vpnclient-eth0
labels:
role: vpnclient
environment: production
spec:
interfaceName: "*"
node: kube-02
expectedIPs: ["172.176.176.2"]
---
apiVersion: crd.projectcalico.org/v1
kind: GlobalNetworkPolicy
metadata:
name: vpn-rules
spec:
selector: "role == 'vpnclient'"
order: 0
applyOnForward: true
preDNAT: true
ingress:
- action: Deny
protocol: TCP
destination:
ports: [6379]
- action: Allow
protocol: UDP
destination:
ports: [53, 67]Tu je pripojenie k portu 6379 prísne zakázané, ale zároveň je zachovaná prevádzka služby DNS, ktorej fungovanie pri zostavovaní pravidiel pomerne často trpí. Pretože, ako už bolo spomenuté, keď sa zobrazí selektor, použije sa naň predvolená politika odmietnutia, pokiaľ nie je uvedené inak.
Výsledky
Pomocou pokročilého API Calico teda môžete flexibilne konfigurovať a dynamicky meniť smerovanie v klastri a okolo neho. Vo všeobecnosti môže jeho použitie vyzerať ako strieľanie vrabcov kanónom a implementácia L3 siete s BGP a IP-IP tunelmi vyzerá v jednoduchej inštalácii Kubernetes na plochej sieti obludne... Inak však nástroj vyzerá celkom životaschopne a užitočne .
Izolácia klastra na splnenie bezpečnostných požiadaviek nemusí byť vždy uskutočniteľná a práve tu prichádza na pomoc Calico (alebo podobné riešenie). Príklady uvedené v tomto článku (s menšími úpravami) sú použité vo viacerých inštaláciách našich klientov v AWS.
PS
Prečítajte si aj na našom blogu:
- «»;
- "Ilustrovaný sprievodca sieťou v Kubernetes": , ;
- «".
Zdroj: hab.com
