A Wine 5.9 megjelenése

A Wine 5.9 megjelenése

A cikk célja, hogy megismertesse az olvasót a hálózati interakciók alapjaival és a Kubernetes hálózati politikáinak kezelésével, valamint a Calico külső pluginnal, amely bővíti a standard lehetőségeket. Útközben bemutatásra kerül a konfiguráció kényelme és néhány funkció valós példákon keresztül, tapasztalataink alapján.

Gyors bevezetés a Kubernetes hálózatának működésébe

A Kubernetes klaszter nem elképzelhető hálózat nélkül. Már publikáltunk anyagokat az alapjairól: „Illusztrált útmutató a Kubernetes hálózati felépítésérőlés a "Bevezetés a Kubernetes hálózati politikákba a biztonsági szakemberek számára».

A cikk kontextusában fontos megjegyezni, hogy a konténerek és csomópontok közötti hálózati kapcsolatért nem magát a K8s felel: ehhez különféle CNI pluginek (Container Networking Interface). Ezzel a fogalommal részletesebben is foglalkoztunk, például elmondtuk.

Például a legelterjedtebb ilyen plugin — Flannel — biztosítja a klaszter összes csomópontja közötti teljes hálózati kapcsolatot, hidak emelésével minden csomóponton, alhálózat hozzárendelésével hozzájuk. Azonban a teljes és szabályozatlan elérhetőség nem mindig előnyös. A klaszter minimális elkülönítésének biztosítása érdekében be kell avatkozni a tűzfal konfigurálásába. Általában ezzel a CNI-nak kell foglalkoznia, ami miatt minden külső beavatkozás az iptables-be helytelenül értelmezhető vagy teljesen figyelmen kívül hagyható.

Az „out of the box” megoldás a hálózati politikák kezelésének megszervezésére a Kubernetes klaszterben a NetworkPolicy API. Ez az erőforrás, amely az adott névtérre vonatkozik, tartalmazhat szabályokat az egyes alkalmazások közötti hozzáférés korlátozására. Lehetővé teszi a hozzáférhetőség konfigurálását konkrét podok, környezetek (névterek) vagy IP-cím blokkok 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

Ez nem a legprimitívebb példa ebből a szempontból hivatalos dokumentációban Egyszer és mindenkorra elveszítheti az érdeklődését a hálózati politikák működésének logikája iránt. Ennek ellenére megpróbáljuk megérteni a forgalomkezelés alapelveit és módszereit a hálózati politikák segítségével...

Logikus, hogy két fajta forgalom létezik: a pod-ba bejövő (Ingress) és onnan kimenő (Egress).

A Wine 5.9 megjelenése

Ezért ez a két kategória a mozgás irányának megfelelően különbözik.

A következő kötelező attribútum a kiválasztó; akihez a szabály alkalmazva van. Ez lehet egy pod (vagy pod-ok csoportja) vagy egy környezet (azaz névtér). Fontos részlet: mindkét típusú objektumnak tartalmaznia kell egy címkét (label a Kubernetes terminológiájában) — ezekkel dolgoznak a politikák.

A kiválasztók végső számán kívül, amelyeket valamilyen címke egyesít, van lehetőség olyan szabályok írására, mint például „Mindent megengedni/megtiltani” különböző változatokban. Ehhez az alábbi konstrukciókat használják:

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

— ebben a példában az összes pod számára le van tiltva a bejövő forgalom a környezetben. Az ellenkező viselkedés eléréséhez az alábbi konstrukció szükséges:

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

Ugyanez vonatkozik a kimenő forgalomra is:

  podSelector: {}
  policyTypes:
  - Egress

— ennek letiltásához. És így lehet aktiválni:

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

