Calico tinkle Kubernetes: įvadas ir šiek tiek patirties

Calico tinkle Kubernetes: įvadas ir šiek tiek patirties

Straipsnio tikslas – supažindinti skaitytoją su „Kubernetes“ tinklo ir tinklo politikos valdymo pagrindais, taip pat su trečiosios šalies „Calico“ papildiniu, praplečiančiu standartines galimybes. Be to, konfigūravimo paprastumas ir kai kurios funkcijos bus pademonstruotos naudojant realius pavyzdžius iš mūsų veiklos patirties.

Greitas įvadas į Kubernetes tinklo įrenginį

„Kubernetes“ klasteris neįsivaizduojamas be tinklo. Mes jau paskelbėme medžiagą apie jų pagrindus: „Iliustruotas „Kubernetes“ tinklo vadovas"Ir"„Kubernetes“ tinklo politikos įvadas saugos specialistams".

Šio straipsnio kontekste svarbu pažymėti, kad pats K8s nėra atsakingas už tinklo ryšį tarp konteinerių ir mazgų: tam skirtos įvairios CNI papildiniai (Container Networking Interface). Daugiau apie šią koncepciją mes jie man taip pat pasakė.

Pavyzdžiui, labiausiai paplitęs iš šių įskiepių yra Flanelė — užtikrina visišką tinklo ryšį tarp visų klasterio mazgų, keldamas tiltus kiekviename mazge, priskirdamas jam potinklį. Tačiau visiškas ir nereguliuojamas prieinamumas ne visada yra naudingas. Norint užtikrinti minimalią klasterio izoliaciją, būtina įsikišti į ugniasienės konfigūraciją. Paprastai jį kontroliuoja tas pats CNI, todėl bet kokios trečiosios šalies intervencijos į iptables gali būti interpretuojamos neteisingai arba visiškai ignoruojamos.

Taip pat yra numatytas tinklo politikos valdymo organizavimas Kubernetes klasteryje NetworkPolicy API. Šiame šaltinyje, paskirstytame pasirinktose vardų erdvėse, gali būti taisyklių, skirtų atskirti vienos programos prieigą prie kitos. Tai taip pat leidžia konfigūruoti pasiekiamumą tarp konkrečių rinkinių, aplinkų (pavadinimų erdvių) arba IP adresų blokų:

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

Tai nėra pats primityviausias pavyzdys oficialius dokumentus gali kartą ir visiems laikams atgrasyti nuo noro suprasti tinklo politikos veikimo logiką. Tačiau mes vis tiek pabandysime suprasti pagrindinius srauto srautų apdorojimo principus ir metodus naudojant tinklo politiką...

Logiška, kad yra 2 srauto tipai: įėjimas į podą (Ingress) ir išeinantis iš jo (Egress).

Calico tinkle Kubernetes: įvadas ir šiek tiek patirties

Tiesą sakant, politika pagal judėjimo kryptį skirstoma į šias 2 kategorijas.

Kitas būtinas atributas yra parinkiklis; tas, kuriam galioja taisyklė. Tai gali būti grupė (arba jų grupė) arba aplinka (t. y. vardų erdvė). Svarbi detalė: abiejų šių objektų tipai turi turėti etiketę (etiketė Kubernetes terminologija) – tai yra tie, kuriais politikai operuoja.

Be riboto skaičiaus selektorių, kuriuos vienija tam tikra etiketė, galima įvairiais variantais parašyti tokias taisykles kaip „Leisti/neleisti viską/visiems“. Šiuo tikslu naudojamos formos konstrukcijos:

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

– šiame pavyzdyje visos aplinkos ankštys yra užblokuotos įeinančiam srautui. Priešingą elgesį galima pasiekti naudojant tokią konstrukciją:

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

Panašiai ir išeinantiems:

  podSelector: {}
  policyTypes:
  - Egress

- jį išjungti. Ir štai ką įtraukti:

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

