
Opmerking vertaler.: De auteur van het artikel - Reuven Harrison - heeft meer dan 20 jaar ervaring in softwareontwikkeling en is momenteel technisch directeur en medeoprichter van Tufin, een bedrijf dat oplossingen voor het beheer van beveiligingsbeleid ontwikkelt. Hij beschouwt netwerkgroepen in Kubernetes als een krachtig middel voor netwerksegmentatie in clusters, maar gelooft tegelijkertijd dat ze in de praktijk niet zo eenvoudig toe te passen zijn. Dit vrij omvangrijke materiaal is bedoeld om de kennis van specialisten op dit gebied te verbeteren en hen te helpen bij het creëren van de noodzakelijke configuraties.
Vandaag de dag kiezen steeds meer bedrijven voor Kubernetes om hun applicaties te draaien. De belangstelling voor deze software is zo groot dat sommigen Kubernetes de 'nieuwe besturingssysteem voor datacenters' noemen. Geleidelijk begint Kubernetes (of k8s) te worden gezien als een cruciaal onderdeel van de business dat volwassen bedrijfsprocessen vereist, inclusief netwerkbeveiliging.
Voor beveiligingsspecialisten die worstelen met Kubernetes kan het standaardbeleid van dit platform een openbaring zijn: alles toestaan.
Deze gids helpt om inzicht te krijgen in de interne werking van netwerkbeleid; het zal duidelijk maken hoe ze verschillen van regels voor traditionele firewalls. Er zullen ook enkele valkuilen worden besproken en aanbevelingen worden gegeven die kunnen helpen bij het beveiligen van applicaties in Kubernetes.
Kubernetes netwerkbeleid
Het mechanisme van Kubernetes netwerkbeleid maakt het mogelijk om de interactie tussen applicaties die op het platform zijn uitgerold op netwerkniveau (laag drie in het OSI-model) te beheren. Netwerkbeleid mist bepaalde geavanceerde functies van moderne firewalls, zoals controle op laag 7 van het OSI-model en dreigingsdetectie, maar biedt een basisniveau van netwerkbeveiliging dat een goede startpunt vormt.
Netwerkbeleid controleert de communicatie tussen pods
Werkbelastingen in Kubernetes worden verdeeld over pods, die uit één of meerdere samen uitgerolde containers bestaan. Kubernetes kent elke pod een IP-adres toe dat toegankelijk is vanaf andere pods. Netwerkbeleid in Kubernetes definieert toegangsrechten voor groepen pods, op een manier die lijkt op hoe beveiligingsgroepen in de cloud worden gebruikt voor het beheer van toegang tot virtuele machine-instanties.
Definitie van netwerkbeleid
Net als andere Kubernetes-resources worden netwerkbeleidsregels gedefinieerd in YAML. In het onderstaande voorbeeld krijgt de applicatie balance toegang tot postgres:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default.postgres
namespace: default
spec:
podSelector:
matchLabels:
app: postgres
ingress:
- from:
- podSelector:
matchLabels:
app: balance
policyTypes:
- Ingress 
(Opmerking vertaler.: deze screenshot, evenals alle volgende soortgelijke, is gemaakt met behulp van een hulpmiddel van Tufin Orca, dat door het bedrijf van de auteur van het originele artikel is ontwikkeld en aan het einde van het materiaal wordt genoemd.
Voor het definiëren van uw eigen netwerkbeleid zijn basiskennis van YAML vereist. Deze taal is gebaseerd op inspringingen (gegeven door spaties en niet door tabs). Een element met inspringing behoort tot het dichtstbijzijnde element met inspringing boven hem. Een nieuw listelement begint met een koppelteken; alle andere elementen hebben de vorm van sleutel-waarde.
Nadat u het beleid in YAML heeft beschreven, gebruikt u , om het in het cluster aan te maken:
kubectl create -f policy.yamlSpecificatie van netwerkbeleid
De specificatie van netwerkbeleid in Kubernetes omvat vier elementen:
-
podSelector: definieert de pods die door dit beleid worden aangetast (doelen) - verplicht; -
policyTypes: geeft aan welke soorten beleid in dit zijn opgenomen: ingress en/of egress - optioneel, maar ik raad aan het in alle gevallen expliciet op te nemen; -
ingress: definieert het toegestaan inkomend verkeer naar de doelpods - optioneel; -
egress: definieert het toegestaan uitgaand verkeer van de doelpods - optioneel.
Een voorbeeld, ontleend aan de Kubernetes-website (ik heb role en een werkende opdracht krijgen. app), toont aan hoe alle vier elementen worden gebruikt:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: test-network-policy
namespace: default
spec:
podSelector: # <<<
matchLabels:
app: 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 

Let op dat het niet noodzakelijk is om alle vier de elementen op te nemen. Alleen podSelector, de andere parameters kunnen optioneel worden gebruikt.
Als je policyTypesweglaten, zal het beleid als volgt worden geïnterpreteerd:
- Standaard gaat men ervan uit dat het de ingress-zijde definieert. Als er geen expliciete aanwijzingen in het beleid zijn, beschouwt het systeem al het verkeer als verboden.
- Het gedrag aan de egress-zijde zal worden bepaald door de aanwezigheid of afwezigheid van de bijbehorende egress-parameter.
Om fouten te voorkomen, raad ik aan altijd expliciet aan te geven policyTypes.
Volgens de bovenstaande logica, als de parameters ingress and/or egress worden weggelaten, zal het beleid al het verkeer verbieden (zie de "Cleanup-regel" hieronder).
Het standaardbeleid is toestaan
Als er geen beleidsregels zijn gedefinieerd, staat Kubernetes standaard al het verkeer toe. Alle pods kunnen vrij informatie met elkaar uitwisselen. Vanuit beveiligingsoogpunt lijkt dit misschien onlogisch, maar herinner je dat Kubernetes oorspronkelijk werd ontwikkeld door ontwikkelaars om de interactie tussen applicaties te waarborgen. Netwerkbeleid werd later toegevoegd.
Namespaces
Namespaces zijn een mechanisme voor samenwerking binnen Kubernetes. Ze zijn bedoeld om logische omgevingen van elkaar te isoleren, terwijl gegevensuitwisseling tussen namespaces standaard is toegestaan.
Net als de meeste componenten van Kubernetes leven netwerkbeleid in een specifieke namespace. In het blok metadata kan worden vastgelegd aan welke namespace het beleid toebehoort:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: test-network-policy
namespace: my-namespace # <<<
spec:
... Als de namespace in de metadata niet expliciet is opgegeven, zal het systeem de namespace gebruiken die is opgegeven in kubectl (standaard namespace=default):
kubectl apply -n my-namespace -f namespace.yamlIk raad aan de namespace expliciet aan te geven, tenzij u een beleid schrijft dat bedoeld is voor meerdere namespaces.
Hoofd element podSelector in het beleid zal pods selecteren uit de namespace waartoe het beleid behoort (het heeft geen toegang tot pods uit andere namespaces).
Evenzo kunnen podSelectors in de ingress- en egress-blokken alleen pods selecteren uit hun eigen namespace, tenzij u ze combineert met namespaceSelector (hierover wordt gesproken in het gedeelte 'Filteren op namespaces en pods').
Naamgevingsregels voor beleid
Beleidsnamen zijn uniek binnen één namespace. Er kunnen geen twee beleidsdocumenten met dezelfde naam in één namespace zijn, maar het is mogelijk om beleidsdocumenten met dezelfde namen in verschillende namespaces te hebben. Dit is handig wanneer u hetzelfde beleid wilt hergebruiken in meerdere namespaces.
Een van de naamgevingswijzen die ik bijzonder leuk vind, bestaat uit het combineren van de naam van de namespace met de doel-pods. Bijvoorbeeld:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default.postgres # <<<
namespace: default
spec:
podSelector:
matchLabels:
app: postgres
ingress:
- from:
- podSelector:
matchLabels:
app: admin
policyTypes:
- Ingress 
Labels
Aan Kubernetes-objecten, zoals pods en namespaces, kunnen aangepaste labels worden gehecht. Labels (labels — tags) zijn het equivalent van tags in de cloud. Netwerkbeleidsdocumenten van Kubernetes gebruiken labels om te selecteren pods, waaraan zij worden toegepast:
podSelector:
matchLabels:
role: db… of namespaces, waaraan zij worden toegepast. In dit voorbeeld worden alle pods in namespaces met de bijbehorende labels geselecteerd:
namespaceSelector:
matchLabels:
project: myproject Een waarschuwing: wanneer u namespaceSelector zorg ervoor dat de geselecteerde namespaces de juiste label bevatten.Houd er rekening mee dat ingebouwde namespaces, zoals default en kube-system, standaard geen labels bevatten.
U kunt een label aan een namespace toevoegen op de volgende manier:
kubectl label namespace default namespace=default Hierbij moet de namespace in het gedeelte metadata verwijzen naar de feitelijke naam van de namespace en niet naar het label:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: test-network-policy
namespace: default # <<<
spec:
...Bron en ontvanger
Beleid voor firewalls bestaat uit regels met bronnen en bestemmingen. Netwerkbeleid in Kubernetes wordt gedefinieerd voor een doel — een set van pods waarop ze van toepassing zijn, en voert vervolgens regels in voor inkomend (ingress) en/of uitgaand (egress) verkeer. In ons voorbeeld is het doel van het beleid alle pods in de namespace met het label met de sleutel default apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: test-network-policy namespace: default spec: podSelector: matchLabels: app: 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 app en waarde. . Service-meshen lossen dergelijke problemen meestal op met behulp van mTLS: certificaten fungeren in dit geval als de noodzakelijke identificatie.:
Sectie 

in dit beleid opent het inkomende verkeer naar de doelpods. Met andere woorden, ingress is de bron, en het doel is de overeenkomstige bestemming. Evenzo is egress de bestemming, en het doel is de bron. ingress Dit komt overeen met twee regels voor de firewall: Ingress → Doel; Doel → Egress.

Egress en DNS (belangrijk!)
Bij het beperken van uitgaand verkeer,
let vooral op DNS — Kubernetes gebruikt deze service om services met IP-adressen te koppelen. Bijvoorbeeld, het volgende beleid zal niet werken omdat je de applicatie niet hebt toegestaan om verbinding te maken met DNS: balance apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: default.balance namespace: default spec: podSelector: matchLabels: app: balance egress: - to: - podSelector: matchLabels: app: postgres policyTypes: - Egress
Dit kan worden opgelost door toegang tot de DNS-service te verlenen: 
apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: default.balance namespace: default spec: podSelector: matchLabels: app: balance egress: - to: - podSelector: matchLabels: app: postgres - to: # <<< ports: # <<< - protocol: UDP # <<< port: 53 # <<< policyTypes: - Egress
Het laatste element 
to — is leeg, en kiest daardoor indirect alle pods in alle namespaces , wat het mogelijk maaktom DNS-verzoeken naar de overeenkomstige Kubernetes-service te sturen (die meestal draait in de namespace balance Deze aanpak werkt, maar is kube-system).
overmatig permissief en onveilig , omdat het DNS-verzoeken buiten de cluster mogelijk maakt.Het kan worden verbeterd in drie opeenvolgende stappen.
1. Sta DNS-verzoeken alleen toe
voor de cluster door toe te voegen binnenin clusters, toegevoegen namespaceSelector:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default.balance
namespace: default
spec:
podSelector:
matchLabels:
app: balance
egress:
- to:
- podSelector:
matchLabels:
app: postgres
- to:
- namespaceSelector: {} # <<<
ports:
- protocol: UDP
port: 53
policyTypes:
- Egress 
2. Sta DNS-verzoeken alleen toe in de namespace kube-system.
Hiervoor moet je een label aan de namespace toevoegen kube-system: kubectl label namespace kube-system namespace=kube-system — en dit opnemen in het beleid met behulp van namespaceSelector:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default.balance
namespace: default
spec:
podSelector:
matchLabels:
app: balance
egress:
- to:
- podSelector:
matchLabels:
app: postgres
- to:
- namespaceSelector: # <<<
matchLabels: # <<<
namespace: kube-system # <<<
ports:
- protocol: UDP
port: 53
policyTypes:
- Egress 
3. Paranoïden kunnen nog verder gaan en DNS-verzoeken beperken tot een specifieke DNS-service in kube-system. In het gedeelte 'Filteren op namespaces en pods' wordt uitgelegd hoe dat te bereiken.
Een andere optie is om DNS op namespace-niveau toe te staan. In dit geval hoeft het niet voor elke service te worden geopend:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default.dns
namespace: default
spec:
podSelector: {} # <<<
egress:
- to:
- namespaceSelector: {}
ports:
- protocol: UDP
port: 53
policyTypes:
- Egress Leeg podSelector selecteert alle pods in de namespace.

Eerste overeenkomst en volgorde van regels
In reguliere firewalls wordt de actie ('Toestaan' of 'Blokkeren') met betrekking tot een pakket bepaald door de eerste regel die van toepassing is. In Kubernetes is de volgorde van beleidsregels niet van belang.
Standaard is, wanneer er geen beleidsregels zijn ingesteld, de communicatie tussen pods toegestaan en kunnen ze vrij informatie uitwisselen. Zodra je begint met het formuleren van beleidsregels, wordt elke pod die door een van hen is aangetast, geïsoleerd in overeenstemming met de disjunctie (logische OF) van alle beleidsregels die op hem van toepassing zijn. Pods die niet door een beleidsregel zijn aangetast, blijven open.
Dit gedrag kan worden gewijzigd met behulp van een opruimregel.
Opruimregel ('Blokkeren')
Beleidsregels van firewalls blokkeren doorgaans al het verkeer dat niet expliciet is toegestaan.
In Kubernetes is er geen actie 'blokkeren' (deny), maar een vergelijkbaar effect kan worden bereikt met een reguliere (toelatende) beleidsregel door een lege groep inkomende pods (ingress) te kiezen:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: deny-all
namespace: default
spec:
podSelector: {}
policyTypes:
- Ingress 
Dit beleid selecteert alle pods in de naamruimte en laat ingress onbepaald, waardoor al het binnenkomende verkeer wordt verboden.
Op dezelfde manier kan al het uitgaande verkeer uit de naamruimte worden beperkt:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: deny-all-egress
namespace: default
spec:
podSelector: {}
policyTypes:
- Egress 
Houd er rekening mee dat alle extra beleidsregels die verkeer naar pods in de naamruimte toestaan, prioriteit hebben boven deze regel (vergelijkbaar met het toevoegen van een toestemmingsregel vóór een verbod in de firewallconfiguratie).
Sta alles toe (Any-Any-Any-Allow)
Om een "Sta alles toe" beleid te maken, moet de bovenstaande verbodspolitiek worden aangevuld met een leeg element ingress:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-all
namespace: default
spec:
podSelector: {}
ingress: # <<<
- {} # <<<
policyTypes:
- Ingress 
Het opent toegang van alle pods in alle naamruimten (en alle IP's) naar elke pod in de naamruimte default. Dit gedrag is standaard ingeschakeld, dus meestal hoeft dit niet verder gedefinieerd te worden. Soms kan het echter nodig zijn om specifieke toegangen tijdelijk uit te schakelen om een probleem te diagnosticeren.
De regel kan worden ingeperkt en toegang alleen toestaan tot een specifieke set pods (app:balance) in de naamruimte default:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-all-to-balance
namespace: default
spec:
podSelector:
matchLabels:
app: balance
ingress:
- {}
policyTypes:
- Ingress 
Het volgende beleid staat al het binnenkomende (ingress) en uitgaande (egress) verkeer toe, inclusief toegang tot elk IP buiten de cluster:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-all
spec:
podSelector: {}
ingress:
- {}
egress:
- {}
policyTypes:
- Ingress
- Egress 

Combineren van meerdere beleidsregels
Beleidsregels worden gecombineerd met behulp van logische OF op drie niveaus; toestemmingen voor elke pod worden vastgesteld op basis van de disjunctie van alle beleidsregels die van toepassing zijn:
1. In de velden van en — is leeg, en kiest daardoor indirect kunnen drie soorten elementen worden gedefinieerd (allemaal worden ze gecombineerd met behulp van OF):
-
namespaceSelector— selecteert de hele naamruimte; -
podSelector— selecteert pods; -
ipBlock— selecteert een subnet.
In dit geval is het aantal elementen (zelfs dezelfde) in subsecties van/— is leeg, en kiest daardoor indirect niet beperkt. Ze worden allemaal samengevoegd met een logische OF.
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default.postgres
namespace: default
spec:
ingress:
- from:
- podSelector:
matchLabels:
app: indexer
- podSelector:
matchLabels:
app: admin
podSelector:
matchLabels:
app: postgres
policyTypes:
- Ingress 
2. Binnen een beleidsectie ingress kan het meerdere elementen bevatten van (samengevoegd met een logische OF). Op soortgelijke wijze kan een sectie egress meerdere elementen bevatten — is leeg, en kiest daardoor indirect (ook samengevoegd met een disjunctie):
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default.postgres
namespace: default
spec:
ingress:
- from:
- podSelector:
matchLabels:
app: indexer
- from:
- podSelector:
matchLabels:
app: admin
podSelector:
matchLabels:
app: postgres
policyTypes:
- Ingress 
3. Verschillende beleidsregels worden ook samengevoegd met een logische OF
Maar bij het combineren zijn er beperkingen waaraan : Kubernetes kan alleen beleidsregels combineren die verschillend zijn policyTypes (Ingress of Egress). Beleidsregels die ingress (of egress) definiëren, zullen elkaar overschrijven.
De relatie tussen namespaces
Standaard is informatie-uitwisseling tussen namespaces toegestaan. Dit kan worden gewijzigd met een beperkend beleid dat de uitgaande en/of inkomende verkeer naar een namespace beperkt (zie 'Clearance regel' hierboven).
Door de toegang tot een namespace te blokkeren (zie 'Clearance regel' hierboven), kunt u uitzonderingen maken in het beperkende beleid door verbindingen vanuit een bepaalde namespace toe te staan met namespaceSelector:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: database.postgres
namespace: database
spec:
podSelector:
matchLabels:
app: postgres
ingress:
- from:
- namespaceSelector: # <<<
matchLabels:
namespace: default
policyTypes:
- Ingress 
Als gevolg hiervan krijgen alle pods in de namespace default toegang tot de pods postgres in de namespace database. Maar wat als u toegang wilt geven aan postgres slechts specifieke pods in de namespace default?
Filteren op namespaces en pods
Kubernetes versie 1.11 en hoger staat toe dat operatoren worden gecombineerd namespaceSelector en podSelector met een logische EN. Dit ziet er als volgt uit:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: database.postgres
namespace: database
spec:
podSelector:
matchLabels:
app: postgres
ingress:
- from:
- namespaceSelector:
matchLabels:
namespace: default
podSelector: # <<<
matchLabels:
app: admin
policyTypes:
- Ingress 
Waarom wordt dit geïnterpreteerd als EN in plaats van de gebruikelijke OF?
Let op dat podSelector begint niet met een streepje. In YAML betekent dit dat podSelector en het voorafgaande element namespaceSelector tot hetzelfde lijstitem behoren. Daarom worden ze samengevoegd met een logische EN.
Een dash toevoegen voor podSelector leidt tot het ontstaan van een nieuw lijstitem, dat zal worden gecombineerd met het voorgaande namespaceSelector met behulp van logische OF.
Om pods met een bepaalde label te kiezen in alle namespaces, typ leeg namespaceSelector:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: database.postgres
namespace: database
spec:
podSelector:
matchLabels:
app: postgres
ingress:
- from:
- namespaceSelector: {}
podSelector:
matchLabels:
app: admin
policyTypes:
- Ingress 
Meerdere labels worden gecombineerd met EN
Regels voor de firewall met meerdere objecten (hosts, netwerken, groepen) worden gecombineerd met logische OF. De volgende regel wordt geactiveerd als de pakketbron overeenkomt met Host_1 OF Host_2:
| Bron | Bestemming | Dienst | Actie |
| ----------------------------------------|
| Host_1 | Subnet_A | HTTPS | Toestaan |
| Host_2 | | | |
| ----------------------------------------| Daarentegen worden in Kubernetes verschillende labels podSelector of namespaceSelector samengevoegd met logische EN. Bijvoorbeeld, de volgende regel zal pods selecteren die beide labels hebben, role=db En version=v2:
podSelector:
matchLabels:
role: db
version: v2Dezelfde logica is van toepassing op alle soorten operatoren: beleidsdoel selectors, pod selectors en namespace selectors.
Subnetten en IP-adressen (IPBlocks)
Voor netwerksegmentatie gebruiken firewalls VLAN's, IP-adressen en subnetten.
In Kubernetes worden IP-adressen automatisch toegekend aan pods en kunnen vaak veranderen, daarom worden labels gebruikt voor het selecteren van pods en namespaces in netwerkbeleid.
Subnetten (ipBlocks) worden gebruikt bij het beheren van binnenkomende (ingress) of uitgaande (egress) externe (North-South) verbindingen. Bijvoorbeeld, dit beleid geeft alle pods in de namespace default toegang tot de DNS-service van Google:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: egress-dns
namespace: default
spec:
podSelector: {}
policyTypes:
- Egress
egress:
- to:
- ipBlock:
cidr: 8.8.8.8/32
ports:
- protocol: UDP
port: 53 
Een lege pod selector in dit voorbeeld betekent "selecteer alle pods in de namespace".
Dit beleid staat alleen toegang toe tot 8.8.8.8; toegang tot elk ander IP is verboden. Hierdoor heeft u in wezen de toegang tot de interne DNS-service van Kubernetes geblokkeerd. Als u deze toch wilt toestaan, geef dat dan expliciet aan.
Normaal ipBlocks en podSelectors zijn wederzijds exclusief, aangezien interne IP-adressen van pods niet worden gebruikt in ipBlocks. Door interne IP's van pods op te geven, u geeft eigenlijk verbindingen toe van/naar pods met deze adressen. In de praktijk weet u niet welk IP-adres te gebruiken, daarom is het niet aan te raden ze te gebruiken om pods te selecteren.
Als een tegenvoorbeeld omvat het volgende beleid alle IP's en staat het dus toegang toe tot alle andere pods:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: egress-any
namespace: default
spec:
podSelector: {}
policyTypes:
- Egress
egress:
- to:
- ipBlock:
cidr: 0.0.0.0/0 
Toegang kan alleen worden verleend tot externe IP's, waarbij interne IP-adressen van pods worden uitgesloten. Bijvoorbeeld, als uw pod-subnet 10.16.0.0/14 is:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: egress-any
namespace: default
spec:
podSelector: {}
policyTypes:
- Egress
egress:
- to:
- ipBlock:
cidr: 0.0.0.0/0
except:
- 10.16.0.0/14 
Poorten en protocollen
Over het algemeen luisteren pods naar één poort. Dit betekent dat u de poortnummers in de beleidsregels gewoon kunt weglaten en alles op de standaardinstellingen kunt laten. Echter, het is aan te raden om de beleidsregels zo restrictief mogelijk te maken, dus in sommige gevallen kunt u wel poorten opgeven:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default.postgres
namespace: default
spec:
ingress:
- from:
- podSelector:
matchLabels:
app: indexer
- podSelector:
matchLabels:
app: admin
ports: # <<<
- port: 443 # <<<
protocol: TCP # <<<
- port: 80 # <<<
protocol: TCP # <<<
podSelector:
matchLabels:
app: postgres
policyTypes:
- Ingress 
Let op dat de selector poorten toegepast wordt op alle elementen in het blok — is leeg, en kiest daardoor indirect of van, waarin het zich bevindt. Om verschillende poorten voor verschillende sets elementen op te geven, splitst u ingress of egress in verschillende subsecties met — is leeg, en kiest daardoor indirect of van en schrijft u in elke sectie uw eigen poorten op:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default.postgres
namespace: default
spec:
ingress:
- from:
- podSelector:
matchLabels:
app: indexer
ports: # <<<
- port: 443 # <<<
protocol: TCP # <<<
- from:
- podSelector:
matchLabels:
app: admin
ports: # <<<
- port: 80 # <<<
protocol: TCP # <<<
podSelector:
matchLabels:
app: postgres
policyTypes:
- Ingress 
Standaardpoortwerking:
- Als u de poortdefinities volledig weglaat (
poorten), betekent dit alle protocollen en alle poorten; - Als u de protocoldefinitie weglaat (
protocol), betekent dit TCP; - Als u de poortdefinitie weglaat (
port), betekent dit alle poorten.
Best practice: vertrouw niet op standaardwaarden, geef expliciet de waarden op die u nodig heeft.
Let op dat je de ports van pods moet gebruiken en niet die van services (meer hierover in de volgende paragraaf).
Zijn de beleidsregels gedefinieerd voor pods of services?
Gewoonlijk communiceren pods in Kubernetes met elkaar via een service - een virtuele load balancer die het verkeer naar de pods die de service implementeren omleidt. Je zou kunnen denken dat netwerkbeleidsregels de toegang tot de services controleren, maar dat is niet het geval. Netwerkbeleidsregels in Kubernetes werken met de ports van pods en niet met die van services.
Bijvoorbeeld, als een service luistert op poort 80, maar het verkeer omleidt naar poort 8080 van zijn pods, dan moet in de netwerkpolitiek precies 8080 worden opgegeven.
Een dergelijk mechanisme wordt als suboptimaal beschouwd: bij het veranderen van de interne structuur van de service (wiens ports door de pods worden geluisterd) moeten netwerkbeleidsregels worden bijgewerkt.
Een nieuwe architecturale aanpak met behulp van Service Mesh (bijvoorbeeld, zie Istio hieronder — opmerking van de vertaler) maakt het mogelijk om met dit probleem om te gaan.
Moet zowel Ingress als Egress worden gespecificeerd?
Het korte antwoord is ja, zodat pod A verbinding kan maken met pod B, moet het toestemming krijgen om een uitgaande verbinding te maken (hiervoor moet een egress-beleid worden ingesteld), en pod B moet in staat zijn om een inkomende verbinding te accepteren (hiervoor is een ingress-beleid nodig).
Echter, in de praktijk kan men vertrouwen op het standaardbeleid dat verbindingen in een of beide richtingen toestaat.
Als een bepaalde podbron wordt geselecteerd door een of meerdere egress-beleidsregels, worden de aan hem opgelegde beperkingen bepaald door hun disjunctie. In dit geval moet expliciet toestemming worden gegeven voor verbinding met pod-de ontvanger.. Als de pod niet door een beleid is geselecteerd, is zijn uitgaande (egress) verkeer standaard toegestaan.
Evenzo zal de status van de pod-de ontvanger, geselecteerd door een of meerdere-beleidsregels, worden bepaald door hun disjunctie. In dit geval moet expliciet worden toegestaan dat hij verkeer ontvangt van de pod-bron. Als de pod niet door een beleid is geselecteerd, is al het inkomende (ingress) verkeer voor hem standaard toegestaan. ingressZie het punt "Stateful of Stateless" hieronder.
Netwerkbeleidsregels in Kubernetes kunnen het verkeer niet loggen. Dit bemoeilijkt het vaststellen of het beleid correct functioneert en bemoeilijkt de veiligheidsanalyse aanzienlijk.
Logs
Controle over verkeer naar externe services.
Monitoring van verkeer naar externe diensten
Kubernetes-netwerkbeleid staat niet toe om een volledig domeinnaam (DNS) op te geven in egress-secties. Dit resulteert in aanzienlijke ongemakken bij het proberen te beperken van het verkeer naar externe bestemmingen zonder vast IP-adres (zoals aws.com).
Beleid controle
Firewalls zullen je waarschuwen of zelfs een fout beleid weigeren. Kubernetes voert ook enige validatie uit. Wanneer je een netwerkbeleid via kubectl instelt, kan Kubernetes aangeven dat het onjuist is en het weigeren te accepteren. In andere gevallen accepteert Kubernetes het beleid en vult het ontbrekende details aan. Deze zijn te zien met het commando:
kubernetes get networkpolicy -o yamlHoud er rekening mee dat de verificatiesysteem van Kubernetes niet onfeilbaar is en sommige soorten fouten kan missen.
Uitvoering
Kubernetes implementeert het netwerkbeleid niet zelf, maar fungeert alleen als een API-gateway die de lastige taak van controle overlaat aan een onderliggend systeem dat de Container Networking Interface (CNI) wordt genoemd. Het instellen van beleid in een Kubernetes-cluster zonder de juiste CNI is vergelijkbaar met het maken van beleid op een firewall-beheerder zonder deze vervolgens in de firewalls te installeren. Je moet zelf zorgen voor een geschikte CNI of, in het geval van Kubernetes-platforms in de cloud, (met een lijst van providers beschikbaar — vert. opm.), activeer netwerkbeleid dat CNI voor je instelt.
Let op, Kubernetes waarschuwt je niet als je een netwerkbeleid instelt zonder de juiste ondersteunende CNI.
Stateful of Stateless?
Alle Kubernetes CNI's waarmee ik te maken heb gehad, zijn stateful (bijvoorbeeld Calico gebruikt Linux conntrack). Dit stelt een pod in staat om antwoorden te ontvangen op de door hem geïnitieerde TCP-verbinding zonder deze opnieuw te hoeven opzetten. Voor zover ik weet, is er geen Kubernetes-standaard die de opslag van staat (statefulness) garandeert.
Geavanceerd beheer van beveiligingsbeleid
Hier zijn enkele manieren om de effectiviteit van het beveiligingsbeleid in Kubernetes te verbeteren:
- Het architecturale patroon Service Mesh maakt gebruik van sidecar-containers voor gedetailleerde telemetrie en verkeerscontrole op serviceniveau. Als voorbeeld kan worden genomen .
- Sommige CNI-leveranciers hebben hun tools uitgebreid om verder te gaan dan de netwerkbeleidsregels van Kubernetes.
- biedt transparantie en automatisering van de netwerkbeleidsregels van Kubernetes.
Het Tufin Orca-pakket beheert de netwerkbeleidsregels van Kubernetes (en dient als bron voor de hierboven weergegeven screenshots).
Aanvullende informatie
- ;
- ;
- ;
- .
Conclusie
Netwerkbeleidsregels van Kubernetes bieden een behoorlijke set tools voor het segmenteren van clusters, maar zijn intuïtief moeilijk te begrijpen en hebben veel nuances. Ik denk dat door deze complexiteit veel bestaande clusters fouten bevatten. Mogelijke oplossingen voor dit probleem zijn het automatiseren van beleidsdefinities of het toepassen van andere segmentatietools.
Ik hoop dat deze handleiding helpt om enkele vragen te verhelderen en problemen op te lossen waarmee je kunt worden geconfronteerd.
P.S. van de vertaler
Lees ook op onze blog:
- «Terug naar microservices met Istio»: , , ;
- «Geïllustreerde handleiding voor netwerkconfiguratie in Kubernetes»: , ;
- «»;
- «»;
- «».
Bron: habr.com
