Calico për rrjetin në Kubernetes: njohja dhe pak nga përvoja

Calico për rrjetin në Kubernetes: njohja dhe pak nga përvoja

Qëllimi i këtij artikulli është të njohë lexuesin me bazat e ndërveprimit rrjetor dhe menaxhimin e politikave rrjetore në Kubernetes, si dhe me një plugin të jashtëm Calico, që zgjeron mundësitë standarde. Ndërkohë, do të demonstrohet lehtësia e konfigurimit dhe disa veçori në shembuj realë nga përvoja jonë e përdorimit.

Një hyrje e shpejtë në pajisjen rrjetore të Kubernetes

Një kluster Kubernetes nuk mund të përfytyrohet pa rrjetë. Ne tashmë kemi publikuar materiale mbi bazat e tyre: "Një udhëzues i ilustruar për strukturën e rrjetit në Kubernetes» dhe "Hyrje në politikat rrjetore Kubernetes për specialistët e sigurisë».

Në kontekstin e këtij artikulli, është e rëndësishme të theksohet se për lidhshmërinë rrjetore mes kontejnerëve dhe nyjave nuk është përgjegjës vetë K8s: për këtë përdoren të gjitha llojet e plugjineve CNI (Container Networking Interface). Më shumë rreth kësaj koncepte ne kemi folur.

PĂ«r shembull, plugini mĂ« i zakonshĂ«m i tillĂ« — Flannel ofron lidhshmĂ«ri tĂ« plotĂ« rrjetore midis tĂ« gjitha nyjave tĂ« klustrit duke ngritur ura nĂ« secilĂ«n nyje, duke i caktuar njĂ« subnet. MegjithatĂ«, disponueshmĂ«ria e plotĂ« dhe e paushtruar nuk Ă«shtĂ« gjithmonĂ« e dobishme. PĂ«r tĂ« siguruar ndonjĂ« izolim minimal nĂ« kluster, Ă«shtĂ« e nevojshme tĂ« ndĂ«rhyhet nĂ« konfigurimin e firewall-it. NĂ« pĂ«rgjithĂ«si, ai i Ă«shtĂ« besuar atij tĂ« njĂ«jtĂ« CNI, e cila mund tĂ« interpretojĂ« çdo ndĂ«rhyrje tĂ« jashtme nĂ« iptables si tĂ« pasaktĂ« ose tĂ« injorojĂ« krejtĂ«sisht.

Dhe "nga fabrika" për organizimin e menaxhimit të politikave rrjetore në klusterin Kubernetes ofrohet NetworkPolicy API. Ky burim, që zgjerohet në hapësirat përkatëse të emrave, mund të përmbajë rregulla për ndarjen e qasjes nga një aplikacion në tjetrin. Ai gjithashtu lejon të konfigurojë disponueshmërinë midis pod-eve të caktuar, mjediseve (hapësirave emrash) ose blloqeve të adresave 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

Ky është një shembull jo aq primitiv i dokumentacionin zyrtar mund të shfaqë dëshira për të kuptuar logjikën e politikave rrjetërore për herë të parë. Megjithatë, do të përpiqemi ta kuptojmë parimet e zakonshme dhe metodat e trajtimit të trafikut me anë të politikave rrjetërore...

E arsyeshme, ka 2 lloje trafiku: trafiku që hyn në pod (Ingress) dhe trafiku që del prej tij (Egress).

Calico për rrjetin në Kubernetes: njohja dhe pak nga përvoja

Kështu, këto 2 kategori ndahen sipas drejtimit të lëvizjes.

Atributi tjetĂ«r i domosdoshĂ«m Ă«shtĂ« selektori; ai, pĂ«r tĂ« cilin zbatohet rregulli. Kjo mund tĂ« jetĂ« pod (apo grupi i pod’ave) ose mjedisi (dmth. hapĂ«sira emĂ«rtimi). Detaj i rĂ«ndĂ«sishĂ«m: tĂ« dyja kĂ«to lloje objektesh duhet tĂ« pĂ«rmbajnĂ« njĂ« etikĂ« (label nĂ« terminologjinĂ« Kubernetes) — ato janĂ« pikĂ«risht ato me tĂ« cilat punojnĂ« politikat.

