Calico verkostoitumiseen Kubernetesissa: esittely ja vähän kokemusta

Calico verkostoitumiseen Kubernetesissa: esittely ja vähän kokemusta

Artikkelin tarkoituksena on esitellä lukija Kubernetesin verkottumisen ja verkkokäytäntöjen hallinnan perusteisiin sekä kolmannen osapuolen Calico-laajennukseen, joka laajentaa vakioominaisuuksia. Matkan varrella konfiguroinnin helppous ja jotkut ominaisuudet tulevat esille käyttämällä todellisia esimerkkejä käyttökokemuksestamme.

Nopea johdatus Kubernetes-verkkolaitteeseen

Kubernetes-klusteria ei voi kuvitella ilman verkkoa. Olemme jo julkaisseet materiaalia heidän perusteistaan: "Kubernetesin kuvitettu verkostoitumisopas"Ja"Johdatus Kubernetes-verkkokäytäntöihin tietoturva-ammattilaisille'.

Tämän artikkelin yhteydessä on tärkeää huomata, että K8s ei itse ole vastuussa verkkoyhteyksistä säiliöiden ja solmujen välillä: tätä varten CNI-laajennukset (Container Networking Interface). Lisää tästä konseptista me kertoivat myös minulle.

Esimerkiksi yleisin näistä laajennuksista on Flanelli — tarjoaa täyden verkkoyhteyden kaikkien klusterisolmujen välillä nostamalla siltoja jokaiseen solmuun ja määrittämällä sille aliverkon. Täydellinen ja sääntelemätön saavutettavuus ei kuitenkaan aina ole hyödyllistä. Jonkinlaisen minimaalisen eristyksen aikaansaamiseksi klusterissa on tarpeen puuttua palomuurin kokoonpanoon. Yleensä se on asetettu saman CNI:n hallintaan, minkä vuoksi kaikki kolmannen osapuolen toimet iptablesissa voidaan tulkita väärin tai jättää kokonaan huomiotta.

Ja Kubernetes-klusterissa verkkopolitiikan hallinnan järjestämiseen tarjotaan "pakkauksesta". NetworkPolicy API. Tämä resurssi, joka on jaettu valittuihin nimiavaruuksiin, voi sisältää sääntöjä, jotka erottavat pääsyn sovelluksista toiseen. Sen avulla voit myös määrittää saavutettavuuden tiettyjen ryhmien, ympäristöjen (nimiavaruuksien) tai IP-osoitteiden lohkojen välillä:

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

Tämä ei ole primitiivisin esimerkki virallinen dokumentaatio voi kerta kaikkiaan lannistaa halun ymmärtää verkkokäytäntöjen toiminnan logiikkaa. Yritämme kuitenkin edelleen ymmärtää liikennevirtojen käsittelyn perusperiaatteet ja menetelmät verkkokäytäntöjen avulla...

On loogista, että on olemassa 2 tyyppistä liikennettä: sisääntulo (Ingress) ja sieltä lähtevä (Egress).

Calico verkostoitumiseen Kubernetesissa: esittely ja vähän kokemusta

Itse asiassa politiikka on jaettu näihin kahteen kategoriaan liikkeen suunnan perusteella.

Seuraava pakollinen attribuutti on valitsin; se, jota sääntö koskee. Tämä voi olla pod (tai ryhmä podeja) tai ympäristö (eli nimiavaruus). Tärkeä yksityiskohta: näiden objektien molemmissa tyypeissä on oltava tarra (etiketti Kubernetes-terminologiassa) - poliitikot toimivat näillä.

Jonkinlaisen etiketin yhdistämien rajallisten valitsimien lisäksi on mahdollista kirjoittaa sääntöjä, kuten "Salli/kiellä kaikki/kaikki" eri muunnelmissa. Tätä tarkoitusta varten käytetään muodon rakenteita:

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

— Tässä esimerkissä kaikki ympäristön kotelot on estetty saapuvalta liikenteeltä. Päinvastainen käyttäytyminen voidaan saavuttaa seuraavalla rakenteella:

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

Samoin lähteville:

  podSelector: {}
  policyTypes:
  - Egress

- sammuttaaksesi sen. Ja tässä on mitä sisällytetään:

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

