Calico za umrežavanje u Kubernetesu: uvod i malo iskustva

Calico za umrežavanje u Kubernetesu: uvod i malo iskustva

Svrha je članka upoznati čitatelja s osnovama umrežavanja i upravljanja mrežnim pravilima u Kubernetesu, kao i dodatkom Calico treće strane koji proširuje standardne mogućnosti. Usput će se demonstrirati jednostavnost konfiguracije i neke značajke korištenjem stvarnih primjera iz našeg radnog iskustva.

Kratki uvod u Kubernetes mrežni uređaj

Kubernetes klaster se ne može zamisliti bez mreže. Već smo objavili materijale o njihovim osnovama: “Ilustrirani vodič za umrežavanje u Kubernetesu"A"Uvod u mrežna pravila Kubernetes za sigurnosne stručnjake".

U kontekstu ovog članka, važno je napomenuti da sam K8s nije odgovoran za mrežnu povezanost između spremnika i čvorova: za to su različiti CNI dodaci (Mrežno sučelje spremnika). Više o ovom konceptu mi rekli su mi i oni.

Na primjer, najčešći od ovih dodataka je Flanel — pruža potpunu mrežnu povezanost između svih čvorova klastera podizanjem mostova na svakom čvoru, dodjeljivanjem podmreže za njega. Međutim, potpuna i neregulirana dostupnost nije uvijek korisna. Kako bi se osigurala neka vrsta minimalne izolacije u klasteru, potrebno je intervenirati u konfiguraciji vatrozida. U općem slučaju, stavljen je pod kontrolu istog CNI-ja, zbog čega se bilo kakve intervencije trećih strana u iptables mogu protumačiti netočno ili u potpunosti zanemariti.

Dostupno je i "izvan okvira" za organiziranje upravljanja mrežnim pravilima u Kubernetes klasteru NetworkPolicy API. Ovaj resurs, distribuiran u odabranim imenskim prostorima, može sadržavati pravila za razlikovanje pristupa jedne aplikacije drugoj. Također vam omogućuje da konfigurirate pristupačnost između određenih mahuna, okruženja (imenskih prostora) ili blokova IP adresa:

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

Ovo nije najprimitivniji primjer službena dokumentacija može jednom zauvijek obeshrabriti želju za razumijevanjem logike funkcioniranja mrežnih politika. Ipak, pokušat ćemo razumjeti osnovne principe i metode obrade tokova prometa pomoću mrežnih politika...

Logično je da postoje 2 vrste prometa: ulaz u pod (Ingress) i izlaz iz njega (Egress).

Calico za umrežavanje u Kubernetesu: uvod i malo iskustva

Zapravo, politika se prema smjeru kretanja dijeli u ove 2 kategorije.

Sljedeći potrebni atribut je selektor; onaj na koga se pravilo odnosi. To može biti pod (ili grupa podova) ili okruženje (tj. imenski prostor). Važan detalj: obje vrste ovih objekata moraju sadržavati oznaku (oznaka u terminologiji Kubernetesa) - to su oni s kojima operiraju političari.

Osim konačnog broja selektora objedinjenih nekom vrstom oznake, moguće je napisati pravila poput “Dopusti/zabrani sve/svima” u različitim varijantama. U tu svrhu koriste se konstrukcije oblika:

  podSelector: {}
  ingress: []
  policyTypes:
  - Ingress

— u ovom primjeru, sve jedinice u okruženju su blokirane od dolaznog prometa. Suprotno ponašanje može se postići sljedećom konstrukcijom:

  podSelector: {}
  ingress:
  - {}
  policyTypes:
  - Ingress

Slično za odlazne:

  podSelector: {}
  policyTypes:
  - Egress

- da ga isključite. A evo što uključiti:

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

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 konfigurirati mrežna pravila, koja to je izravno rečeno u službenom repozitoriju. Tu se spominje i alternativa - Open Source projekt platno, koji značajno proširuje standardni skup Kubernetes API-ja u smislu mrežnih pravila.

Calico za umrežavanje u Kubernetesu: uvod i malo iskustva

Upoznavanje s Calico: teorija

Dodatak Calico može se koristiti u integraciji s Flannelom (potprojekt Kanal) ili neovisno, pokrivajući i mrežnu povezanost i mogućnosti upravljanja dostupnošću.

Koje mogućnosti pruža korištenje K8s "boxed" rješenja i API skupa iz Calica?

Evo što je ugrađeno u NetworkPolicy:

  • političare ograničava okolina;
  • pravila se primjenjuju na mahune označene naljepnicama;
  • pravila se mogu primijeniti na podove, okruženja ili podmreže;
  • pravila mogu sadržavati protokole, imenovane ili simboličke specifikacije porta.