Përveç numrit përfundimtar të selektorëve, të bashkuar me një etikë të caktuar, ekziston mundësia e shkruajtjes së rregullave si "Lejo/ndalo të gjithë" në variante të ndryshme. Për këtë përdoren struktura të tilla si:

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

— nĂ« kĂ«tĂ« shembull, tĂ« gjitha pod’ave tĂ« mjedisit u mbyllet trafiku qĂ« hyn. NjĂ« sjellje tĂ« kundĂ«rt mund ta arrihet me kĂ«tĂ« strukturĂ«:

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

Njësoj për trafikun që del:

  podSelector: {}
  policyTypes:
  - Egress

— pĂ«r ta çaktivizuar. Dhe ja se si ta aktivizojmĂ«:

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

Duke u kthyer nĂ« zgjedhjen e plugin CNI pĂ«r klasterin, ia vlen tĂ« theksohet se jo çdo plugin rrjetor mbĂ«shtet funksionimin me NetworkPolicy. PĂ«r shembull, Flannel i pĂ«rmendur tashmĂ« nuk di tĂ« konfigurojĂ« politikat rrjetore, pĂ«r çka tha qartĂ« nĂ« depo zyrtare. Po ashtu, aty Ă«shtĂ« pĂ«rmendur njĂ« alternativĂ« — projekti Open Source Calico, i cili zgjeron ndjeshĂ«m setin standard tĂ« API-ve tĂ« Kubernetes pĂ«r sa i pĂ«rket politikave rrjetore.

Calico për rrjetin në Kubernetes: njohja dhe pak nga përvoja

Njoftohet me Calico: teoria

Plugin Calico mund të përdoret në integrim me Flannel (nënprojektin Canal) ose vetë, duke mbuluar si funksionet për sigurimin e lidhjes rrjetore ashtu edhe mundësitë e menaxhimit të aksesit.

Cilat mundësi ofron përdorimi i një zgjidhjeje 'të kutisë' K8s dhe setit të API-ve nga Calico?

Ja çfarë është integruar në NetworkPolicy:

  • politikat janĂ« tĂ« kufizuara nĂ« mjedis;
  • politikat aplikohen nĂ« pod’ët e etiketuar me etiketa;
  • rregullat mund tĂ« aplikohen nĂ« pod’ët, mjediset ose nĂ«nrrjetet;
  • rregullat mund tĂ« pĂ«rmbajnĂ« protokolle, referencat e emĂ«ruara ose simbolike tĂ« porteve.

Ja se si Calico zgjerohet këto funksione:

  • politikĂ«t mund tĂ« aplikohet pĂ«r çdo objekt: pod, konteiner, makinĂ« virtuale ose ndĂ«rfaqe;
  • rregullat mund tĂ« pĂ«rmbajnĂ« njĂ« veprim tĂ« caktuar (ndalesĂ«, leje, regjistrim);
  • si qĂ«llim ose burim i rregullave mund tĂ« jetĂ« njĂ« port, njĂ« gamĂ« portesh, protokollet, atribute HTTP ose ICMP, IP ose subnet (gjen 4 ose 6), çdo selektor (nodash, hostesh, mjedisesh);
  • pĂ«r mĂ« tepĂ«r, Ă«shtĂ« e mundur tĂ« rregullohet kalimi i trafikut me ndihmĂ«n e konfigurimeve DNAT dhe politikave tĂ« kalimit tĂ« trafikut.

Komitetet e para nĂ« GitHub nĂ« repo-n Calico datojnĂ« nga korriku i vitit 2016, dhe tashmĂ« pas njĂ« viti projekti arriti pozita tĂ« liderit nĂ« organizimin e lidhjes rrjetore Kubernetes — kjo dĂ«shmohet, pĂ«r shembull, nga rezultatet e anketĂ«s, tĂ« realizuar nga The New Stack:

Calico për rrjetin në Kubernetes: njohja dhe pak nga përvoja

Shumë zgjidhje të mëdha të menaxhuara me K8s, si Amazon EKS, Azure AKS, Google GKE dhe të tjerë, filluan të rekomandojnë përdorimin e tij.

Sa i përket performancës, këtu gjithçka është e shkëlqyer. Gjatë testimit të produktit të saj, ekipi zhvillues i Calico demonstroi tregues astronomik, duke lansuar mbi 50000 kontejnerë në 500 node fizik me shpejtësinë e krijimit të 20 kontejnerëve në sekondë. Nuk janë identifikuar probleme në shkallëzim. Këto rezultate u shpallën tashmë në njoftimin e versionit të parë. Studi të pavarura, të drejtuara drejt kapacitetit dhe vëllimeve të konsumit të burimeve, gjithashtu konfirmojnë performancën e Calico, e cila praktikisht nuk i shpëton Flannel-it. Për shembull:

Calico për rrjetin në Kubernetes: njohja dhe pak nga përvoja

Projekti po zhvillohet shumë shpejt, mbështet përputhshmërinë në zgjidhjet e njohura të menaxhuara K8s, OpenShift, OpenStack, ka mundësi të përdoret Calico gjatë vendosjes së klasterit me ndihmën e kops, përmenden ndërtimi i rrjeteve Service Mesh (ja një shembuj përdorimi së bashku me Istio).

Praktika me Calico

Në rastin e zakonshëm të përdorimit të Kubernetes vanilje, instalimi i CNI përfshin përdorimin e skedarit calico.yaml, të shkarkuar nga faqja zyrtare, me ndihmën e kubectl apply -f.

Si rregull, versioni aktual i plugin-it është i përputhshëm me 2-3 versionet e fundit të Kubernetes: puna me versionet më të vjetra nuk testohet dhe nuk garanton. Sipas deklaratave të zhvilluesve, Calico funksionon mbi bërthamën Linux mbi 3.10 nën menaxhimin e CentOS 7, Ubuntu 16 ose Debian 8, mbi iptables ose IPVS.

Izolimi brenda mjedisit

Për një kuptim të përgjithshëm, le të shqyrtojmë një rast të thjeshtë, për të kuptuar se si ndryshojnë politikat e rrjetit në notacionin Calico nga standardet dhe si qasja ndaj hartimit të rregullave e thjeshton lexueshmërinë dhe fleksibilitetin e konfigurimit:

Calico për rrjetin në Kubernetes: njohja dhe pak nga përvoja

Në klastrin janë implementuar 2 aplikacione web: një në Node.js dhe një në PHP, - një prej të cilave përdor Redis. Për të mbyllur aksesin në Redis nga PHP, duke ruajtur lidhjen me Node.js, mjafton të aplikojmë politikën e mëposhtme:

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

Në thelb, ne kemi lejuar trafikun e ardhshëm në portin Redis nga Node.js. Dhe qartë nuk kemi ndaluar asgjë tjetër. Sapo shfaqet NetworkPolicy, të gjithë selektorët e përmendur në të fillojnë të izoloheshin, nëse nuk ceket ndryshe. Rregullat e izolimit nuk zbatohen për objekte të tjera që nuk mbulohen nga selektori.

NĂ« shembull pĂ«rdoret apiVersion tĂ« Kubernetes’it "nga kutia", por asgjĂ« nuk e pengon pĂ«rdorimin e burimit me emĂ«r tĂ« njĂ«jtĂ« nga oferta e Calico. Sintaksa atje Ă«shtĂ« mĂ« e zgjeruar, prandaj do tĂ« nevojitet tĂ« shkruhet sĂ«rish rregulli pĂ«r rastin e pĂ«rshkruar mĂ« sipĂ«r nĂ« kĂ«tĂ« formĂ«:

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

