Calico vir netwerk in Kubernetes: 'n inleiding en 'n bietjie ervaring

Calico vir netwerk in Kubernetes: 'n inleiding en 'n bietjie ervaring

Die doel van die artikel is om die leser bekend te stel aan die basiese beginsels van netwerkvorming en die bestuur van netwerkbeleide in Kubernetes, sowel as die derdeparty Calico-inprop wat standaardvermoëns uitbrei. Langs die pad sal die gemak van konfigurasie en sommige kenmerke gedemonstreer word deur werklike voorbeelde uit ons bedryfservaring te gebruik.

'n Vinnige inleiding tot Kubernetes-netwerktoestel

'n Kubernetes-kluster kan nie sonder 'n netwerk voorgestel word nie. Ons het reeds materiaal oor hul basiese beginsels gepubliseer: "'n Geïllustreerde gids tot netwerkvorming in Kubernetes"En"'n Inleiding tot Kubernetes-netwerkbeleide vir sekuriteitspersoneel".

In die konteks van hierdie artikel is dit belangrik om daarop te let dat K8s self nie verantwoordelik is vir netwerkverbinding tussen houers en nodusse nie: hiervoor is verskeie CNI-inproppe (Container-netwerkkoppelvlak). Meer oor hierdie konsep ons hulle het my ook vertel.

Byvoorbeeld, die algemeenste van hierdie inproppe is flanel - verskaf volledige netwerkverbinding tussen alle groepknooppunte deur brûe op elke nodus te verhoog en 'n subnet daaraan toe te wys. Volledige en ongereguleerde toeganklikheid is egter nie altyd voordelig nie. Om 'n soort minimale isolasie in die groepie te verskaf, is dit nodig om in te gryp in die konfigurasie van die firewall. In die algemene geval word dit onder die beheer van dieselfde CNI geplaas, en daarom kan enige derdeparty-intervensies in iptables verkeerd geïnterpreteer of heeltemal geïgnoreer word.

En "buite die boks" vir die organisering van netwerkbeleidbestuur in 'n Kubernetes-kluster word voorsien NetworkPolicy API. Hierdie hulpbron, versprei oor geselekteerde naamruimtes, kan reëls bevat om toegang van een toepassing na 'n ander te onderskei. Dit laat jou ook toe om toeganklikheid tussen spesifieke peule, omgewings (naamruimtes) of blokke IP-adresse op te stel:

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 nie die mees primitiewe voorbeeld van amptelike dokumentasie kan eens en vir altyd die begeerte ontmoedig om die logika van hoe netwerkbeleide werk te verstaan. Ons sal egter steeds probeer om die basiese beginsels en metodes van die verwerking van verkeersvloei met behulp van netwerkbeleide te verstaan ​​...

Dit is logies dat daar 2 tipes verkeer is: die ingang van die peul (Ingress) en uitgaan daarvan (Egress).

Calico vir netwerk in Kubernetes: 'n inleiding en 'n bietjie ervaring

Eintlik word politiek in hierdie 2 kategorieë verdeel op grond van die rigting van beweging.

