Calico foar netwurken yn Kubernetes: ynlieding en in bytsje ûnderfining

Calico foar netwurken yn Kubernetes: ynlieding en in bytsje ûnderfining

It doel fan it artikel is om de lêzer yn te fieren nei de basis fan netwurking en it behearen fan netwurkbelied yn Kubernetes, lykas ek de Calico-plugin fan tredden dy't standertmooglikheden útwreidet. Underweis sille it gemak fan konfiguraasje en guon funksjes wurde oantoand mei echte foarbylden út ús bedriuwsûnderfining.

In rappe yntroduksje ta Kubernetes netwurkapparaat

In Kubernetes-kluster kin net foarsteld wurde sûnder in netwurk. Wy hawwe al materialen publisearre oer har basis: "In yllustrearre gids foar netwurken yn Kubernetes"En"In yntroduksje ta Kubernetes netwurkbelied foar befeiligingsprofessionals".

Yn it ramt fan dit artikel is it wichtich om te merken dat K8s sels net ferantwurdlik is foar netwurkferbining tusken konteners en knooppunten: hjirfoar binne ferskate CNI plugins (Container netwurkynterface). Mear oer dit konsept we se fertelden my ek.

Bygelyks, de meast foarkommende fan dizze plugins is Flannel - biedt folsleine netwurkferbining tusken alle klusterknooppunten troch brêgen op elke knooppunt te ferheegjen, dêr in subnet oan te jaan. Folsleine en net-regulearre tagonklikens is lykwols net altyd foardielich. Om in soarte fan minimale isolaasje yn it kluster te leverjen, is it nedich om yn te gripen yn 'e konfiguraasje fan' e brânmuorre. Yn it algemiene gefal wurdt it ûnder de kontrôle fan deselde CNI pleatst, en dêrom kinne yntervinsjes fan tredden yn iptables ferkeard ynterpretearre wurde of hielendal negeare.

En "out of the box" foar it organisearjen fan netwurkbeliedbehear yn in Kubernetes-kluster wurdt levere NetworkPolicy API. Dizze boarne, ferdield oer selektearre nammeromten, kin regels befetsje om tagong te ûnderskieden fan de iene applikaasje nei de oare. It lit jo ek tagonklikens konfigurearje tusken spesifike pods, omjouwings (nammeromten) of blokken fan IP-adressen:

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

Dit is net it meast primitive foarbyld fan offisjele dokumintaasje kin ienris en foar altyd de winsk ûntmoedigje om de logika te begripen fan hoe't netwurkbelied wurket. Wy sille lykwols noch besykje de basisprinsipes en metoaden te begripen foar it ferwurkjen fan ferkearsstreamen mei netwurkbelied ...

It is logysk dat d'r 2 soarten ferkear binne: it ynfieren fan 'e pod (Ingress) en it útgean (Egress).

Calico foar netwurken yn Kubernetes: ynlieding en in bytsje ûnderfining

Eigentlik is polityk ferdield yn dizze 2 kategoryen basearre op 'e rjochting fan beweging.

De folgjende fereaske attribút is in selector; dejinge op wa't de regel jildt. Dit kin in pod (of in groep pods) of in omjouwing (dus in nammeromte) wêze. In wichtich detail: beide soarten fan dizze objekten moatte in label befetsje (etiket yn Kubernetes terminology) - dit binne dejingen wêrmei politisy operearje.

Neist in einich oantal selectors, ferienige troch in soarte fan label, is it mooglik om te skriuwen regels lykas "Alles tastean / wegerje / elkenien" yn ferskillende fariaasjes. Foar dit doel wurde konstruksjes fan 'e foarm brûkt:

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

- yn dit foarbyld binne alle pods yn 'e omjouwing blokkearre foar ynkommend ferkear. It tsjinoerstelde gedrach kin berikt wurde mei de folgjende konstruksje:

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

Lykas foar útgeande:

  podSelector: {}
  policyTypes:
  - Egress

- om it út te skeakeljen. En hjir is wat te befetsjen:

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

