Calico hálózatépítéshez Kubernetesben: bemutatkozás és egy kis tapasztalat

Calico hálózatépítéshez Kubernetesben: bemutatkozás és egy kis tapasztalat

A cikk célja, hogy bemutassa az olvasónak a Kubernetes hálózatkezelésének és hálózati házirendek kezelésének alapjait, valamint a szabványos képességeket kiterjesztő, harmadik féltől származó Calico bővítményt. Útközben a konfigurálás egyszerűségét és néhány szolgáltatást a működési tapasztalatainkból származó valós példák segítségével mutatjuk be.

A Kubernetes hálózati eszköz gyors bemutatása

Egy Kubernetes-fürt nem képzelhető el hálózat nélkül. Az alapjaikról már publikáltunk anyagokat: "Illusztrált útmutató a Kubernetes hálózatépítéshez"És"Bevezetés a Kubernetes hálózati irányelveibe biztonsági szakembereknek".

A cikk kapcsán fontos megjegyezni, hogy a K8s maga nem felelős a konténerek és csomópontok közötti hálózati kapcsolatért: ehhez különféle CNI bővítmények (Container Networking Interface). Erről a koncepcióról bővebben mi nekem is mondták.

Például ezek közül a beépülő modulok közül a leggyakoribb az Flanel — teljes hálózati kapcsolatot biztosít az összes fürtcsomópont között azáltal, hogy minden csomóponton hidat hoz létre, hozzárendelve egy alhálózatot. A teljes és szabályozatlan akadálymentesítés azonban nem mindig előnyös. Ahhoz, hogy a fürtben valamilyen minimális elszigetelést biztosítsunk, be kell avatkozni a tűzfal konfigurációjába. Általában ugyanannak a CNI-nek az irányítása alá kerül, ezért az iptables-ban bármilyen harmadik fél beavatkozása helytelenül értelmezhető vagy teljesen figyelmen kívül hagyható.

A Kubernetes-fürtben a hálózati házirend-kezelés megszervezéséhez pedig „kivételes” lehetőség biztosított NetworkPolicy API. Ez az erőforrás, amely a kiválasztott névtereken van elosztva, szabályokat tartalmazhat az alkalmazások közötti hozzáférés megkülönböztetésére. Lehetővé teszi továbbá az akadálymentesítés konfigurálását adott podok, környezetek (névterek) vagy IP-címblokkok között:

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

Nem ez a legprimitívebb példa erre hivatalos dokumentáció egyszer s mindenkorra elriaszthatja a vágyat, hogy megértsük a hálózati politikák működésének logikáját. Ennek ellenére megpróbáljuk megérteni a forgalmi áramlások hálózati házirendek segítségével történő feldolgozásának alapelveit és módszereit...

Logikus, hogy 2 fajta forgalom létezik: a podba belépő (Ingress) és onnan kimenő (Kilépés).

Calico hálózatépítéshez Kubernetesben: bemutatkozás és egy kis tapasztalat

Valójában a politika ebbe a két kategóriába oszlik a mozgás iránya alapján.

A következő kötelező attribútum egy szelektor; akire vonatkozik a szabály. Ez lehet egy pod (vagy pod-csoport) vagy egy környezet (azaz egy névtér). Egy fontos részlet: mindkét típusú objektumnak tartalmaznia kell egy címkét (címke Kubernetes terminológiában) – ezekkel operálnak a politikusok.

A véges számú szelektoron kívül, amelyeket valamilyen címkével egyesítenek, lehetséges olyan szabályokat írni, mint a „Minden/mindenki engedélyezése/megtagadása” különböző változatokban. Erre a célra a következő forma konstrukciókat használják:

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

- ebben a példában a környezetben lévő összes pod blokkolva van a bejövő forgalom elől. Ellentétes viselkedés érhető el a következő konstrukcióval:

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

Hasonlóan a kimenőhöz:

  podSelector: {}
  policyTypes:
  - Egress

- kikapcsolni. És a következőket kell belefoglalni:

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