Konstruksionet e përmendura më sipër për të lejuar ose ndaluar të gjithë trafikun përmes API-së standarde të NetworkPolicy kanë struktura komplekse për t'u kuptuar dhe memorizuar me kllapa. Në rastin e Calico, për të ndryshuar logjikën e funksionimit të rregullit të firewall-it në të kundërt, mjafton të ndryshoni action: Allow në action: Deny.

Izolimi sipas mjediseve

Tani le të imagjinojmë një situatë, kur aplikacioni gjeneron metrika biznesi për t'u mbledhur në Prometheus dhe për analizë të mëtejshme përmes Grafana. Në shkarkim mund të përmbahen të dhëna të ndjeshme, të cilat përdefault janë sërish të qasshme për publikun. Le t'i mbyllim këto të dhëna nga sytë e huaj:

Calico për rrjetin në Kubernetes: njohja dhe pak nga përvoja

Prometheus, si rregull, shpesh është i vendosur në një mjedis shërbimi të veçantë - në këtë shembull do të jetë namespace i tipit të mëposhtëm:

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

Fusha metadata.labels këtu doli të mos ishte rastësi. Siç u përmend më sipër, namespaceSelector (si dhe podSelector) operon me etiketime. Prandaj, për të lejuar marrjen e metrikave nga të gjitha pod'ët në një port të caktuar, do të duhet të shtoni ndonjë etikë (ose të merrni nga ato ekzistuese), dhe pastaj të aplikoni një konfigurim si:

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

Ndërsa në rastin e përdorimit të politikave Calico, sintaksisi do të jetë kështu:

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

Në tërësi, duke shtuar politika të këtij lloji për nevoja specifike, është e mundur të mbrohen nga ndërhyrjet keqdashëse ose aksidentale në funksionimin e aplikacioneve në klaster.

Praktika më e mirë, sipas krijuesve të Calico, është qasja 'Ndalo gjithçka dhe hap qartë atë që është e nevojshme', e shënuar në dokumentacionin zyrtar (qasje e ngjashme ndjekin edhe të tjerët - përkatësisht në artikullin e përmendur më parë).

Përdorimi i objekteve të tjera Calico

Më kujtohet se përmes një grupi të zgjeruar API, Calico mund të rregullojë disponueshmërinë e nyjave, pa u kufizuar në pod'ët. Në shembullin e mëposhtëm me GlobalNetworkPolicy mbyllet mundësia e kalimit të kërkesave ICMP në klaster (për shembull, ping nga pod'i në nyjë, midis pod'ëve ose nga nyja në IP-në e pod'it):

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

Në rastin e mësipërm, mbetet mundësia që nyjat e klasterit të 'arrijnë' njëra-tjetrën përmes ICMP. Dhe ky problem zgjidhet përmes GlobalNetworkPolicy, e aplikuar në entitetin 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"]

Rasti me VPN

Më në fund, do të jap një shembull krejtësisht realist të përdorimit të funksioneve të Calico për rastin e ndërveprimit pranë klasterit, kur grupi standard i politikave nuk është i mjaftueshëm. Për akses në aplikacionin web nga klientët përdoret një tunel VPN, dhe ky akses kontrollohet dhe kufizohet rreptësisht nga një listë e veçantë e shërbimeve të lejuara për t'u përdorur:

Calico për rrjetin në Kubernetes: njohja dhe pak nga përvoja

Klientët lidhen me VPN përmes portit standard UDP 1194 dhe gjatë lidhjes marrin rrugët për subnetet e klastereve të pod'ave dhe shërbimeve. Subnetet dërgohen tërësisht, për të mos humbur shërbimet gjatë rinisjeve dhe ndërrimit të adresave.