Grįžtant prie CNI įskiepio pasirinkimo klasteriui, verta paminėti ne kiekvienas tinklo papildinys palaiko NetworkPolicy. Pavyzdžiui, jau minėtas „Flanel“ nemoka konfigūruoti tinklo strategijų, kurios tai pasakyta tiesiai oficialioje saugykloje. Ten minima ir alternatyva – atvirojo kodo projektas kartūnas, kuris žymiai išplečia standartinį Kubernetes API rinkinį tinklo politikos požiūriu.

Calico tinkle Kubernetes: įvadas ir šiek tiek patirties

Susipažinimas su Calico: teorija

„Calico“ papildinys gali būti naudojamas kartu su „Flanel“ (paprojekčiu Kanalas) arba atskirai, apimantis tiek tinklo ryšį, tiek pasiekiamumo valdymo galimybes.

Kokias galimybes suteikia K8s „boxed“ sprendimas ir API rinkinys iš Calico?

Štai kas integruota į NetworkPolicy:

  • politikus riboja aplinka;
  • politika taikomos etiketėmis pažymėtoms ankštims;
  • taisyklės gali būti taikomos ankštims, aplinkoms ar potinkliams;
  • taisyklėse gali būti protokolų, pavadintų arba simbolinių prievadų specifikacijų.

Štai kaip Calico išplečia šias funkcijas:

  • politika gali būti taikoma bet kokiam objektui: pod, konteineriui, virtualiai mašinai ar sąsajai;
  • taisyklėse gali būti nurodytas konkretus veiksmas (draudimas, leidimas, registravimas);
  • taisyklių tikslas arba šaltinis gali būti prievadas, prievadų diapazonas, protokolai, HTTP arba ICMP atributai, IP arba potinklis (4 arba 6 karta), bet kokie selektoriai (mazgai, prieglobos, aplinkos);
  • Be to, srautą galite reguliuoti naudodami DNAT nustatymus ir srauto persiuntimo politiką.

Pirmieji įsipareigojimai „GitHub“ „Calico“ saugykloje datuojami 2016 m. liepos mėn., o po metų projektas užėmė lyderio poziciją organizuojant „Kubernetes“ tinklo ryšį – tai liudija, pavyzdžiui, apklausos rezultatai, dirigavo „The New Stack“.:

Calico tinkle Kubernetes: įvadas ir šiek tiek patirties

Daugelis didelių valdomų sprendimų su K8, pvz Amazon EX, Azure AKS, Google GKE ir kiti pradėjo rekomenduoti jį naudoti.

Kalbant apie našumą, čia viskas puiku. Bandydama savo gaminį, Calico kūrėjų komanda pademonstravo astronominį našumą, naudodama daugiau nei 50000 500 konteinerių 20 fizinių mazgų, kurių kūrimo greitis buvo XNUMX konteinerių per sekundę. Su mastelio keitimu problemų nenustatyta. Tokie rezultatai buvo paskelbti jau paskelbus pirmąją versiją. Nepriklausomi tyrimai, kuriuose daugiausia dėmesio skiriama pralaidumui ir išteklių sunaudojimui, taip pat patvirtina, kad Calico našumas yra beveik toks pat geras kaip Flannel. Pavyzdžiui:

Calico tinkle Kubernetes: įvadas ir šiek tiek patirties

Projektas vystosi labai greitai, palaiko darbą populiariuose sprendimuose, valdomuose K8s, OpenShift, OpenStack, galima naudoti Calico diegiant klasterį naudojant spardyti, yra nuorodų į Service Mesh tinklų kūrimą (čia yra pavyzdys naudojamas kartu su Istio).

Praktikuokite su Calico

Paprastai naudojant vanilinį Kubernetes, CNI įdiegimas reiškia failo naudojimą calico.yaml, parsisiųsti iš oficialios svetainės, naudojant kubectl apply -f.

Paprastai dabartinė papildinio versija yra suderinama su naujausiomis 2–3 „Kubernetes“ versijomis: veikimas senesnėse versijose nėra išbandytas ir negarantuojamas. Pasak kūrėjų, „Calico“ veikia „Linux“ branduoliuose, aukštesniuose nei 3.10, kuriuose veikia „CentOS 7“, „Ubuntu 16“ arba „Debian 8“, be „iptables“ ar IPVS.