Evo kako Calico proširuje te funkcije:

  • pravila se mogu primijeniti na bilo koji objekt: pod, spremnik, virtualni stroj ili sučelje;
  • pravila mogu sadržavati određenu akciju (zabrana, dopuštenje, zapis);
  • cilj ili izvor pravila može biti port, niz portova, protokoli, HTTP ili ICMP atributi, IP ili podmreža (4. ili 6. generacija), bilo koji selektori (čvorovi, hostovi, okruženja);
  • Dodatno, možete regulirati prolaz prometa pomoću DNAT postavki i politika prosljeđivanja prometa.

Prvi komiti na GitHubu u Calico repozitoriju datiraju iz srpnja 2016., a godinu dana kasnije projekt je preuzeo vodeću poziciju u organizaciji Kubernetes mrežnog povezivanja – tome svjedoče, primjerice, rezultati ankete, provodi The New Stack:

Calico za umrežavanje u Kubernetesu: uvod i malo iskustva

Mnoga velika upravljana rješenja s K8, kao što su Amazon EKS, Azurni AKS, Google GKE a drugi su ga počeli preporučivati ​​za korištenje.

Što se performansi tiče, ovdje je sve super. U testiranju svog proizvoda, razvojni tim Calico pokazao je astronomske performanse, pokrenuvši više od 50000 spremnika na 500 fizičkih čvorova s ​​brzinom stvaranja od 20 spremnika u sekundi. Nisu identificirani problemi s skaliranjem. Ovakvi rezultati bili su najavljeni već pri najavi prve verzije. Neovisne studije koje se fokusiraju na propusnost i potrošnju resursa također potvrđuju da je Calicov učinak gotovo jednako dobar kao Flannelov. Na primjer:

Calico za umrežavanje u Kubernetesu: uvod i malo iskustva

Projekt se razvija vrlo brzo, podržava rad u popularnim rješenjima kojima se upravlja K8s, OpenShift, OpenStack, moguće je koristiti Calico prilikom postavljanja klastera pomoću udarac nogom, postoje reference na izgradnju Service Mesh mreža (ovdje je primjer koristi se zajedno s Istio).

Vježbajte s Calico

U općenitom slučaju korištenja vanilla Kubernetesa, instaliranje CNI-ja svodi se na korištenje datoteke calico.yaml, preuzeto sa službene stranice, s pomoću kubectl apply -f.

U pravilu je trenutna verzija dodatka kompatibilna s posljednje 2-3 verzije Kubernetesa: rad u starijim verzijama nije testiran i nije zajamčen. Prema programerima, Calico radi na Linux kernelima iznad 3.10 s CentOS 7, Ubuntu 16 ili Debian 8, povrh iptables ili IPVS.

Izolacija unutar okoline

Za opće razumijevanje, pogledajmo jednostavan slučaj da bismo razumjeli kako se mrežna pravila u Calico notaciji razlikuju od standardnih i kako pristup stvaranju pravila pojednostavljuje njihovu čitljivost i fleksibilnost konfiguracije:

Calico za umrežavanje u Kubernetesu: uvod i malo iskustva

U klasteru su postavljene 2 web aplikacije: u Node.js i PHP, od kojih jedna koristi Redis. Da biste blokirali pristup Redisu iz PHP-a, a da pritom zadržite povezanost s Node.js, samo primijenite sljedeća pravila:

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

U biti smo dopustili dolazni promet na Redis port iz Node.js. I očito nisu ništa drugo zabranili. Čim se NetworkPolicy pojavi, svi selektori spomenuti u njemu počinju se izolirati, osim ako nije drugačije navedeno. Međutim, pravila izolacije ne primjenjuju se na druge objekte koji nisu obuhvaćeni selektorom.

Primjer koristi apiVersion Kubernetes izvan kutije, ali ništa vas ne sprječava da ga koristite izvor istog naziva iz Calico isporuke. Tamošnja sintaksa je detaljnija, pa ćete morati ponovno napisati pravilo za gornji slučaj u sljedećem obliku:

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

Gore spomenute konstrukcije za dopuštanje ili zabranjivanje cjelokupnog prometa putem uobičajenog API-ja NetworkPolicy sadrže konstrukcije sa zagradama koje je teško razumjeti i zapamtiti. U slučaju Calica, da biste promijenili logiku pravila vatrozida u suprotnu, samo promijenite action: Allow na action: Deny.

Izolacija okolinom

Sada zamislite situaciju u kojoj aplikacija generira poslovne metrike za prikupljanje u Prometheusu i daljnju analizu pomoću Grafane. Prijenos može sadržavati osjetljive podatke, koji su ponovno javno vidljivi prema zadanim postavkama. Sakrijmo ove podatke od znatiželjnih očiju:

Calico za umrežavanje u Kubernetesu: uvod i malo iskustva

Prometheus se u pravilu postavlja u zasebno okruženje usluge - u primjeru će to biti prostor imena poput ovog:

apiVersion: v1
kind: Namespace
metadata:
  labels:
    module: prometheus
  name: kube-prometheus