Porti në konfigurim është standard, që imponon disa nuanca në procesin e konfigurimit të aplikacionit dhe transferimit të tij në klasterin Kubernetes. Për shembull, në AWS LoadBalancer për UDP u shfaq vetëm në fund të vitit të kaluar në një listë të përmbajtur të rajoneve, dhe NodePort nuk mund të përdoret për shkak se kalon në të gjitha nyjat e klasterit dhe nuk është e mundur të shkallëzohet numri i instancave të serverëve për qëllime qëndrore. Plus, do të duhet të ndryshohet diapazoni i porteve, i zgjedhur nga default...

Si rezultat i shqyrtimit të zgjidhjeve të mundshme, u zgjodh e ardhmja e mëposhtme:

  1. Pod’ët me VPN planifikohen nĂ« nyjĂ« nĂ« modin hostNetwork, qĂ« do tĂ« thotĂ« nĂ« IP-nĂ« faktike.
  2. Shërbimi publikohet përjashtas përmes ClusterIP. Në nyje fizikisht ngrihet një port, i cili është i aksesueshëm nga jashtë me disa rezervime (prania e një adrese reale IP).
  3. PĂ«rcaktimi i nyjĂ«s, ku Ă«shtĂ« ngritur podi, Ă«shtĂ« jashtĂ« temĂ«s tonĂ«. Do tĂ« them vetĂ«m se mund tĂ« "ngjisim" shĂ«rbimin nĂ« nyje ose tĂ« shkruajmĂ« njĂ« shĂ«rbim tĂ« vogĂ«l sidecar, i cili do tĂ« monitorojĂ« IP-nĂ« aktuale tĂ« shĂ«rbimit VPN dhe do tĂ« rregullojĂ« rekordet DNS tĂ« regjistruara te klientĂ«t — sipas imagjinatĂ«s sĂ« secilit.

Nga perspektiva e rrugĂ«zimit, ne mund ta identifikojmĂ« qartĂ« klientin pĂ«rmes VPN sipas IP-sĂ« sĂ« tij, e cila i jepet nga serveri VPN. MĂ« poshtĂ« — njĂ« shembull elementar i kufizimit tĂ« aksesit tĂ« kĂ«tij klienti nĂ« shĂ«rbime, ilustruar nĂ« Redis-in e pĂ«rmendur mĂ« sipĂ«r:

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]

Këtu është rreptësisht e ndaluar lidhja në portin 6379, por në të njëjtën kohë është e ruajtur funksionimi i shërbimit DNS, funksionimi i të cilit shumë herë dëmtohet gjatë hartimit të rregullave. Sepse, siç u përmend më parë, kur shfaqet selektori, atij i aplikohet politika ndaluese me default, nëse nuk është përcaktuar ndryshe.

Përfundime

Kështu, me anë të API-së së zgjeruar Calico, mund të konfigurohet në mënyrë fleksibile dhe të ndryshohet dinamikisht rrugëzimi në klaster dhe rreth tij. Në përgjithësi, përdorimi i tij mund të duket si të gjuash me top nga një armik i vogël, ndërsa implementimi i rrjetit L3 me tunelimin BGP dhe IP-IP duket monstruoz në një instalim të thjeshtë Kubernetes në një rrjet të sheshtë... Megjithatë, përsa i përket të tjerave, instrumenti duket mjaft i zbatueshëm dhe i dobishëm.

Izolimi i klasterit për të përmbushur kërkesat e sigurisë nuk mund të realizohet gjithmonë, dhe pikërisht në këto raste vjen në ndihmë Calico (ose një zgjidhje të ngjashme). Shembujt e dhënë në artikull (me disa modifikime të vogla) përdoren në disa instalime të klientëve tanë në AWS.

P.S.

Lexoni gjithashtu në blogun tonë:

Burimi: habr.com

Blini hosting tĂ« besueshĂ«m pĂ«r faqe interneti me mbrojtje nga DDoS, serverĂ« VPS VDS đŸ”„ Blini hosting tĂ« besueshĂ«m pĂ«r faqe interneti me mbrojtje nga DDoS, serverĂ« VPS VDS | ProHoster