Visszatérve a CNI-bővítmény kiválasztásához a klaszterhez, érdemes megjegyezni, hogy nem minden hálózati bővítmény támogatja a NetworkPolicy használatát. Például a már említett Flannel nem tudja konfigurálni a hálózati politikákat, amint az hivatalosan is állítva van a hivatalos tárolóban. Ott említik egy alternatívát is — egy nyílt forráskódú projektet, Calico, amely jelentősen kibővíti a Kubernetes hálózati politikákhoz tartozó API-k alapértelmezett készletét.

A Wine 5.9 megjelenése

Ismerkedjünk meg a Calico-val: elmélet

A Calico bővítmény integrálható a Flannel-lal (a Canal) vagy önállóan is használható, biztosítva a hálózati kapcsolat működését és a hozzáférési lehetőségek kezelését.

Milyen lehetőségeket nyújt a „dobozos” K8s megoldás használata és a Calico API készlet?

Íme, ami a NetworkPolicy-ba van beépítve:

  • a politikák a környezetre korlátozódnak;
  • a politikák a címkékkel ellátott pod-okhoz alkalmazhatóak;
  • a szabályok pod-okhoz, környezetekhez vagy alhálózatokhoz alkalmazhatók;
  • a szabályok tartalmazhatnak protokollokat, névvel ellátott vagy szimbolikus port meghatározásokat.

Íme, hogyan bővíti a Calico ezeket a funkciókat:

  • A politikák bármely objektumra alkalmazhatók: pod, konténer, virtuális gép vagy interfész;
  • A szabályok tartalmazhatnak konkrét műveleteket (tiltás, engedélyezés, naplózás);
  • Szabályok céljaként vagy forrásaként port, port tartományokat, protokollokat, HTTP- vagy ICMP-attribútumokat, IP-t vagy alhálózatot (IPv4 vagy IPv6), bármely szelektort (csomópontok, gazdák, környezetek) használhatunk;
  • Továbbá a forgalom irányítását DNAT beállításokkal és forgalom átkonfigurálási politikákkal is szabályozhatjuk.

A Calico GitHub tárolójában az első committok 2016 júliusára datálhatók, és már egy évvel később a projekt vezető szerepet töltött be a Kubernetes hálózati kapcsolódási megoldásaiban, amit például a The New Stack által végzett felmérés eredményei is igazolnak.:

A Wine 5.9 megjelenése

Számos nagyobb managed K8s megoldás, mint például Amazon EKS, Azure AKS, Google GKE és mások, javasolják a használatát.

A teljesítményt illetően minden remekül alakul. A Calico fejlesztőcsapata a termék tesztelése során csillagászati mutatókat mutatott be, több mint 50000 konténer futtatása mellett 500 fizikai csomóponton, 20 konténer/másodperces sebességgel. A skálázás során problémákat nem tapasztaltak. Ezek az eredmények a legelső verzió bejelentésekor már elhangzottak. Független kutatások, amelyek a sávszélességre és erőforrás-felhasználásra irányultak, szintén megerősítik a Calico teljesítményét, amely szinte felér a Flanneléval. Például:

A Wine 5.9 megjelenése

A projekt rendkívül gyorsan fejlődik, támogatja a népszerű managed K8s megoldásokat, az OpenShiftet, az OpenStacket, lehetőséget biztosít a Calico használatára a klaszter telepítésekor, kops, és előfordulnak Service Mesh hálózatok kialakítására vonatkozó említések (itt egy példa az Istióval való együttműködésre).

Gyakorlat Calico-val

A vanilla Kubernetes használata során a CNI telepítése általában a következő fájlra korlátozódik: calico.yaml, amit a hivatalos weboldalról tölthetünk le., a segítségével kubectl apply -f.

Általában az aktuális bővítmény verziója kompatibilis a Kubernetes 2-3 legutolsó verziójával: a régebbi verziókban való működést nem tesztelik és nem garantálják. A fejlesztők állítása szerint a Calico a Linux 3.10 verzió feletti kernével működik CentOS 7, Ubuntu 16 vagy Debian 8 alatt, az iptables vagy IPVS felett.

Izoláció a környezeten belül

