Calico pre vytváranie sietí v Kubernetes: úvod a malá skúsenosť

Calico pre vytváranie sietí v Kubernetes: úvod a malá skúsenosť

Úč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: “Ilustrovaný sprievodca sieťou v Kubernetes"A"Úvod do sieťových zásad Kubernetes pre profesionálov v oblasti bezpečnosti".

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 tiež mi povedali.

Napríklad najbežnejším z týchto doplnkov je flanel — 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 NetworkPolicy API. 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: 5978

Toto nie je najprimitívnejší príklad oficiálna dokumentácia 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).

Calico pre vytváranie sietí v Kubernetes: úvod a malá skúsenosť

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:
  - Ingress

Podobne pre odchádzajúce:

  podSelector: {}
  policyTypes:
  - Egress

- vypnúť. A tu je to, čo treba zahrnúť:

  podSelector: {}
  egress:
  - {}
  policyTypes:
  - Egress

Keď 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é hovorí sa to priamo v oficiálnom úložisku. Spomína sa tam aj alternatíva – Open Source projekt kaliko, ktorý výrazne rozširuje štandardnú sadu Kubernetes API z hľadiska sieťových politík.

Calico pre vytváranie sietí v Kubernetes: úvod a malá skúsenosť

Spoznávanie Calico: teória

Doplnok Calico je možné použiť v integrácii s Flannel (podprojekt channel) 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, pod vedením The New Stack:

Calico pre vytváranie sietí v Kubernetes: úvod a malá skúsenosť

Mnoho veľkých riadených riešení s K8, ako napr Amazon EKS, Azure AKS, Google GKE 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 boli oznámené 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. Napríklad:

Calico pre vytváranie sietí v Kubernetes: úvod a malá skúsenosť

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 kopnúť, existujú odkazy na výstavbu sietí Service Mesh (tu je príklad 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, stiahnuté z oficiálnej stránky, s помощью kubectl apply -f.

Spravidla je aktuálna verzia pluginu kompatibilná s najnovšími 2-3 verziami Kubernetes: prevádzka v starších verziách nie je testovaná a nie je zaručená. Podľa vývojárov Calico beží na linuxových jadrách nad 3.10 so systémom CentOS 7, Ubuntu 16 alebo Debian 8, nad rámec 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:

Calico pre vytváranie sietí v Kubernetes: úvod a malá skúsenosť

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: 6379

V 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í zdroj s rovnakým názvom z dodávky Calico. 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:

Calico pre vytváranie sietí v Kubernetes: úvod a malá skúsenosť

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: 9100

A 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:
      - 9100

Vo 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 oficiálna dokumentácia (iní majú podobný prístup - najmä v už spomínaný článok).

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:

Calico pre vytváranie sietí v Kubernetes: úvod a malá skúsenosť

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é:

  1. Pody s VPN sú naplánované pre každý uzol hostNetwork, teda do skutočnej IP.
  2. 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).
  3. 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:

Zdroj: hab.com

Pridať komentár