Werom nei de kar fan in CNI plugin foar in kluster, it is de muoite wurdich opskriuwen dat net elke netwurk plugin stipet NetworkPolicy. Bygelyks, de al neamde Flannel wit net hoe te konfigurearjen netwurk belied, hokker it wurdt sein direkt yn 'e offisjele repository. Dêr wurdt ek in alternatyf neamd - in Open Source-projekt Calico, dy't de standertset fan Kubernetes API's signifikant útwreidet yn termen fan netwurkbelied.

Calico foar netwurken yn Kubernetes: ynlieding en in bytsje ûnderfining

Calico te kennen: teory

De Calico-plugin kin brûkt wurde yn yntegraasje mei Flannel (subprojekt Kanaal) of selsstannich, dy't sawol netwurkferbining as beskikberensbehearmooglikheden dekke.

Hokker kânsen biedt it brûken fan de K8s "boxed" oplossing en de API-set fan Calico?

Hjir is wat yn NetworkPolicy ynboud is:

  • politisy wurde beheind troch it miljeu;
  • belied wurdt tapast op pods markearre mei labels;
  • regels kinne tapast wurde op pods, omjouwings of subnets;
  • regels kinne befetsje protokollen, neamd of symboalyske haven spesifikaasjes.

Hjir is hoe't Calico dizze funksjes útwreidet:

  • belied kin tapast wurde op elk objekt: pod, kontener, firtuele masine of ynterface;
  • regels kinne in spesifike aksje befetsje (ferbod, tastimming, logging);
  • it doel of boarne fan regels kin in poarte wêze, in berik fan havens, protokollen, HTTP- of ICMP-attributen, IP of subnet (4e of 6e generaasje), alle seleksjes (knooppunten, hosts, omjouwings);
  • Derneist kinne jo de trochgong fan ferkear regelje mei DNAT-ynstellingen en ferkearsferkearbelied.

De earste commits op GitHub yn it Calico-repository datearje werom nei july 2016, en in jier letter naam it projekt in liedende posysje yn it organisearjen fan Kubernetes netwurkferbining - dit wurdt bygelyks bewiisd troch de resultaten fan 'e enkête, útfierd troch The New Stack:

Calico foar netwurken yn Kubernetes: ynlieding en in bytsje ûnderfining

In protte grutte managed oplossings mei K8s, lykas Amazon EKS, Azure AKS, Google GKE en oaren begûnen it oan te rieden foar gebrûk.

Wat de prestaasjes oanbelanget, is alles hjir geweldich. By it testen fan har produkt hat it Calico-ûntwikkelingsteam astronomyske prestaasjes oantoand, mei mear dan 50000 konteners op 500 fysike knopen mei in skeppingsrate fan 20 konteners per sekonde. Gjin problemen waarden identifisearre mei skaalfergrutting. Sokke resultaten waarden oankundige al by de oankundiging fan de earste ferzje. Unôfhinklike stúdzjes dy't rjochte binne op trochstreaming en boarneferbrûk befêstigje ek dat de prestaasjes fan Calico hast like goed binne as dy fan Flannel. Bygelyks:

Calico foar netwurken yn Kubernetes: ynlieding en in bytsje ûnderfining

It projekt ûntwikkelet heul fluch, it stipet wurk yn populêre oplossings beheard K8s, OpenShift, OpenStack, it is mooglik om Calico te brûken by it ynsetten fan in kluster mei kops, der binne ferwizings nei de bou fan Service Mesh-netwurken (hjir is in foarbyld brûkt yn kombinaasje mei Istio).

Oefenje mei Calico

Yn it algemiene gefal fan it brûken fan vanille Kubernetes, it ynstallearjen fan CNI komt del op it brûken fan it bestân calico.yaml, ynladen fan 'e offisjele webside, troch te brûken kubectl apply -f.

As regel is de hjoeddeistige ferzje fan it plugin kompatibel mei de lêste 2-3 ferzjes fan Kubernetes: operaasje yn âldere ferzjes wurdt net hifke en wurdt net garandearre. Neffens de ûntwikkelders rint Calico op Linux kernels boppe 3.10 mei CentOS 7, Ubuntu 16 of Debian 8, boppe op iptables of IPVS.

