Calico za mreženje v Kubernetesu: uvod in malo izkušenj

Calico za mreženje v Kubernetesu: uvod in malo izkušenj

Namen članka je bralcu predstaviti osnove mreženja in upravljanja omrežnih politik v Kubernetesu ter vtičnik Calico drugega proizvajalca, ki razširja standardne zmogljivosti. Med potjo bomo prikazali enostavnost konfiguracije in nekatere funkcije z dejanskimi primeri iz naših delovnih izkušenj.

Hiter uvod v omrežno napravo Kubernetes

Grozda Kubernetes si ni mogoče predstavljati brez omrežja. O njihovih osnovah smo že objavili gradiva: "Ilustriran vodnik za mreženje v Kubernetesu"In"Uvod v omrežne pravilnike Kubernetes za varnostne strokovnjake".

V kontekstu tega članka je pomembno omeniti, da K8s sam ni odgovoren za omrežno povezljivost med vsebniki in vozlišči: za to so različni vtičniki CNI (omrežni vmesnik vsebnika). Več o tem konceptu mi so mi tudi povedali.

Na primer, najpogostejši od teh vtičnikov je Flannel — zagotavlja popolno omrežno povezljivost med vsemi vozlišči gruče z dvigom mostov na vsakem vozlišču in mu dodeli podomrežje. Popolna in neurejena dostopnost pa ni vedno koristna. Da bi zagotovili nekakšno minimalno izolacijo v gruči, je treba poseči v konfiguracijo požarnega zidu. V splošnem primeru je postavljen pod nadzor istega CNI, zato se morebitni posegi tretjih oseb v iptables lahko interpretirajo nepravilno ali pa se sploh ne upoštevajo.

Na voljo je tudi »izven škatle« za organiziranje upravljanja omrežne politike v gruči Kubernetes API NetworkPolicy. Ta vir, porazdeljen po izbranih imenskih prostorih, lahko vsebuje pravila za razlikovanje dostopa od ene aplikacije do druge. Prav tako vam omogoča, da konfigurirate dostopnost med določenimi sklopi, okolji (imenski prostori) ali bloki naslovov 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

To ni najbolj primitiven primer uradna dokumentacija lahko enkrat za vselej odvrne željo po razumevanju logike delovanja omrežnih politik. Vendar bomo še vedno poskušali razumeti osnovna načela in metode obdelave prometnih tokov z uporabo omrežnih politik ...

Logično je, da obstajata dve vrsti prometa: vstop v pod (Ingress) in izhod iz njega (Egress).

Calico za mreženje v Kubernetesu: uvod in malo izkušenj

Pravzaprav se politika glede na smer gibanja deli na ti dve kategoriji.

Naslednji zahtevani atribut je izbirnik; tistega, za katerega pravilo velja. To je lahko pod (ali skupina podov) ali okolje (tj. imenski prostor). Pomembna podrobnost: obe vrsti teh objektov morata vsebovati oznako (nalepka v terminologiji Kubernetes) – to so tisti, s katerimi operirajo politiki.

Poleg končnega števila izbirnikov, združenih z nekakšno oznako, je mogoče napisati pravila, kot je "Dovoli/zavrni vse/vse" v različnih različicah. V ta namen se uporabljajo konstrukcije obrazca:

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

— v tem primeru so vsi podi v okolju blokirani pred dohodnim prometom. Nasprotno vedenje je mogoče doseči z naslednjo konstrukcijo:

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

Podobno za odhodne:

  podSelector: {}
  policyTypes:
  - Egress

- da ga izklopite. In tukaj je, kaj vključiti:

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

Če se vrnemo k izbiri vtičnika CNI za gručo, velja omeniti, da vsak omrežni vtičnik ne podpira NetworkPolicy. Na primer, že omenjeni Flannel ne zna konfigurirati omrežnih politik, ki je povedano direktno v uradnem repozitoriju. Tam je omenjena tudi alternativa - odprtokodni projekt Calico, ki znatno razširi standardni nabor API-jev Kubernetes v smislu omrežnih politik.

Calico za mreženje v Kubernetesu: uvod in malo izkušenj

Spoznavanje Calico: teorija

Vtičnik Calico se lahko uporablja v integraciji s Flannel (podprojekt Channel) ali neodvisno, ki zajema tako omrežno povezljivost kot zmožnosti upravljanja razpoložljivosti.

Kakšne priložnosti ponuja uporaba "škatlaste" rešitve K8s in nabora API-jev podjetja Calico?

Tukaj je vgrajeno v NetworkPolicy:

  • politiki so omejeni z okoljem;
  • politike se uporabljajo za stroke, označene z nalepkami;
  • pravila je mogoče uporabiti za sklope, okolja ali podomrežja;
  • pravila lahko vsebujejo protokole, poimenovane ali simbolične specifikacije vrat.

