
Artikli eesmärk on tutvustada lugejat Kubernetes'e võrgus kommunikatsiooni ja võrgu poliitikate haldamise alustega ning kolmanda osapoole plugina Calico, mis laiendab standardseid võimalusi. Samuti demonstreeritakse seadistamise mugavust ja mõningaid funktsioone meie töökogemuste põhjal.
Kiire sissejuhatus Kubernetes'e võrguseadmisse
Kubernetes'e kluster on võimatu ette kujutada ilma võrguta. Oleme juba avaldanud materjale nende aluste kohta: "» ja «».
Sellest artiklist rääkides on oluline märkida, et konteinerite ja sõlmede vahelise võrguside eest vastutab mitte K8s ise: selleks kasutatakse mitmesuguseid CNI pluginaid (Container Networking Interface). Täiendavat teavet selle kontseptsiooni kohta oleme .
Näiteks on kõige levinum selline plugin — — tagab täielikku võrguühenduvust kõigi klastris olevate sõlmede vahel, luues igas sõlmes sillad ja kinnitades neile alamvõrgu. Siiski ei ole täielik ja reguleerimata kättesaadavus alati kasulik. Klastris mingisuguse minimaalsete eraldusmeetmete tagamiseks on vajalik sekkuda tulemüüride konfigureerimisse. Üldiselt on see usaldatud sama CNI haldusesse, mistõttu võivad kõik välised sekkumised iptables’isse olla vale tõlgendusega või sootuks ignoreeritud.
Ja "kastist välja" pakub Kubernetes klastris võrgu poliitikate juhtimiseks . See ressurss, mida rakendatakse valitud nime ruumides, võib sisaldada reegleid juurdepääsu eraldamiseks ühe rakenduse ja teise vahel. See võimaldab samuti seadistada juurdepääsu konkreetsete pod’ide, keskkondade (nime ruumide) või IP-aadresside plokkide vahel:
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Этот не самый примитивный пример из может раз и навсегда отбить желание разбираться в логике работы сетевых политик. Однако мы всё же попробуем понять основные принципы и методы обработки потоков трафика с помощью сетевых политик…
Логично, что есть 2 типа трафика: входящий в pod (Ingress) и исходящий из него (Egress).

Собственно, на эти 2 категории по направлению движения и разделяется политика.
Следующий обязательный атрибут — селектор; тот, к кому применяется правило. Это может быть pod (или группа pod’ов) или окружение (т.е. пространство имен). Важная деталь: оба вида этих объектов обязаны содержать метку (silt в терминологии Kubernetes) — именно ими оперируют политики.
Lisaks lõplikule valikule, mis on ühendatud mõne märgisega, on võimalik kirjutada reegleid nagu "Luba / keela kõik / kõigile" erinevates variatsioonides. Selleks kasutatakse konstruktsioone, nagu:
podSelector: {}
ingress: []
policyTypes:
- Ingress— sel juhul suletakse kõigi pod'ide sisenemine keskkonda. Vastupidist käitumist saab saavutada sellise konstruktsiooniga:
podSelector: {}
ingress:
- {}
policyTypes:
- IngressSama kehtib ka väljuva liikluse kohta:
podSelector: {}
policyTypes:
- Egress— selle keelamiseks. Ja siin on see, kuidas seda lubada:
podSelector: {}
egress:
- {}
policyTypes:
- EgressTagasi tulles CNI-lisa valikku klastrile, tasub märkida, et kõik võrgu lisad ei toeta NetworkPolicy tööd. Näiteks juba mainitud Flannel ei oska võrgu poliitikaid seadistada, millest ametlikus hoidlas. Seal mainitakse ka alternatiivi — avatud lähtekoodiga projekt , mis laianeb oluliselt Kubernetes'e võrgu poliitilisi API-sid.

Tutvume Calicoga: teooria
Calico plugin saab kasutada Flanneliga koos (alaprojekt ) või iseseisvalt, katab nii võrguühenduse tagamise funktsioonid kui ka kättesaadavuse haldamise võimalused.
Milliseid võimalusi pakub ‘karbi’ K8s lahenduse ja Calico API komplekti kasutamine?
Siin on, mis on NetworkPolicy sisse ehitatud:
- poliitikad on piiratud keskkonnaga;
- poliitikad rakendatakse siltidega pod'idele;
- reeglid võivad kehtida pod'idele, keskkondadele või alamvõrkudele;
- reeglid võivad sisaldada protokolle, nimetatud või sümboolseid portide viiteid.
Ja nii laiendab Calico neid funktsioone:
- poliitikad võivad kehtida igasugustele objektidele: pod, konteiner, virtuaalmasin või liides;
- reeglid võivad sisaldada konkreetset tegevust (keeldumine, lubamine, logimine);
- reeglite sihtmärgiks või allikaks võivad olla port, portide vahemik, protokollid, HTTP- või ICMP-attribuudid, IP või alamvõrk (4. või 6. põlvkond), kõik valijad (sõlmed, hostid, keskkonnad);
- lisaks on võimalik reguleerida liikluse läbimist DNAT-i seadete ja liikluse suunamise poliitikate abil.
Calico hoidlate esimesed commitid GitHubis pärinevad 2016. aasta juulist, ja juba aasta hiljem saavutas projekt juhtiva positsiooni Kubernetes'i võrgutootmise organisatsioonis — näiteks kinnitavad seda küsitluse tulemused. :