Isolaasje binnen it miljeu

Foar in algemien begryp, litte wy nei in ienfâldige saak sjen om te begripen hoe't netwurkbelied yn 'e Calico-notaasje ferskille fan standert en hoe't de oanpak foar it meitsjen fan regels har lêsberens en konfiguraasjefleksibiliteit ferienfâldigt:

Calico foar netwurken yn Kubernetes: ynlieding en in bytsje ûnderfining

D'r binne 2 webapplikaasjes ynset yn it kluster: yn Node.js en PHP, wêrfan ien Redis brûkt. Om tagong ta Redis fan PHP te blokkearjen, wylst jo ferbining mei Node.js behâlde, tapasse gewoan it folgjende belied:

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

Yn essinsje hawwe wy ynkommende ferkear tastien nei de Redis-haven fan Node.js. En se hawwe dúdlik neat oars ferbean. Sadree't NetworkPolicy ferskynt, begjinne alle selectors neamd yn it isolearre, útsein as oars oantsjutte. De isolaasjeregels binne lykwols net fan tapassing op oare objekten dy't net binne bedekt troch de selector.

It foarbyld brûkt apiVersion Kubernetes út 'e doaze, mar neat foarkomt jo út in gebrûk it boarne mei deselde namme út de Calico levering. De syntaksis dêr is mear detaillearre, dus jo moatte de regel foar it boppesteande gefal opnij skriuwe yn 'e folgjende foarm:

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

De hjirboppe neamde konstruksjes foar it tastean of wegerjen fan alle ferkear fia de reguliere NetworkPolicy API befetsje konstruksjes mei heakjes dy't lestich te begripen en te ûnthâlden binne. Yn it gefal fan Calico, feroarje de logika fan in firewall regel nei it tsjinoerstelde, gewoan feroarje action: Allow op action: Deny.

Isolaasje troch miljeu

Stel jo no in situaasje foar wêr't in applikaasje saaklike metriken genereart foar kolleksje yn Prometheus en fierdere analyse mei Grafana. De upload kin gefoelige gegevens befetsje, dy't standert wer iepenbier te sjen binne. Litte wy dizze gegevens ferbergje foar nijsgjirrige eagen:

Calico foar netwurken yn Kubernetes: ynlieding en in bytsje ûnderfining

Prometheus wurdt yn 'e regel pleatst yn in aparte tsjinstomjouwing - yn it foarbyld sil it in nammeromte wêze as dit:

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

fjild metadata.labels dit bliek gjin tafal te wêzen. Lykas hjirboppe neamde, namespaceSelector (lykas podSelector) wurket mei labels. Dêrom, om metriken te nimmen fan alle pods op in spesifike poarte, moatte jo in soarte fan label tafoegje (of nimme fan besteande), en dan in konfiguraasje tapasse lykas:

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

En as jo Calico-belied brûke, sil de syntaksis sa wêze:

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

Yn 't algemien kinne jo troch dizze soarten belied ta te foegjen foar spesifike behoeften, beskermje tsjin kweade of tafallige ynterferinsje yn' e wurking fan applikaasjes yn it kluster.

De bêste praktyk, neffens de makkers fan Calico, is de oanpak "Alles blokkearje en eksplisyt iepenje wat jo nedich binne", dokumintearre yn offisjele dokumintaasje (oaren folgje in ferlykbere oanpak - benammen yn al neamd artikel).

Mei help fan ekstra Calico-objekten

Lit my jo herinnerje dat troch de útwreide set fan Calico API's jo de beskikberens fan knopen kinne regelje, net beheind ta pods. Yn it folgjende foarbyld brûke GlobalNetworkPolicy de mooglikheid om ICMP-oanfragen yn it kluster troch te jaan is sluten (bygelyks pings fan in pod nei in node, tusken pods, of fan in node nei in IP-pod):

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