Általános megértés céljából nézzük meg az egyszerű esetet, hogy megértsük, miben különböznek a Calico notációban lévő hálózati szabályok a hagyományosaktól, és hogyan egyszerűsíti a szabályok megfogalmazása azok olvashatóságát és konfigurálhatóságát:

A Wine 5.9 megjelenése

A klaszterben 2 webalkalmazás fut: Node.js és PHP, az egyik Redis-t is használ. Ahhoz, hogy megakadályozzuk a PHP hozzáférését a Redis-hoz, miközben a Node.js-zel való kapcsolódást megőrizzük, elegendő alkalmazni az alábbi szabályt:

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

Valójában engedélyeztük a bejövő forgalmat a Redis portjára Node.js-ből. És egyértelműen nem tiltottunk meg semmi mást. Amint megjelenik egy NetworkPolicy, az összes előírt szelektor, amelyet tartalmaz, elkülönül, hacsak másképp nem rendelkeznek. Ugyanakkor az izolációs szabályok nem terjednek ki más objektumokra, amelyeket a szelektor nem fed le.

A példában szereplő apiVersion a Kubernetes-től „alapértelmezetten”, de semmi sem akadályozza meg, hogy a Calico szállítmányból származó azonos nevű forrást használjuk. A szintaxis ott bővebb, ezért át kell írnunk a fenti eset szabályát 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 fent említett konstrukciók hálózati forgalom engedélyezésére vagy megtiltására a szokásos NetworkPolicy API-nál nehezen érthető és megjegyezhető konstrukciókat tartalmaznak zárójelek formájában. A Calico esetében, hogy megváltoztassuk a tűzfal szabályának logikáját az ellenkezőjére, elegendő megváltoztatni a action: Allow Gyorsan emlékezzünk vissza, hogyan működik a moduláris aritmetika. Az óra már egy ismert koncepció. Az órák használata action: Deny.

Izoláció környezetek szerint

Most képzeljük el azt a helyzetet, amikor egy alkalmazás üzleti metrikákat generál Prometheus számára, hogy azokat gyűjtse és később elemezze Grafana segítségével. A kivitel érzékeny adatokat tartalmazhat, amelyek alapértelmezetten ismételten mindenki számára láthatóak. Zárjuk el ezeket az adatokat a kíváncsi szemek elől:

A Wine 5.9 megjelenése

A Prometheus általában egy külön szolgáltatási környezetbe van helyezve — a példában ez az alábbi típusú namespace:

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

Mező metadata.labels itt nem véletlenül jelent meg. Mint korábban említettük, namespaceSelector (mint a podSelector) címkékkel operál. Ezért ahhoz, hogy engedje meg a metrikák lekérését minden podból egy adott porton, hozzá kell adnia valamilyen címkét (vagy el kell érni a meglévőkből), majd alkalmazni kell egy hasonló 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 Calico politikák használata esetén 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, ha az ilyen típusú politikákat a konkrét igényekhez igazítjuk, meg lehet védeni az alkalmazások működését a klaszterben a szándékos vagy véletlen beavatkozásoktól.

A Calico készítői szerint a legjobb gyakorlat az, hogy „Tiltson le mindent, és nyissa meg kifejezetten a szükségest”, amit rögzítettek hivatalos dokumentációban (hasonló megközelítést követ mások is — konkrétan a már említett cikkben).

Kiegészítő Calico objektumok alkalmazása

Emlékeztetem, hogy a Calico kiterjesztett API-készletén keresztül lehet szabályozni a csomópontok elérhetőségét, nem csupán a podokra korlátozódva. A következő példában GlobalNetworkPolicy lezárja a lehetőséget, hogy ICMP-üzenetek haladjanak át a klaszteren (például pings a podból a csomópontra, podok között vagy a csomóponton IP podra):

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 a klaszter csomópontjainak lehetősége van arra, hogy ICMP-vel kommunikáljanak egymással. És ezt a kérdést a GlobalNetworkPolicy, alkalmazva az entitásra 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 esetén