Paljud suured K8s-i hallatud lahendused, nagu , , ning teised, on hakanud seda soovitama.
Mis puutub jõudlusesse, siis on kõik suurepärane. Calico arendustiim demonstreeris oma toote testimisel astronoomilisi näitajaid, käivitades enam kui 50000 konteinerit 500 füüsilisel sõlmel kiirusel 20 konteinerit sekundis. Skaleerimisega ei esinenud probleeme. Sellised tulemused juba esimese versiooni väljakuulutamisel. Olenematu teadusuuringud, mis on suunatud läbilaskevõime ja ressursitarbimise mahtude määramisele, kinnitavad samuti Calico jõudlust, mis praktiliselt ei jää Flannelile alla. :

Projekt areneb väga kiiresti, toetades töötlust populaarsetes hallatud K8s-i lahendustes, OpenShiftis, OpenStackis ning on võimalik kasutada Calicot klastrite juurutamisel , kohtab viiteid Service Mesh-võrkude ehitamisele ( использования совместно с Istio).
Практика с Calico
В общем случае использования ванильного Kubernetes установка CNI сводится к применению файла calico.yaml, , kasutades kubectl apply -f.
Как правило, актуальная версия плагина совместима с 2-3 последними версиями Kubernetes: работу в более старых версиях не тестируют и не гарантируют. По заявлениям разработчиков, Calico работает на ядре Linux выше 3.10 под управлением CentOS 7, Ubuntu 16 или Debian 8, поверх iptables или IPVS.
Изоляция внутри окружения
Для общего понимания рассмотрим простой случай, чтобы понять, чем отличаются сетевые политики в нотации Calico от стандартных и как подход к составлению правил упрощает их читаемость и гибкость конфигурирования:

В кластере развёрнуты 2 веб-приложения: на Node.js и PHP, — одно из которых использует Redis. Чтобы закрыть доступ к Redis из PHP, оставив при этом связность с Node.js, достаточно применить следующую политику:
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: 6379Põhimõtteliselt oleme lubanud sissetuleva liikluse Redis pordile Node.js-st. Ja me ei ole selgelt midagi muud keelanud. Kui NetworkPolicy ilmub, hakkavad kõik selles mainitud selektorid isoleeruma, kui pole teisiti märgitud. Samuti ei laiene isolatsioonieeskirjad muudele objektidele, mida selektor ei kata.
Näites kasutatakse apiVersion Kubernetes'e "välja kastist", kuid miski ei takista kasutamast . Süntaks on seal keerulisem, seega tuleb ülaltoodud juhtumi eeskirja kirjutada järgmisel kujul:
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 Ülalmainitud konstruktsioonid, et lubada või keelata kogu liiklust tavapärase NetworkPolicy API kaudu, sisaldavad keerulisi ja meeldejäävaid konstruktsioone sulgudes. Calico puhul piisab tulemüüri reegli logika muutmiseks vastupidiseks, kui muuta action: Allow järgnevaga action: Deny.
Isolatsioon keskkondade kaupa
Kujutage nüüd olukorda, kus rakendus genereerib ärimetreid nende kogumiseks Prometheuses ja edasisteks analüüsideks Grafanas. Väljavõttes võivad olla tundlikud andmed, mis vaikimisi on taas kergesti kätte saadavad. Kaitseme need andmed võõraste silmade eest:

Prometheus on tavaliselt eraldi teenusekeskkonnas — näites on see nimede ruum järgmise nimega:
apiVersion: v1
kind: Namespace
metadata:
labels:
module: prometheus
name: kube-prometheus Väli metadata.labels see ei juhtunud juhuslikult. Nagu eespool juba mainitud, namespaceSelector'iga (nagu ka podSelector) opereerib etiketiga. Seetõttu, et lubada metrikate hankimist kõigilt pod'idelt teatud pordil, tuleb lisada mõni silt (või võtta olemasolevatest), seejärel rakendada konfiguratsioon nagu:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-metrics-prom
spec:
podSelector: {}
ingress:
- from:
- namespaceSelector:
matchLabels:
module: prometheus
ports:
- protocol: TCP
port: 9100Ja Calico poliitikate kasutamise korral näeb süntaks välja järgmine:
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Üldiselt saab selliste poliitikate kohandamisel konkreetsete vajadustega kaitsta rakenduste tööd klastris pahatahtliku või juhusliku sekkumise eest.
Parim praktika Calico looja arvates on lähenemine "Keela kõik ja ava selgelt vajalik", mis on dokumenteeritud (sama lähenemist järgivad ka teised, sealhulgas ).
Lisaressursside Calico rakendamine
Tuletan meelde, et Calico laiendatud API komplekti kaudu saab reguleerida sõlmede kättesaadavust, mitte ainult pod’ide osas. Järgmises näites aitab see GlobalNetworkPolicy blokeerida ICMP-päringute läbimise klastris (näiteks pod’ist sõlmele, pod’ide vahel või sõlmelt pod’i IP-le):
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 Eeltoodud juhul jääb klastris olevatele sõlmedele võimalus üksteisega ICMP kaudu ühendust võtta. Ja see probleem lahendatakse GlobalNetworkPolicy, mis on rakendatud objekti 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"]VPNi juhtum
Toon lõpuks üsna reaalset näidet Calico funktsioonide kasutamisest, kui standardne poliitikakogum ei piisa klastritevahelise suhtluse juhtimiseks. Klientide juurdepääs veebirakendusele toimub VPN-tunneli kaudu, kusjuures juurdepääs on rangelt reguleeritud ja piiratud kindla lubatud teenuste nimekirjaga:

Kliendid ühenduvad VPN-i kaudu tavalise UDP-pordi 1194 kaudu ja saavad ühendamisel marsruudid klastrite pods ja teenuste alamvõrkudesse. Alamvõrgud push’itakse tervikuna, et teenused ei kaoks taaskäivituste ja aadresside muutmise korral.
Konfiguratsioonis on port standardne, mis seab rakenduse konfigureerimise protsessile ja selle viimiseks Kubernetes klastrisse mõned eripärad. Näiteks, AWS LoadBalanceris ilmus UDP eelmisel aastal piiratud piirkondade loetelus, kuid NodePorti ei saa kasutada, kuna see suunatakse kõikidele klastris olevatele sõlmedele ja ei ole võimalik skaleerida serveri instantside arvu töökindluse saavutamiseks. Lisaks tuleb muuta vaikimisi valitud portide vahemikku...
Võimalike lahenduste ülesseadmise tulemusel valiti järgnev:
- VPN Pod'id plaanitakse sõlmele režiimis
hostNetwork, st tegelikule IP-le. - Teenust väljapoole suunatakse läbi
ClusterIP. Sõlmel tõstetakse füüsiliselt port, mis on kergelt väljastpoolt kergesti ligipääsetav (tingimuslik olemasolek reaalse IP-aadressiga). - Sõlme määramise, kuhu pod on üles tõstetud, jääb meie jutustuse piiridest välja. Ütlen vaid, et teenust saab kindlalt "kinni haakida" sõlmele või kirjutada väikese sidecar-teenuse, mis jälgib VPN-teenuse praegust IP-aadressi ja muudab kliente registreeritud DNS-kirjeid — kellel on kujutlust.
VPN-i IP-aadressi kaudu saame kliendi selgelt tuvastada. Allpool on primitiivne näide selle kliendi juurdepääsu piirangust, kasutades eespool mainitud Redis't:
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]Siin on port 6379 ühendamine rangelt keelatud, kuid samal ajal on DNS-teenus säilinud, mille toimivus kannatab sageli reeglite koostamisel. Sest nagu eelnevalt mainitud, rakendatakse sättega seoses vaikimisi keelu poliitikat, kui pole öeldud teisiti.
Kokkuvõte
Seega saab Calico laiendatud API abil paindlikult konfigureerida ja dünaamiliselt muuta marsruutimist klastris ja selle ümber. Üldiselt võib selle kasutamine tunduda nagu püssist varblaste peale laskmine, ning L3-võrgu juurutamine BGP- ja IP-IP-tunnelitega näeb välja monstrueus lihtsas Kubernetes'i tasandatud võrgus… Siiski näeb muu tööriist välja üsna elujõuline ja kasulik.
Klastri isoleerimine turvanõuete täitmiseks ei pruugi alati olla teostatav, ja just sellistel juhtudel tulebki appi Calico (või sarnane lahendus). Artiklis toodud näidiseid (veidi kohandatuna) kasutatakse mitmes meie klientide AWS-i paigalduses.
P.S.
Lugege ka meie blogist:
- «»;
- „Illustreeritud juhend Kuberneteses olevate võrkude seadistamiseks“: , ;
- «».
Allikas: habr.com