Izoliacija aplinkoje

Kad būtų lengviau suprasti, pažvelkime į paprastą atvejį, kad suprastume, kuo tinklo politika Calico žymėjime skiriasi nuo standartinių ir kaip taisyklių kūrimo metodas supaprastina jų skaitomumą ir konfigūracijos lankstumą:

Calico tinkle Kubernetes: įvadas ir šiek tiek patirties

Klasteryje yra įdiegtos 2 žiniatinklio programos: Node.js ir PHP, viena iš jų naudoja Redis. Norėdami užblokuoti prieigą prie Redis iš PHP, išlaikant ryšį su Node.js, tiesiog taikykite šią politiką:

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

Iš esmės leidome įeinantį srautą į Redis prievadą iš Node.js. Ir jie aiškiai nieko kito nedraudė. Kai tik pasirodo „NetworkPolicy“, visi joje paminėti parinkikliai pradedami atskirti, nebent nurodyta kitaip. Tačiau izoliavimo taisyklės netaikomos kitiems objektams, kurių neapima parinkiklis.

Pavyzdys naudoja apiVersion Kubernetes iš dėžutės, bet niekas netrukdo juo naudotis to paties pavadinimo šaltinis iš Calico pristatymo. Sintaksė yra išsamesnė, todėl turėsite perrašyti taisyklę aukščiau nurodytam atvejui tokia forma:

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

Pirmiau minėtose konstrukcijose, leidžiančiose arba uždrausti bet kokį srautą per įprastą NetworkPolicy API, yra konstrukcijos su skliaustais, kurias sunku suprasti ir prisiminti. Calico atveju, norėdami pakeisti ugniasienės taisyklės logiką į priešingą, tiesiog pakeiskite action: Allow apie action: Deny.

Izoliacija pagal aplinką

Dabar įsivaizduokite situaciją, kai programa generuoja verslo metriką rinkimui „Prometheus“ ir tolesnei analizei naudojant „Grafana“. Įkeltame dokumente gali būti neskelbtinų duomenų, kurie pagal numatytuosius nustatymus vėl yra viešai matomi. Paslėpkime šiuos duomenis nuo smalsių akių:

Calico tinkle Kubernetes: įvadas ir šiek tiek patirties

„Prometheus“, kaip taisyklė, dedamas į atskirą paslaugų aplinką - pavyzdyje tai bus tokia vardų erdvė:

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

Laukas metadata.labels tai pasirodė neatsitiktinai. Kaip paminėta aukščiau, namespaceSelector (taip pat podSelector) veikia su etiketėmis. Todėl norėdami leisti paimti metriką iš visų konkretaus prievado rinkinių, turėsite pridėti tam tikrą etiketę (arba paimti iš esamų) ir pritaikyti tokią konfigūraciją:

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

Ir jei naudojate Calico politiką, sintaksė bus tokia:

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

Apskritai, pridėję šios rūšies politiką konkretiems poreikiams, galite apsisaugoti nuo kenkėjiškų ar atsitiktinių trukdžių klasterio taikomųjų programų veikimui.

Geriausia praktika, pasak Calico kūrėjų, yra metodas „Blokuoti viską ir aiškiai atidaryti tai, ko jums reikia“, dokumentuotas oficialius dokumentus (kiti laikosi panašaus požiūrio – ypač in jau minėtas straipsnis).

Papildomų Calico objektų naudojimas

Leiskite jums priminti, kad naudodamiesi išplėstiniu Calico API rinkiniu galite reguliuoti mazgų prieinamumą, neapsiribojant vienetais. Toliau pateiktame pavyzdyje naudojant GlobalNetworkPolicy galimybė perduoti ICMP užklausas klasteryje yra uždaryta (pavyzdžiui, ping iš grupės į mazgą, tarp blokų arba iš mazgo į IP grupę):

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

Aukščiau nurodytu atveju klasterio mazgai vis tiek gali „susiekti“ vienas su kitu per ICMP. Ir ši problema išspręsta priemonėmis GlobalNetworkPolicy, taikoma subjektui 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"]