Palatakseni CNI-laajennuksen valintaan klusterille, se on syytä huomata kaikki verkkolaajennukset eivät tue NetworkPolicyta. Esimerkiksi jo mainittu Flannel ei osaa määrittää verkkokäytäntöjä, mikä se sanotaan suoraan virallisessa arkistossa. Siellä mainitaan myös vaihtoehto - Open Source -projekti kalikoo, joka laajentaa merkittävästi Kubernetes-sovellusliittymien standardijoukkoa verkkokäytäntöjen suhteen.

Calico verkostoitumiseen Kubernetesissa: esittely ja vähän kokemusta

Calicoon tutustuminen: teoria

Calico-laajennusta voidaan käyttää yhdessä Flannelin kanssa (aliprojekti Kanava) tai itsenäisesti, joka kattaa sekä verkkoyhteyden että saatavuuden hallintaominaisuudet.

Mitä mahdollisuuksia K8s:n "boxed" -ratkaisun ja Calicon API-sarjan käyttö tarjoaa?

NetworkPolicyn sisäänrakennetut ominaisuudet:

  • poliitikkoja rajoittaa ympäristö;
  • käytäntöjä sovelletaan etiketeillä merkittyihin koteloihin;
  • sääntöjä voidaan soveltaa podeihin, ympäristöihin tai aliverkkoihin;
  • säännöt voivat sisältää protokollia, nimettyjä tai symbolisia porttimäärityksiä.

Näin Calico laajentaa näitä toimintoja:

  • käytäntöjä voidaan soveltaa mihin tahansa objektiin: pod, säilö, virtuaalikone tai käyttöliittymä;
  • säännöt voivat sisältää tietyn toiminnon (kielto, lupa, kirjaaminen);
  • sääntöjen kohde tai lähde voi olla portti, joukko portteja, protokollia, HTTP- tai ICMP-attribuutteja, IP tai aliverkko (4. tai 6. sukupolvi), mitkä tahansa valitsimet (solmut, isännät, ympäristöt);
  • Lisäksi voit säädellä liikenteen kulkua DNAT-asetusten ja liikenteenohjauskäytäntöjen avulla.

Ensimmäiset sitoumukset GitHubissa Calicon arkistossa ovat heinäkuussa 2016, ja vuotta myöhemmin projekti nousi johtoasemaan Kubernetes-verkkoyhteyksien järjestämisessä – tästä ovat osoituksena mm. johtajana The New Stack:

Calico verkostoitumiseen Kubernetesissa: esittely ja vähän kokemusta

Monet suuret hallitut ratkaisut K8:lla, kuten Amazon EX, Azure AKS, Google GKE ja muut alkoivat suositella sitä käyttöön.

Mitä tulee suorituskykyyn, kaikki on hienoa täällä. Testaessaan tuotettaan Calicon kehitystiimi osoitti tähtitieteellistä suorituskykyä ja käytti yli 50000 500 konttia 20 fyysisessä solmussa luomisnopeudella XNUMX konttia sekunnissa. Skaalaamisessa ei havaittu ongelmia. Sellaisia ​​tuloksia ilmoitettiin jo ensimmäisen version julkistamisen yhteydessä. Riippumattomat suoritukseen ja resurssien kulutukseen keskittyvät tutkimukset vahvistavat myös, että Calicon suorituskyky on lähes yhtä hyvä kuin Flannelin. Esimerkiksi:

Calico verkostoitumiseen Kubernetesissa: esittely ja vähän kokemusta

Projekti kehittyy erittäin nopeasti, se tukee työskentelyä suosituissa hallittavissa ratkaisuissa K8s, OpenShift, OpenStack, on mahdollista käyttää Calicoa klusterin käyttöönotossa käyttämällä potkia, on viittauksia Service Mesh -verkkojen rakentamiseen (tässä on esimerkki käytetään yhdessä Istion kanssa).

Harjoittele Calicon kanssa

Yleisessä tapauksessa vanilja Kubernetesia käytettäessä CNI:n asentaminen tarkoittaa tiedoston käyttöä calico.yaml, ladattu viralliselta verkkosivustolta, käyttämällä kubectl apply -f.

Pääsääntöisesti laajennuksen nykyinen versio on yhteensopiva Kubernetesin 2-3 uusimman version kanssa: toimintaa vanhemmissa versioissa ei testata, eikä sitä taata. Kehittäjien mukaan Calico toimii yli 3.10:n Linux-ytimillä, joissa on CentOS 7, Ubuntu 16 tai Debian 8, iptablesin tai IPVS:n lisäksi.