Polje metadata.labels pokazalo se da to nije slučajno. Kao što je gore navedeno, namespaceSelector (kao i podSelector) radi s oznakama. Stoga, da biste omogućili preuzimanje metrike iz svih mahuna na određenom priključku, morat ćete dodati neku vrstu oznake (ili uzeti iz postojećih), a zatim primijeniti konfiguraciju poput:

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 ako koristite Calico pravila, sintaksa će biti ovakva:

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

Općenito, dodavanjem ovakvih pravila za specifične potrebe, možete se zaštititi od zlonamjernog ili slučajnog uplitanja u rad aplikacija u klasteru.

Najbolja praksa, prema kreatorima Calica, je pristup "Blokiraj sve i eksplicitno otvori ono što trebaš", dokumentiran u službena dokumentacija (drugi slijede sličan pristup - posebice u već spomenuti članak).

Korištenje dodatnih Calico objekata

Dopustite mi da vas podsjetim da putem proširenog skupa Calico API-ja možete regulirati dostupnost čvorova, ne ograničavajući se na podove. U sljedećem primjeru pomoću GlobalNetworkPolicy mogućnost prosljeđivanja ICMP zahtjeva u klasteru je zatvorena (na primjer, pingovi od modula do čvora, između modula ili od čvora do IP modula):

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

U gornjem slučaju još uvijek je moguće da čvorovi klastera "dopru" jedni do drugih putem ICMP-a. I ovo pitanje je riješeno sredstvima GlobalNetworkPolicy, primijenjen na entitet 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"]

Slučaj VPN

Konačno, dat ću vrlo stvaran primjer korištenja Calico funkcija za slučaj interakcije blizu klastera, kada standardni skup politika nije dovoljan. Za pristup web aplikaciji klijenti koriste VPN tunel, a taj pristup je strogo kontroliran i ograničen na određeni popis usluga dopuštenih za korištenje:

Calico za umrežavanje u Kubernetesu: uvod i malo iskustva

Klijenti se povezuju na VPN putem standardnog UDP porta 1194 i, kada su povezani, primaju rute do podmreža klastera podova i usluga. Cijele podmreže se guraju kako se ne bi izgubile usluge prilikom ponovnog pokretanja i promjene adresa.

Port u konfiguraciji je standardan, što nameće neke nijanse u procesu konfiguriranja aplikacije i njenog prijenosa u Kubernetes klaster. Na primjer, u istom AWS-u LoadBalancer za UDP pojavio se doslovno krajem prošle godine u ograničenom popisu regija, a NodePort se ne može koristiti zbog prosljeđivanja na svim čvorovima klastera i nemoguće je skalirati broj instanci poslužitelja za svrhe tolerancije grešaka. Osim toga, morat ćete promijeniti zadani raspon portova...

Kao rezultat traženja mogućih rješenja odabrano je sljedeće:

  1. Podovi s VPN-om zakazani su po čvoru hostNetwork, odnosno na stvarni IP.
  2. Usluga je objavljena izvana kroz ClusterIP. Na čvoru je fizički instaliran port koji je dostupan izvana uz manje zadrške (uvjetna prisutnost stvarne IP adrese).
  3. Određivanje čvora na kojem je mahuna ruža izvan je okvira naše priče. Reći ću samo da uslugu možete čvrsto “prikovati” na čvor ili napisati malu pomoćnu uslugu koja će pratiti trenutnu IP adresu VPN usluge i uređivati ​​DNS zapise registrirane kod klijenata – tko ima dovoljno mašte.

Iz perspektive usmjeravanja, možemo jedinstveno identificirati VPN klijenta prema njegovoj IP adresi koju izdaje VPN poslužitelj. Ispod je primitivni primjer ograničavanja pristupa takvog klijenta uslugama, ilustriran na gore spomenutom Redisu:

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]

Ovdje je strogo zabranjeno povezivanje s portom 6379, ali je istovremeno očuvan rad DNS usluge, čije funkcioniranje često trpi prilikom izrade pravila. Jer, kao što je prethodno spomenuto, kada se birač pojavi, na njega se primjenjuje zadana politika odbijanja osim ako nije drugačije navedeno.

Rezultati

Stoga, korištenjem Calicovog naprednog API-ja, možete fleksibilno konfigurirati i dinamički mijenjati usmjeravanje unutar i oko klastera. Općenito, njegovo korištenje može izgledati kao pucanje vrabaca iz topa, a implementacija L3 mreže s BGP i IP-IP tunelima izgleda monstruozno u jednostavnoj instalaciji Kubernetesa na ravnoj mreži... No, inače alat izgleda prilično održiv i koristan .

Izoliranje klastera radi ispunjavanja sigurnosnih zahtjeva možda nije uvijek izvedivo, a tu Calico (ili slično rješenje) dolazi u pomoć. Primjeri navedeni u ovom članku (s manjim izmjenama) koriste se u nekoliko instalacija naših klijenata u AWS.

PS

Pročitajte i na našem blogu:

Izvor: www.habr.com

Dodajte komentar