Visszatérve a CNI-bővítmény kiválasztásához egy fürthöz, érdemes megjegyezni, hogy nem minden hálózati bővítmény támogatja a NetworkPolicy-t. Például a már említett Flanel nem tudja, hogyan kell hálózati házirendeket beállítani, ami közvetlenül ki van mondva a hivatalos adattárban. Egy alternatívát is említenek - egy nyílt forráskódú projektet Karton, amely jelentősen bővíti a Kubernetes API-k szabványos készletét a hálózati házirendek tekintetében.

Calico hálózatépítéshez Kubernetesben: bemutatkozás és egy kis tapasztalat

Calico megismerése: elmélet

A Calico beépülő modul használható a Flannel (alprojekt Csatorna).

Milyen lehetőségeket kínál a K8s „dobozos” megoldása és a Calico API készlete?

A NetworkPolicy tartalma a következő:

  • a politikusokat korlátozza a környezet;
  • a címkékkel megjelölt hüvelyekre az irányelvek vonatkoznak;
  • szabályok alkalmazhatók podokra, környezetekre vagy alhálózatokra;
  • A szabályok tartalmazhatnak protokollokat, elnevezett vagy szimbolikus portspecifikációkat.

A Calico a következőképpen terjeszti ki ezeket a funkciókat:

  • a házirendek bármely objektumra alkalmazhatók: pod, tároló, virtuális gép vagy interfész;
  • a szabályok tartalmazhatnak konkrét műveletet (tiltás, engedély, naplózás);
  • a szabályok célpontja vagy forrása lehet egy port, portok, protokollok, HTTP- vagy ICMP-attribútumok, IP vagy alhálózat (4. vagy 6. generáció), bármilyen szelektor (csomópontok, gazdagépek, környezetek);
  • Ezenkívül szabályozhatja a forgalom áthaladását a DNAT-beállítások és a forgalomtovábbítási házirendek segítségével.

Az első commitok a Calico repository-ban található GitHubon 2016 júliusára nyúlnak vissza, majd egy évvel később a projekt vezető pozícióba került a Kubernetes hálózati kapcsolat megszervezésében – ezt bizonyítják például a felmérés eredményei, a The New Stack vezényletével:

Calico hálózatépítéshez Kubernetesben: bemutatkozás és egy kis tapasztalat

Sok nagy menedzselt megoldás a K8-asokkal, mint pl Amazon EX, Azure AKS, Google GKE és mások elkezdték ajánlani a használatát.

Ami a teljesítményt illeti, itt minden nagyszerű. Termékük tesztelése során a Calico fejlesztőcsapata csillagászati ​​teljesítményt mutatott be: több mint 50000 500 konténert futtatott 20 fizikai csomóponton, másodpercenként XNUMX konténer létrehozási sebességgel. A méretezéssel kapcsolatban nem észleltek problémát. Ilyen eredmények bejelentették már az első verzió bejelentésekor. Az átviteli teljesítményre és az erőforrás-felhasználásra összpontosító független tanulmányok is megerősítik, hogy a Calico teljesítménye majdnem olyan jó, mint a Flannelé. Például:

Calico hálózatépítéshez Kubernetesben: bemutatkozás és egy kis tapasztalat

A projekt nagyon gyorsan fejlődik, támogatja a népszerű K8s, OpenShift, OpenStack menedzselt megoldásokban való munkát, lehetőség van a Calico használatára fürt telepítésekor rúgás, vannak utalások a Service Mesh hálózatok felépítésére (itt egy példa Istio-val együtt használva).

Gyakorolj Calico-val

A vanília Kubernetes általános használata esetén a CNI telepítése a fájl használatán múlik calico.yaml, letöltve a hivatalos webhelyről, használva kubectl apply -f.

Általános szabály, hogy a beépülő modul jelenlegi verziója kompatibilis a Kubernetes legújabb 2-3 verziójával: a régebbi verziók működése nincs tesztelve, és nem garantált. A fejlesztők szerint a Calico 3.10 feletti Linux kerneleken fut, amelyeken CentOS 7, Ubuntu 16 vagy Debian 8, az iptables vagy IPVS mellett.