Eristys ympäristön sisällä

Yleisen ymmärtämisen vuoksi tarkastellaan yksinkertaista tapausta ymmärtääksemme, kuinka Calico-merkinnän verkkokäytännöt eroavat tavallisista ja kuinka sääntöjen luontitapa yksinkertaistaa niiden luettavuutta ja konfiguroinnin joustavuutta:

Calico verkostoitumiseen Kubernetesissa: esittely ja vähän kokemusta

Klusterissa on käytössä 2 verkkosovellusta: Node.js:ssä ja PHP:ssä, joista toinen käyttää Redistä. Voit estää pääsyn Redikseen PHP:stä ja säilyttää yhteyden Node.js:n kanssa noudattamalla seuraavaa käytäntöä:

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

Pohjimmiltaan sallimme saapuvan liikenteen Redis-porttiin Node.js:stä. Ja he eivät selvästikään kieltäneet mitään muuta. Heti kun NetworkPolicy tulee näkyviin, kaikki siinä mainitut valitsimet alkavat eristää, ellei toisin mainita. Eristyssäännöt eivät kuitenkaan koske muita kohteita, joita valitsin ei kata.

Esimerkki käyttää apiVersion Kubernetes pois pakkauksesta, mutta mikään ei estä sinua käyttämästä sitä samanniminen resurssi Calico-toimituksesta. Syntaksi on yksityiskohtaisempi, joten sinun on kirjoitettava sääntö yllä olevaa tapausta varten seuraavassa muodossa:

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

Yllä mainitut rakenteet kaiken liikenteen sallimiseksi tai estämiseksi tavallisen NetworkPolicy API:n kautta sisältävät suluissa olevia konstruktioita, joita on vaikea ymmärtää ja muistaa. Calicon tapauksessa palomuurisäännön logiikka päinvastaiseksi muutetaan vain action: Allow päälle action: Deny.

Eristäminen ympäristön mukaan

Kuvittele nyt tilanne, jossa sovellus luo liiketoimintamittareita Prometheuksen keräämistä varten ja Grafanan avulla tapahtuvaa analysointia varten. Lataus voi sisältää arkaluontoisia tietoja, jotka ovat taas oletuksena julkisesti nähtävissä. Piilotetaan nämä tiedot uteliailta silmiltä:

Calico verkostoitumiseen Kubernetesissa: esittely ja vähän kokemusta

Prometheus sijoitetaan pääsääntöisesti erilliseen palveluympäristöön - esimerkissä se on tällainen nimiavaruus:

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

Kenttä metadata.labels tämä ei osoittautunut sattumaksi. Kuten yllä mainittu, namespaceSelector (yhtä hyvin kuin podSelector) toimii tarrojen kanssa. Siksi, jotta mittaukset voidaan ottaa kaikista tietyn portin tyypeistä, sinun on lisättävä jonkinlainen tunniste (tai otettava olemassa olevista) ja käytettävä sitten seuraavanlaisia ​​määrityksiä:

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

Ja jos käytät Calico-käytäntöjä, syntaksi on seuraava:

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

Yleisesti ottaen lisäämällä tällaisia ​​käytäntöjä erityistarpeita varten voit suojautua haitallisilta tai vahingossa tapahtuvilta häiriöiltä klusterin sovellusten toiminnassa.

Calicon tekijöiden mukaan paras käytäntö on "Estä kaikki ja avaa mitä tarvitset" -lähestymistapa, joka on dokumentoitu virallinen dokumentaatio (toiset noudattavat samanlaista lähestymistapaa - erityisesti in jo mainittu artikkeli).

Muiden Calico-objektien käyttäminen

Muistutan teitä siitä, että laajennetun Calico API -sarjan avulla voit säädellä solmujen saatavuutta, ei rajoittuen podeihin. Seuraavassa esimerkissä käyttämällä GlobalNetworkPolicy kyky välittää ICMP-pyyntöjä klusterissa on suljettu (esimerkiksi ping-kutsut podista solmuun, podien välillä tai solmusta IP-koteloon):

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