Tukaj je opisano, kako Calico razširi te funkcije:

  • politike je mogoče uporabiti za kateri koli predmet: pod, vsebnik, virtualni stroj ali vmesnik;
  • pravila lahko vsebujejo določeno dejanje (prepoved, dovoljenje, beleženje);
  • cilj ali vir pravil so lahko vrata, obseg vrat, protokoli, atributi HTTP ali ICMP, IP ali podomrežje (4. ali 6. generacija), kateri koli izbirniki (vozlišča, gostitelji, okolja);
  • Poleg tega lahko regulirate prehod prometa z nastavitvami DNAT in politikami posredovanja prometa.

Prve objave na GitHub v repozitoriju Calico segajo v julij 2016, leto kasneje pa je projekt prevzel vodilno mesto pri organizaciji omrežne povezljivosti Kubernetes – to dokazujejo na primer rezultati ankete, izvaja The New Stack:

Calico za mreženje v Kubernetesu: uvod in malo izkušenj

Veliko velikih upravljanih rešitev s K8, kot npr Amazon EKS, Azurni AKS, Google GKE in drugi so ga začeli priporočati za uporabo.

Kar zadeva zmogljivost, je tukaj vse super. Pri testiranju svojega izdelka je razvojna ekipa Calico pokazala astronomsko zmogljivost, saj je poganjala več kot 50000 vsebnikov na 500 fizičnih vozliščih s hitrostjo ustvarjanja 20 vsebnikov na sekundo. Pri skaliranju niso bile ugotovljene nobene težave. Takšni rezultati so bili napovedani že ob napovedi prve različice. Neodvisne študije, ki se osredotočajo na prepustnost in porabo virov, prav tako potrjujejo, da je zmogljivost Calica skoraj tako dobra kot Flannel. Na primer:

Calico za mreženje v Kubernetesu: uvod in malo izkušenj

Projekt se razvija zelo hitro, podpira delo v priljubljenih rešitvah, ki jih upravlja K8s, OpenShift, OpenStack, možno je uporabiti Calico pri uvajanju gruče z uporabo brcatiobstajajo sklicevanja na gradnjo omrežij Service Mesh (tukaj je primer uporablja se skupaj z Istio).

Vadite s Calico

V splošnem primeru uporabe vanilije Kubernetes se namestitev CNI zmanjša na uporabo datoteke calico.yaml, preneseno z uradne spletne strani, skozi kubectl apply -f.

Praviloma je trenutna različica vtičnika združljiva z najnovejšimi 2-3 različicami Kubernetesa: delovanje v starejših različicah ni testirano in ni zagotovljeno. Po navedbah razvijalcev Calico deluje na jedrih Linux nad 3.10, ki poganjajo CentOS 7, Ubuntu 16 ali Debian 8, poleg iptables ali IPVS.

Izolacija v okolju

Za splošno razumevanje si poglejmo preprost primer, da razumemo, kako se omrežne politike v zapisu Calico razlikujejo od standardnih in kako pristop k ustvarjanju pravil poenostavi njihovo berljivost in fleksibilnost konfiguracije:

Calico za mreženje v Kubernetesu: uvod in malo izkušenj

V gruči sta nameščeni 2 spletni aplikaciji: v Node.js in PHP, od katerih ena uporablja Redis. Če želite blokirati dostop do Redisa iz PHP-ja in hkrati ohraniti povezljivost z Node.js, samo uporabite ta pravilnik:

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 bistvu smo dovolili dohodni promet do vrat Redis iz Node.js. In očitno niso prepovedali ničesar drugega. Takoj ko se prikaže NetworkPolicy, se vsi izbirniki, omenjeni v njem, začnejo izolirati, razen če ni drugače določeno. Vendar pravila izolacije ne veljajo za druge objekte, ki jih izbirnik ne pokriva.

Primer uporablja apiVersion Kubernetes kot nalašč, vendar vam nič ne preprečuje, da bi ga uporabljali istoimenski vir iz dostave Calico. Sintaksa tam je podrobnejša, zato boste morali pravilo za zgornji primer prepisati v naslednji obliki:

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

Zgoraj omenjeni konstrukti za dovoljevanje ali zavrnitev celotnega prometa prek običajnega API-ja NetworkPolicy vsebujejo konstrukte z oklepaji, ki jih je težko razumeti in si jih je težko zapomniti. Če želite v primeru Calico spremeniti logiko pravila požarnega zidu v nasprotno, preprosto spremenite action: Allow o action: Deny.

Izolacija z okoljem

Zdaj pa si predstavljajte situacijo, ko aplikacija generira poslovne metrike za zbiranje v Prometheusu in nadaljnjo analizo z uporabo Grafane. Nalaganje lahko vsebuje občutljive podatke, ki so spet privzeto javno vidni. Skrijmo te podatke pred radovednimi očmi:

Calico za mreženje v Kubernetesu: uvod in malo izkušenj

Prometheus je praviloma postavljen v ločeno storitveno okolje - v primeru bo to imenski prostor, kot je ta:

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