Izoláció a környezetben

Az általános megértés érdekében nézzünk meg egy egyszerű esetet, hogy megértsük, miben térnek el a Calico jelölésben szereplő hálózati házirendek a szabványosoktól, és hogy a szabályok létrehozásának megközelítése hogyan egyszerűsíti le az olvashatóságot és a konfigurációs rugalmasságot:

Calico hálózatépítéshez Kubernetesben: bemutatkozás és egy kis tapasztalat

A fürtben két webalkalmazás van telepítve: a Node.js és a PHP, amelyek közül az egyik Redis-t használ. A Redis PHP-ből való hozzáférésének letiltásához, miközben fenntartja a kapcsolatot a Node.js-szel, csak alkalmazza a következő házirendet:

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

Lényegében engedélyeztük a bejövő forgalmat a Redis portra a Node.js-ről. És nyilvánvalóan nem tiltottak mást. Amint megjelenik a NetworkPolicy, az abban említett összes szelektor el lesz különítve, hacsak másképp nincs megadva. Az elkülönítési szabályok azonban nem vonatkoznak más objektumokra, amelyeket a kiválasztó nem fed le.

A példa használja apiVersion Kubernetes a dobozból, de semmi sem akadályozza meg a használatában azonos nevű forrás a Calico szállításból. A szintaxis ott részletesebb, ezért át kell írni a szabályt a fenti esetre a következő formában:

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

A normál NetworkPolicy API-n keresztüli teljes forgalom engedélyezésére vagy letiltására szolgáló fent említett konstrukciók zárójelekkel ellátott konstrukciókat tartalmaznak, amelyeket nehéz megérteni és megjegyezni. A Calico esetében, ha a tűzfalszabály logikáját az ellenkezőjére szeretné változtatni, csak változtasson action: Allow on action: Deny.

Környezeti izoláció

Most képzeljünk el egy olyan helyzetet, amikor egy alkalmazás üzleti mérőszámokat generál a Prometheusban való gyűjtéshez és a Grafana segítségével történő további elemzéshez. A feltöltés érzékeny adatokat tartalmazhat, amelyek alapértelmezés szerint ismét nyilvánosan megtekinthetők. Rejtsük el ezeket az adatokat a kíváncsi szemek elől:

Calico hálózatépítéshez Kubernetesben: bemutatkozás és egy kis tapasztalat

A Prometheus rendszerint külön szolgáltatási környezetbe kerül - a példában ez egy ilyen névtér lesz:

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

Mező metadata.labels ez nem volt véletlen. Fent említett, namespaceSelector (szintén podSelector) címkékkel működik. Ezért ahhoz, hogy egy adott porton lévő összes podból metrikát lehessen venni, hozzá kell adnia valamilyen címkét (vagy át kell vennie a meglévőkből), majd alkalmaznia kell egy ilyen konfigurációt:

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

És ha Calico házirendeket használ, a szintaxis a következő lesz:

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

Általánosságban elmondható, hogy az ilyen típusú házirendek speciális igényekhez történő hozzáadásával védelmet nyújthat a fürtben lévő alkalmazások működésében bekövetkező rosszindulatú vagy véletlen beavatkozások ellen.

A Calico készítői szerint a legjobb gyakorlat a „Block mindent, és kifejezetten nyissa meg, amire szüksége van” megközelítés, amelyet a dokumentum dokumentál. hivatalos dokumentáció (Mások hasonló megközelítést követnek – különösen a már említett cikk).

További Calico objektumok használata

Hadd emlékeztesselek arra, hogy a Calico API-k kiterjesztett készletével szabályozhatja a csomópontok elérhetőségét, nem csak a podokra korlátozva. A következő példában használja GlobalNetworkPolicy az ICMP-kérések fürtben való átadásának képessége le van zárva (például ping-ek egy podból egy csomópontba, a podok között vagy egy csomópontból egy IP podba):

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

A fenti esetben továbbra is lehetséges, hogy a fürtcsomópontok ICMP-n keresztül „elérjék” egymást. És ezt a problémát eszközökkel oldják meg GlobalNetworkPolicy, egy entitásra vonatkoztatva 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"]