Végül bemutatok egy valós példát a Calico funkciók használatára a klaszter körüli interakció során, amikor a standard politikák nem elegendőek. A webalkalmazás ügyfelei VPN-alagutat használnak, és ez a hozzáférés szigorúan ellenőrzött és korlátozott egy adott engedélyezett szolgáltatáslistára:

A Wine 5.9 megjelenése

Az ügyfelek a VPN-hez a standard UDP 1194 porton csatlakoznak, és a csatlakozás során útvonalakat kapnak a podok és szolgáltatások klaszter alhálózataihoz. Az alhálózatok teljes egészében push-olódnak, hogy ne veszítsék el a szolgáltatásokat újraindítások és címváltások esetén.

A konfigurációban a port standard, ami bizonyos szempontból bonyolítja az alkalmazás konfigurálását és annak Kubernetes klaszterbe történő áttelepítését. Például az AWS LoadBalancer esetében az UDP port gyakorlatilag tavaly év végén jelent meg korlátozott régiók listáján, és a NodePort nem használható, mivel az az összes klaszter csomópontot érinti, így nem lehet skálázni a szerver példányok számát a megbízhatóság növelése érdekében. Emellett módosítani kell a kiválasztott portok tartományát is...

A lehetséges megoldások átvizsgálása után a következő került kiválasztásra:

  1. A podok VPN-t a hostNetwork, azaz a tényleges IP-n tervezik.
  2. A szolgáltatás külsőleg a ClusterIPkeresztül van kitetve. A csomóponton fizikailag egy portot indítanak, amely kívülről elérhető néhány korlátozással (feltételezve a tényleges IP-cím meglétét).
  3. A csomópont meghatározása, ahol a pod elindult, a történetünkön kívül esik. Csak annyit mondanék, hogy a szolgáltatást szigorúan a csomóponthoz lehet rögzíteni, vagy írhatunk egy kis sidecar szolgáltatást, amely nyomon követi a VPN szolgáltatás aktuális IP címét, és frissíti a DNS bejegyzéseket az ügyfeleknél — mindenkinek a képzelete szerint.

Az útvonal-kezelés szempontjából egyértelműen azonosítani tudjuk az ügyfelet a VPN-en belül az IP címével, amelyet a VPN szerver ad ki. Az alábbiakban egy primitív példa látható, amely egy ilyen ügyfél hozzáférését korlátozza a szolgáltatásokhoz, a fent említett Redis illusztrációja:

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 porthoz való csatlakozás, de a DNS szolgáltatás működését megőrizzük, amely gyakran szenved a szabályok összeállításakor. Mivel, ahogyan korábban említettem, ha van választó, akkor alapértelmezetten tilalmazó politika lép érvénybe, hacsak másként nincs megjelölve.

Összegzés

Így a Calico kiterjesztett API-jának segítségével rugalmasan konfigurálható és dinamikusan változtatható a Kubernetes klaszter és környékének forgalmi irányítása. Általánosságban elmondható, hogy a használata olyan, mintha ágyúval lőnénk verébkre, míg az L3-hálózat bevezetése BGP- és IP-IP-alagútakkal óriásinak tűnik egy egyszerű Kubernetes telepítés esetén, amely lapos hálózaton működik... Azonban egyéb szempontból az eszköz teljesen életképesnek és hasznosnak tűnik.

A klaszter izolálása a biztonsági követelmények teljesítése érdekében nem mindig valósítható meg, és éppen ilyen esetekben jön segítségül a Calico (vagy hasonló megoldások). A cikkben bemutatott példák (kisebb módosítással) több ügyfél AWS telepítéseiben is használatban vannak.

P.S.

Olvasson további információkat a blogunkban:

Forrás: habr.com

Megbízható hosting vásárlása weboldalak számára, DDoS védelemmel, VPS VDS szerverek. 🔥 Megbízható webtárhely vásárlása DDoS védelemmel, VPS VDS szerverek | ProHoster