Polje metadata.labels izkazalo se je, da to ni bilo naključje. Kot je navedeno zgoraj, namespaceSelector (tako dobro, kot podSelector) deluje z oznakami. Če želite omogočiti prevzem meritev iz vseh podov na določenih vratih, boste morali dodati nekakšno oznako (ali vzeti iz obstoječih) in nato uporabiti konfiguracijo, kot je:

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

In če uporabljate pravilnike Calico, bo sintaksa takšna:

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

Na splošno lahko z dodajanjem tovrstnih pravilnikov za posebne potrebe zaščitite pred zlonamernimi ali naključnimi posegi v delovanje aplikacij v gruči.

Po mnenju ustvarjalcev Calico je najboljša praksa pristop »Blokiraj vse in izrecno odpri, kar potrebuješ«, dokumentiran v uradna dokumentacija (drugi sledijo podobnemu pristopu - zlasti v že omenjeni članek).

Uporaba dodatnih objektov Calico

Naj vas spomnim, da lahko prek razširjenega nabora API-jev Calico uravnavate razpoložljivost vozlišč, ne omejeno na pode. V naslednjem primeru z uporabo GlobalNetworkPolicy zmožnost posredovanja zahtev ICMP v gruči je zaprta (na primer pingi od poda do vozlišča, med podoma ali od vozlišča do IP poda):

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

V zgornjem primeru je še vedno možno, da se vozlišča gruče »dosegajo« med seboj prek ICMP. In to vprašanje je rešeno s sredstvi GlobalNetworkPolicy, uporabljeno za subjekt 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"]

Zadeva VPN

Nazadnje bom podal zelo resničen primer uporabe funkcij Calico za primer interakcije v bližini gruče, ko standardni nabor politik ni dovolj. Za dostop do spletne aplikacije odjemalci uporabljajo tunel VPN, ta dostop pa je strogo nadzorovan in omejen na določen seznam storitev, dovoljenih za uporabo:

Calico za mreženje v Kubernetesu: uvod in malo izkušenj

Odjemalci se na VPN povežejo prek standardnih vrat UDP 1194 in, ko so povezani, prejmejo poti do podomrežij gruče podov in storitev. Celotna podomrežja so potisnjena, da ne izgubite storitev med ponovnimi zagoni in spremembami naslovov.

Vrata v konfiguraciji so standardna, kar nalaga nekaj nians pri procesu konfiguriranja aplikacije in njenega prenosa v gručo Kubernetes. Na primer, v istem AWS se je LoadBalancer za UDP pojavil dobesedno konec lanskega leta na omejenem seznamu regij, NodePort pa ni mogoče uporabiti zaradi njegovega posredovanja na vseh vozliščih gruče in ni mogoče povečati števila primerkov strežnika za namene tolerance napak. Poleg tega boste morali spremeniti privzeti obseg vrat ...

Kot rezultat iskanja možnih rešitev je bila izbrana naslednja:

  1. Podi z VPN so načrtovani na vozlišče v hostNetwork, torej na dejanski IP.
  2. Storitev je objavljena zunaj skozi ClusterIP. Na vozlišču je fizično nameščen port, ki je z manjšimi zadržki dostopen od zunaj (pogojna prisotnost pravega naslova IP).
  3. Določanje vozlišča, na katerem je vrtnica, je izven obsega naše zgodbe. Rekel bom le, da lahko storitev tesno "pribijete" na vozlišče ali napišete majhno stransko storitev, ki bo spremljala trenutni IP naslov storitve VPN in urejala DNS zapise, registrirane pri odjemalcih - kdor ima dovolj domišljije.

Z vidika usmerjanja lahko enolično identificiramo odjemalca VPN po njegovem naslovu IP, ki ga izda strežnik VPN. Spodaj je primitiven primer omejevanja dostopa takega odjemalca do storitev, ki je prikazan na zgoraj omenjenem 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]

Tu je povezava z vrati 6379 strogo prepovedana, hkrati pa je ohranjeno delovanje storitve DNS, katere delovanje pogosto trpi pri pripravi pravil. Ker, kot je bilo že omenjeno, ko se izbirnik pojavi, se zanj uporabi privzeti pravilnik o zavrnitvi, razen če je določeno drugače.

Rezultati

Tako lahko z uporabo Calicovega naprednega API-ja prilagodljivo konfigurirate in dinamično spreminjate usmerjanje v gruči in okoli nje. Na splošno je njegova uporaba lahko videti kot streljanje vrabcev s topom, implementacija omrežja L3 s tuneli BGP in IP-IP pa izgleda pošastno v preprosti namestitvi Kubernetesa na ravnem omrežju ... Sicer pa je orodje videti precej izvedljivo in uporabno. .

Izolacija gruče za izpolnjevanje varnostnih zahtev morda ni vedno izvedljiva, in tu na pomoč priskoči Calico (ali podobna rešitev). Primeri, navedeni v tem članku (z manjšimi spremembami), se uporabljajo v več namestitvah naših strank v AWS.

PS

Preberite tudi na našem blogu:

Vir: www.habr.com

Dodaj komentar