VPN byla

Galiausiai pateiksiu labai realų Calico funkcijų naudojimo pavyzdį beveik klasterio sąveikos atveju, kai standartinio strategijų rinkinio nepakanka. Norėdami pasiekti žiniatinklio programą, klientai naudoja VPN tunelį, ši prieiga yra griežtai kontroliuojama ir apribota konkrečiu paslaugų, kurias leidžiama naudoti, sąrašu:

Calico tinkle Kubernetes: įvadas ir šiek tiek patirties

Klientai prisijungia prie VPN per standartinį UDP prievadą 1194 ir, prisijungę, gauna maršrutus į grupių ir paslaugų potinklius. Visi potinkliai yra stumiami, kad neprarastų paslaugų paleidžiant iš naujo ir keičiant adresus.

Konfigūracijos prievadas yra standartinis, o tai suteikia tam tikrų niuansų programos konfigūravimo ir perkėlimo į Kubernetes klasterį procesui. Pavyzdžiui, tame pačiame AWS LoadBalancer for UDP pasirodė pažodžiui praėjusių metų pabaigoje ribotame regionų sąraše, o NodePort negalima naudoti dėl jo persiuntimo visuose klasterio mazguose ir neįmanoma pakeisti serverio egzempliorių skaičiaus. gedimų tolerancijos tikslais. Be to, turėsite pakeisti numatytąjį prievadų diapazoną...

Išnagrinėjus galimus sprendimus buvo pasirinkta:

  1. Pods su VPN yra suplanuotas kiekvienam mazgui hostNetwork, tai yra, į tikrąjį IP.
  2. Paslauga skelbiama lauke per ClusterIP. Mazge yra fiziškai įdiegtas prievadas, kuris pasiekiamas iš išorės su nedidelėmis išlygomis (sąlyginis tikro IP adreso buvimas).
  3. Nustatyti mazgą, ant kurio išaugo ankštis, mūsų istorija nepatenka. Aš tiesiog pasakysiu, kad galite tvirtai „prikalti“ paslaugą prie mazgo arba parašyti nedidelę šoninio automobilio paslaugą, kuri stebės dabartinį VPN paslaugos IP adresą ir redaguoja DNS įrašus, registruotus pas klientus - kas turi pakankamai vaizduotės.

Žvelgiant iš maršruto perspektyvos, galime unikaliai identifikuoti VPN klientą pagal jo IP adresą, išduotą VPN serverio. Žemiau pateikiamas primityvus tokio kliento prieigos prie paslaugų ribojimo pavyzdys, iliustruotas aukščiau minėtame 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]

Čia griežtai draudžiama prisijungti prie 6379 prievado, tačiau tuo pačiu išsaugomas DNS paslaugos veikimas, kurio veikimas gana dažnai nukenčia rengiant taisykles. Kadangi, kaip minėta anksčiau, pasirodžius parinkikliui, jam taikoma numatytoji atmetimo politika, jei nenurodyta kitaip.

rezultatai

Taigi, naudodami išplėstinę Calico API, galite lanksčiai konfigūruoti ir dinamiškai keisti maršrutą klasteryje ir aplink jį. Apskritai jo naudojimas gali atrodyti kaip šaudymas į žvirblius iš patrankos, o L3 tinklo įdiegimas su BGP ir IP-IP tuneliais atrodo siaubingai paprasta Kubernetes instaliacija plokščiame tinkle... Tačiau kitu atveju įrankis atrodo gana perspektyvus ir naudingas. .

Atskirti klasterį, kad jis atitiktų saugos reikalavimus, ne visada įmanoma, todėl „Calico“ (ar panašus sprendimas) ateina į pagalbą. Šiame straipsnyje pateikti pavyzdžiai (su nedideliais pakeitimais) naudojami keliuose mūsų klientų AWS įrenginiuose.

PS

Taip pat skaitykite mūsų tinklaraštyje:

Šaltinis: www.habr.com

Добавить комментарий