Yllä olevassa tapauksessa klusterisolmut voivat silti "tavoitella" toisiaan ICMP:n kautta. Ja tämä ongelma ratkaistaan ​​keinoin GlobalNetworkPolicy, sovelletaan kokonaisuuteen 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-tapaus

Lopuksi annan hyvin todellisen esimerkin Calico-funktioiden käytöstä lähes klusterin vuorovaikutuksessa, kun vakiokäytäntö ei riitä. Web-sovelluksen käyttämiseen asiakkaat käyttävät VPN-tunnelia, ja tätä pääsyä valvotaan tiukasti ja rajoitetaan tiettyyn luetteloon sallituista palveluista:

Calico verkostoitumiseen Kubernetesissa: esittely ja vähän kokemusta

Asiakkaat muodostavat yhteyden VPN:ään tavallisen UDP-portin 1194 kautta, ja kun ne ovat yhteydessä, ne vastaanottavat reittejä podien ja palveluiden klusterialiverkkoihin. Kokonaisia ​​aliverkkoja työnnetään, jotta ne eivät menetä palveluita uudelleenkäynnistyksen ja osoitteenmuutosten aikana.

Kokoonpanon portti on vakio, mikä asettaa joitain vivahteita sovelluksen määritysprosessiin ja sen siirtämiseen Kubernetes-klusteriin. Esimerkiksi samassa AWS:ssä LoadBalancer for UDP ilmestyi kirjaimellisesti viime vuoden lopulla rajoitetulle alueiden luettelolle, eikä NodePortia voida käyttää sen edelleenlähetyksen vuoksi kaikissa klusterin solmuissa ja palvelinesiintymien määrää on mahdotonta skaalata. vikasietotarkoituksiin. Lisäksi sinun on muutettava porttien oletusaluetta...

Mahdollisten ratkaisujen etsimisen tuloksena valittiin seuraava:

  1. VPN-pohjaiset podit ajoitetaan solmukohtaisesti hostNetwork, eli todelliseen IP-osoitteeseen.
  2. Palvelu postitetaan ulos kautta ClusterIP. Solmulle on asennettu fyysisesti portti, johon pääsee ulkopuolelta pienin varauksin (todellisen IP-osoitteen ehdollinen läsnäolo).
  3. Sen solmun määrittäminen, jolla palko nousi, ei kuulu tarinamme piiriin. Sanon vain, että voit kytkeä palvelun solmuun tai kirjoittaa pienen sivuvaunupalvelun, joka tarkkailee VPN-palvelun nykyistä IP-osoitetta ja muokkaa asiakkaille rekisteröityjä DNS-tietueita - kenellä vain riittää mielikuvitusta.

Reitityksen näkökulmasta voimme yksilöidä VPN-asiakkaan sen VPN-palvelimen antaman IP-osoitteen perusteella. Alla on primitiivinen esimerkki tällaisen asiakkaan pääsyn palveluihin rajoittamisesta, joka on kuvattu edellä mainitussa Redisissä:

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]

Täällä yhdistäminen porttiin 6379 on ehdottomasti kielletty, mutta samalla DNS-palvelun toiminta säilyy, jonka toiminta kärsii melko usein sääntöjä laadittaessa. Koska, kuten aiemmin mainittiin, kun valitsin tulee näkyviin, siihen sovelletaan oletusarvoista estokäytäntöä, ellei toisin mainita.

Tulokset

Näin ollen Calicon edistyneen API:n avulla voit joustavasti määrittää ja muuttaa dynaamisesti reititystä klusterissa ja sen ympärillä. Yleisesti ottaen sen käyttö voi näyttää varpusen ampumiselta tykillä, ja L3-verkon toteuttaminen BGP- ja IP-IP-tunneleilla näyttää hirvittävältä yksinkertaisessa Kubernetes-asennuksessa tasaiseen verkkoon... Muuten työkalu näyttää kuitenkin varsin käyttökelpoiselta ja käyttökelpoiselta. .

Klusterin eristäminen turvallisuusvaatimusten mukaisesti ei välttämättä ole aina mahdollista, ja tässä Calico (tai vastaava ratkaisu) tulee apuun. Tässä artikkelissa annettuja esimerkkejä (pienin muutoksin) käytetään useissa asiakkaidemme AWS-asennuksissa.

PS.

Lue myös blogistamme:

Lähde: will.com

Lisää kommentti