A VPN-ügy

Végül egy nagyon valós példát adok a Calico függvények használatára klaszterközeli interakció esetén, amikor egy szabványos házirend nem elegendő. A webalkalmazás eléréséhez a kliensek VPN-alagutat használnak, és ez a hozzáférés szigorúan ellenőrzött, és a használatra engedélyezett szolgáltatások meghatározott listájára korlátozódik:

Calico hálózatépítéshez Kubernetesben: bemutatkozás és egy kis tapasztalat

Az ügyfelek a szabványos 1194-es UDP-porton keresztül csatlakoznak a VPN-hez, és csatlakozáskor útvonalakat kapnak a pod-ok és szolgáltatások fürt alhálózataihoz. A teljes alhálózatok eltolódnak, hogy ne veszítsék el a szolgáltatásokat az újraindítások és a címmódosítások során.

A konfigurációban lévő port szabványos, ami bizonyos árnyalatokat szab az alkalmazás konfigurálásának és a Kubernetes-fürtbe való átvitelének folyamatában. Például ugyanabban az AWS-ben a LoadBalancer for UDP szó szerint tavaly év végén jelent meg a régiók korlátozott listájában, és a NodePort nem használható az összes fürtcsomóponton történő továbbítása miatt, és lehetetlen a szerverpéldányok számának méretezését. hibatűrési célokra. Ráadásul módosítania kell a portok alapértelmezett tartományát...

A lehetséges megoldások keresése eredményeként a következőket választottuk:

  1. A VPN-t használó pod-ok csomópontonként vannak ütemezve hostNetwork, vagyis a tényleges IP-re.
  2. A szolgáltatás kifüggesztve keresztül történik ClusterIP. A csomóponton fizikailag telepítve van egy port, amely kisebb fenntartásokkal kívülről is elérhető (valós IP-cím feltételes jelenléte).
  3. Annak a csomópontnak a meghatározása, amelyen a hüvely rózsa, túlmutat történetünk keretein. Csak azt mondom, hogy szorosan „szegezheti” a szolgáltatást egy csomóponthoz, vagy írhat egy kis oldalkocsi szolgáltatást, amely figyeli a VPN-szolgáltatás aktuális IP-címét, és szerkeszti az ügyfeleknél regisztrált DNS-rekordokat - akinek van elég fantáziája.

Útválasztási szempontból egyedileg azonosíthatjuk a VPN-klienst a VPN-kiszolgáló által kiadott IP-címe alapján. Az alábbiakban egy primitív példa látható az ilyen ügyfelek szolgáltatásokhoz való hozzáférésének korlátozására, amelyet a fent említett Redis szemléltet:

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]

Itt szigorúan tilos a 6379-es porthoz csatlakozni, de ugyanakkor megmarad a DNS-szolgáltatás működése, amelynek működése gyakran szenved a szabályok kidolgozásakor. Mivel, amint azt korábban említettük, amikor megjelenik egy választó, a rendszer az alapértelmezett megtagadási házirendet alkalmazza, hacsak nincs másként megadva.

Eredményei

Így a Calico fejlett API-jával rugalmasan konfigurálhatja és dinamikusan módosíthatja az útválasztást a fürtben és környékén. Általánosságban elmondható, hogy a használata úgy néz ki, mint a verebek lövöldözése ágyúval, és egy L3-as hálózat megvalósítása BGP és IP-IP alagutak segítségével szörnyen néz ki egy egyszerű Kubernetes telepítésnél lapos hálózaton... Egyébként az eszköz elég életképesnek és hasznosnak tűnik. .

Előfordulhat, hogy a biztonsági követelményeknek megfelelő fürt elkülönítése nem mindig kivitelezhető, és itt a Calico (vagy egy hasonló megoldás) segít. Az ebben a cikkben szereplő példák (kisebb módosításokkal) ügyfeleink több AWS-beli telepítésében is használatosak.

PS

Olvassa el blogunkon is:

Forrás: will.com

Hozzászólás