Die volgende vereiste eienskap is 'n keurder; die een op wie die reël van toepassing is. Dit kan 'n peul (of 'n groep peule) of 'n omgewing (d.w.s. 'n naamruimte) wees. 'n Belangrike detail: beide tipes van hierdie voorwerpe moet 'n etiket bevat (etiket in Kubernetes-terminologie) - dit is dié waarmee politici werk.

Benewens 'n eindige aantal keurders wat deur 'n soort etiket verenig word, is dit moontlik om reëls soos "Laat alles/almal toe/ontken" in verskillende variasies te skryf. Vir hierdie doel word konstruksies van die vorm gebruik:

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

- in hierdie voorbeeld word alle peule in die omgewing geblokkeer van inkomende verkeer. Die teenoorgestelde gedrag kan bereik word met die volgende konstruksie:

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

Net so vir uitgaande:

  podSelector: {}
  policyTypes:
  - Egress

- om dit af te skakel. En hier is wat om in te sluit:

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

Om terug te keer na die keuse van 'n CNI-inprop vir 'n groepering, is dit die moeite werd om daarop te let nie elke netwerkinprop ondersteun NetworkPolicy nie. Byvoorbeeld, die reeds genoemde Flannel weet nie hoe om netwerkbeleide op te stel nie, wat dit word direk gesê in die amptelike bewaarplek. 'n Alternatief word ook daar genoem - 'n Oopbronprojek Calico, wat die standaardstel Kubernetes API's aansienlik uitbrei in terme van netwerkbeleide.

Calico vir netwerk in Kubernetes: 'n inleiding en 'n bietjie ervaring

Leer ken Calico: teorie

Die Calico-inprop kan gebruik word in integrasie met Flannel (subprojek Canal) of onafhanklik, wat beide netwerkverbindings en beskikbaarheidsbestuurvermoëns dek.

Watter geleenthede bied die gebruik van die K8's "boks"-oplossing en die API-stel van Calico?

Hier is wat in NetworkPolicy ingebou is:

  • politici word beperk deur die omgewing;
  • beleide word toegepas op peule wat met etikette gemerk is;
  • reëls kan toegepas word op peule, omgewings of subnette;
  • reëls kan protokolle, benoemde of simboliese poortspesifikasies bevat.

Hier is hoe Calico hierdie funksies uitbrei:

  • beleide kan op enige voorwerp toegepas word: peul, houer, virtuele masjien of koppelvlak;
  • reëls kan 'n spesifieke handeling bevat (verbod, toestemming, aanteken);
  • die teiken of bron van reëls kan 'n poort, 'n reeks poorte, protokolle, HTTP- of ICMP-kenmerke, IP of subnet (4de of 6de generasie), enige kiesers (nodes, gashere, omgewings) wees;
  • Boonop kan u die deurgang van verkeer reguleer deur gebruik te maak van DNAT-instellings en verkeersaanstuurbeleide.

Die eerste commits op GitHub in die Calico-bewaarplek dateer terug na Julie 2016, en 'n jaar later het die projek 'n leidende posisie ingeneem in die organisering van Kubernetes-netwerkverbindings - dit word byvoorbeeld bewys deur die opnameresultate, gelei deur The New Stack:

Calico vir netwerk in Kubernetes: 'n inleiding en 'n bietjie ervaring

Baie groot bestuurde oplossings met K8's, soos Amazon EX, Azure AKS, Google GKE en ander het dit begin aanbeveel vir gebruik.

Wat prestasie betref, alles is puik hier. Deur hul produk te toets, het die Calico-ontwikkelingspan astronomiese prestasie gedemonstreer deur meer as 50000 500 houers op 20 fisiese nodusse te laat loop met 'n skeppingstempo van XNUMX houers per sekonde. Geen probleme is met skaal geïdentifiseer nie. Sulke resultate aangekondig is reeds by die aankondiging van die eerste weergawe. Onafhanklike studies wat op deurset en hulpbronverbruik fokus, bevestig ook dat Calico se prestasie amper so goed soos Flannel s'n is. Byvoorbeeld:

Calico vir netwerk in Kubernetes: 'n inleiding en 'n bietjie ervaring

Die projek ontwikkel baie vinnig, dit ondersteun werk in gewilde oplossingsbestuurde K8's, OpenShift, OpenStack, dit is moontlik om Calico te gebruik wanneer 'n groepering ontplooi word skop, daar is verwysings na die konstruksie van Service Mesh-netwerke (hier is 'n voorbeeld gebruik in samewerking met Istio).

Oefen met Calico

In die algemene geval van die gebruik van vanielje Kubernetes, kom die installering van CNI neer op die gebruik van die lêer calico.yaml, afgelaai vanaf die amptelike webwerf, via kubectl apply -f.

As 'n reël is die huidige weergawe van die inprop versoenbaar met die nuutste 2-3 weergawes van Kubernetes: werking in ouer weergawes word nie getoets nie en word nie gewaarborg nie. Volgens die ontwikkelaars loop Calico op Linux-pitte bo 3.10 met CentOS 7, Ubuntu 16 of Debian 8, bo en behalwe iptables of IPVS.

Isolasie binne die omgewing

Vir 'n algemene begrip, kom ons kyk na 'n eenvoudige geval om te verstaan ​​hoe netwerkbeleide in die Calico-notasie verskil van standaards en hoe die benadering tot die skep van reëls hul leesbaarheid en konfigurasiebuigsaamheid vereenvoudig:

Calico vir netwerk in Kubernetes: 'n inleiding en 'n bietjie ervaring

Daar is 2 webtoepassings wat in die groepering ontplooi is: in Node.js en PHP, waarvan een Redis gebruik. Om toegang tot Redis vanaf PHP te blokkeer, terwyl u verbinding met Node.js behou, pas net die volgende beleid toe:

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

Ons het in wese inkomende verkeer na die Redis-hawe vanaf Node.js toegelaat. En hulle het duidelik niks anders verbied nie. Sodra Netwerkbeleid verskyn, begin alle keurders wat daarin genoem word, geïsoleer word, tensy anders gespesifiseer. Die isolasiereëls is egter nie van toepassing op ander voorwerpe wat nie deur die keurder gedek word nie.

Die voorbeeld gebruik apiVersion Kubernetes uit die boks, maar niks verhoed jou om dit te gebruik nie hulpbron met dieselfde naam van die Calico-aflewering. Die sintaksis daar is meer gedetailleerd, so jy sal die reël vir die bogenoemde geval in die volgende vorm moet herskryf:

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

Die bogenoemde konstrukte om alle verkeer deur die gewone NetworkPolicy API toe te laat of te weier, bevat konstrukte met hakies wat moeilik is om te verstaan ​​en te onthou. In die geval van Calico, verander net om die logika van 'n firewall-reël na die teenoorgestelde te verander action: Allow op action: Deny.

Isolasie deur omgewing

Stel jou nou 'n situasie voor waar 'n toepassing besigheidsstatistieke genereer vir insameling in Prometheus en verdere ontleding deur Grafana te gebruik. Die oplaai kan sensitiewe data bevat, wat weer by verstek publiek sigbaar is. Kom ons verberg hierdie data vir gierige oë:

Calico vir netwerk in Kubernetes: 'n inleiding en 'n bietjie ervaring

Prometheus word as 'n reël in 'n aparte diensomgewing geplaas - in die voorbeeld sal dit 'n naamruimte soos hierdie wees:

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

Veld metadata.labels dit blyk geen toeval te wees nie. Soos bogenoem, namespaceSelector (sowel as podSelector) werk met etikette. Daarom, om toe te laat dat metrieke van alle peule op 'n spesifieke poort geneem word, sal jy 'n soort etiket moet byvoeg (of van bestaandes neem), en dan 'n konfigurasie moet toepas soos:

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 jy Calico-beleide gebruik, sal die sintaksis soos volg wees:

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

Oor die algemeen, deur hierdie soort beleide vir spesifieke behoeftes by te voeg, kan jy beskerm teen kwaadwillige of toevallige inmenging in die werking van toepassings in die groepering.

Die beste praktyk, volgens die skeppers van Calico, is die "Blokkeer alles en maak uitdruklik oop wat jy nodig het" benadering, gedokumenteer in amptelike dokumentasie (ander volg 'n soortgelyke benadering - veral in reeds genoemde artikel).

Gebruik bykomende Calico-voorwerpe

Laat ek jou daaraan herinner dat jy deur die uitgebreide stel Calico API's die beskikbaarheid van nodusse kan reguleer, nie beperk tot peule nie. In die volgende voorbeeld gebruik GlobalNetworkPolicy die vermoë om ICMP-versoeke in die groepering deur te gee, is gesluit (byvoorbeeld, pings van 'n peul na 'n nodus, tussen peule of van 'n nodus na 'n IP-peul):

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

In die bogenoemde geval is dit steeds moontlik vir cluster nodusse om "uit te reik" na mekaar via ICMP. En hierdie probleem word deur middel opgelos GlobalNetworkPolicy, toegepas op 'n 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"]

Die VPN-saak

Ten slotte sal ek 'n baie werklike voorbeeld gee van die gebruik van Calico-funksies vir die geval van byna-groep interaksie, wanneer 'n standaard stel beleide nie genoeg is nie. Kliënte gebruik 'n VPN-tonnel om toegang tot die webtoepassing te verkry, en hierdie toegang word streng beheer en beperk tot 'n spesifieke lys dienste wat toegelaat word vir gebruik:

Calico vir netwerk in Kubernetes: 'n inleiding en 'n bietjie ervaring

Kliënte koppel aan die Skynprivaatnetwerk via standaard UDP-poort 1194 en ontvang roetes na die groepsubnette van peule en dienste, wanneer hulle gekoppel is. Hele subnette word gedruk om nie dienste tydens herbegin en adresveranderinge te verloor nie.

Die poort in die konfigurasie is standaard, wat 'n paar nuanses plaas op die proses om die toepassing op te stel en dit na die Kubernetes-groep oor te dra. Byvoorbeeld, in dieselfde AWS het LoadBalancer vir UDP letterlik aan die einde van verlede jaar in 'n beperkte lys streke verskyn, en NodePort kan nie gebruik word nie as gevolg van die aanstuur daarvan op alle cluster nodusse en dit is onmoontlik om die aantal bedienergevalle vir fouttoleransie doeleindes. Boonop sal u die verstekreeks van poorte moet verander ...

As gevolg van die soektog deur moontlike oplossings, is die volgende gekies:

  1. Peule met VPN word per nodus in geskeduleer hostNetwork, dit wil sê na die werklike IP.
  2. Die diens word buite deur geplaas ClusterIP. 'n Poort is fisies op die nodus geïnstalleer, wat van buite af toeganklik is met geringe besprekings (voorwaardelike teenwoordigheid van 'n regte IP-adres).
  3. Die bepaling van die nodus waarop die peulroos is buite die bestek van ons storie. Ek sal net sê dat jy die diens na 'n nodus kan koppel of 'n klein syspandiens kan skryf wat die huidige IP-adres van die VPN-diens sal monitor en die DNS-rekords wat by kliënte geregistreer is, sal wysig - wie ook al genoeg verbeelding het.

Vanuit 'n roeteperspektief kan ons 'n VPN-kliënt uniek identifiseer deur sy IP-adres wat deur die VPN-bediener uitgereik is. Hieronder is 'n primitiewe voorbeeld van die beperking van so 'n kliënt se toegang tot dienste, geïllustreer op die bogenoemde 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]

Hier is dit streng verbode om aan poort 6379 te koppel, maar terselfdertyd word die werking van die DNS-diens bewaar, waarvan die funksionering dikwels ly wanneer reëls opgestel word. Omdat, soos voorheen genoem, wanneer 'n kieser verskyn, word die verstek weieringbeleid daarop toegepas, tensy anders gespesifiseer.

Resultate van

Met behulp van Calico se gevorderde API kan jy dus buigsaam opstel en roetering in en om die groepering dinamies verander. Oor die algemeen kan die gebruik daarvan lyk soos om mossies met 'n kanon te skiet, en die implementering van 'n L3-netwerk met BGP- en IP-IP-tonnels lyk monsteragtig in 'n eenvoudige Kubernetes-installasie op 'n plat netwerk... Andersins lyk die instrument redelik lewensvatbaar en bruikbaar .

Om 'n groepering te isoleer om aan sekuriteitsvereistes te voldoen, is dalk nie altyd haalbaar nie, en dit is waar Calico (of 'n soortgelyke oplossing) tot die redding kom. Die voorbeelde wat in hierdie artikel gegee word (met geringe wysigings) word in verskeie installasies van ons kliënte in AWS gebruik.

PS

Lees ook op ons blog:

Bron: will.com

Voeg 'n opmerking