Yn it boppesteande gefal is it noch altyd mooglik foar klusterknooppunten om inoar te "berikke" fia ICMP. En dit probleem wurdt oplost troch middel GlobalNetworkPolicy, tapast op in entiteit 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"]

De VPN Case

Uteinlik sil ik in heul echt foarbyld jaan fan it brûken fan Calico-funksjes foar it gefal fan near-cluster ynteraksje, as in standert set fan belied net genôch is. Om tagong te krijen ta de webapplikaasje brûke kliïnten in VPN-tunnel, en dizze tagong wurdt strak kontrolearre en beheind ta in spesifike list mei tsjinsten tastien foar gebrûk:

Calico foar netwurken yn Kubernetes: ynlieding en in bytsje ûnderfining

Klanten ferbine mei de VPN fia standert UDP-poarte 1194 en, as ferbûn, ûntfange rûtes nei de klustersubnetten fan pods en tsjinsten. Hiele subnetten wurde triuwd om tsjinsten net te ferliezen by herstarten en adreswizigingen.

De haven yn 'e konfiguraasje is standert, dy't wat nuânses opleit op it proses fan it konfigurearjen fan' e applikaasje en it oerdragen nei it Kubernetes-kluster. Bygelyks, yn deselde AWS ferskynde LoadBalancer foar UDP letterlik oan 'e ein fan ferline jier yn in beheinde list mei regio's, en NodePort kin net brûkt wurde fanwegen syn trochstjoering op alle klusterknooppunten en it is ûnmooglik om it oantal servereksimplaren te skaaljen foar flater tolerânsje doelen. Plus, jo moatte it standertberik fan havens feroarje ...

As gefolch fan it sykjen nei mooglike oplossingen, waard de folgjende keazen:

  1. Pods mei VPN binne pland per knooppunt yn hostNetwork, dat is, nei de eigentlike IP.
  2. De tsjinst wurdt pleatst bûten troch ClusterIP. In poarte wurdt fysyk ynstallearre op it knooppunt, dat is tagonklik fan bûten mei lytse reservearrings (betingsten oanwêzigens fan in echt IP-adres).
  3. It bepalen fan it knooppunt wêrop de podroas is bûten it berik fan ús ferhaal. Ik sil gewoan sizze dat jo de tsjinst strak kinne "nagelje" op in knooppunt of in lytse sidecar-tsjinst skriuwe dy't it hjoeddeistige IP-adres fan 'e VPN-tsjinst kontrolearje sil en de DNS-records bewurkje registrearre by kliïnten - wa't genôch ferbylding hat.

Fanút in routingperspektyf kinne wy ​​in VPN-kliïnt unyk identifisearje troch syn IP-adres útjûn troch de VPN-tsjinner. Hjirûnder is in primityf foarbyld fan it beheinen fan de tagong fan sa'n klant ta tsjinsten, yllustrearre op de hjirboppe neamde 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]

Hjir is it strikt ferbean om te ferbinen mei poarte 6379, mar tagelyk wurdt de wurking fan 'e DNS-tsjinst bewarre bleaun, wêrfan it funksjonearjen faak lijt by it opstellen fan regels. Om't, lykas earder neamd, as in selector ferskynt, wurdt it standert wegeringsbelied dêrop tapast, útsein as oars oanjûn.

Resultaten

Sa kinne jo, mei help fan Calico's avansearre API, fleksibel konfigurearje en dynamysk feroarje routing yn en om it kluster. Yn 't algemien kin it gebrûk lykje as it sjitten fan sparrows mei in kanon, en it útfieren fan in L3-netwurk mei BGP- en IP-IP-tunnels sjocht monsterlik yn in ienfâldige Kubernetes-ynstallaasje op in plat netwurk ... .

It isolearjen fan in kluster om te foldwaan oan feiligenseasken is miskien net altyd mooglik, en dit is wêr't Calico (as in ferlykbere oplossing) ta de rêding komt. De foarbylden jûn yn dit artikel (mei lytse oanpassings) wurde brûkt yn ferskate ynstallaasjes fan ús kliïnten yn AWS.

PS

Lês ek op ús blog:

Boarne: www.habr.com

Add a comment