
Bem. overs.: Artiklen er skrevet af Reuven Harrison, som har over 20 års erfaring med softwareudvikling og i dag er teknisk direktør og medstifter af Tufin, der udvikler løsninger til håndtering af sikkerhedspolitikker. Selvom han betragter netværkspolitikker i Kubernetes som et kraftfuldt redskab til netværkssegmentering i klynger, mener han samtidig, at de ikke er så nemme at anvende i praksis. Dette materiale (som er ret omfattende) har til formål at øge bevidstheden hos fagfolk om emnet og hjælpe dem med at skabe de nødvendige konfigurationer.
I dag vælger mange virksomheder i stigende grad Kubernetes til at køre deres applikationer. Interessen for denne software er så stor, at nogle kalder Kubernetes "det nye operativsystem for datacentre". Langsomt men sikkert begynder Kubernetes (eller k8s) at blive opfattet som en kritisk vigtig del af forretningen, der kræver etablering af modne forretningsprocesser, herunder sikring af netværkssikkerhed.
For sikkerhedsspecialister, der er foruroliget over arbejdet med Kubernetes, kan standardpolitikken for denne platform være en øjenåbner: tillad alt.
Denne vejledning vil hjælpe med at forstå det indre arbejde af netværkspolitikker; forstå forskellene fra regler for almindelige firewall. Der vil også blive diskuteret nogle faldgruber, og der gives anbefalinger, som kan hjælpe med at beskytte applikationer i Kubernetes.
Kubernetes-netværkspolitikker
Mechanismen for Kubernetes-netværkspolitikker gør det muligt at styre interaktionen mellem applikationer implementeret på platformen på netværksniveau (det tredje niveau i OSI-modellen). Netværkspolitikker mangler nogle af de avancerede funktioner fra moderne firewalls, såsom kontrol på niveau 7 i OSI og trusselsopdagelse, men de leverer et grundlæggende niveau af netværkssikkerhed, som er en god start.
Netværkspolitikker kontrollerer kommunikationen mellem pod'ene
Arbejdsbelastninger i Kubernetes fordeles mellem pods, der består af en eller flere containere, som kører sammen. Kubernetes tildeler hver pod en IP-adresse, der er tilgængelig fra andre pods. Kubernetes-netværkspolitikker definerer adgangsrettigheder for grupper af pods på samme måde, som sikkerhedsgrupper i skyen bruges til at styre adgangen til virtuelle maskiner.
Definition af netværkspolitikker
Som andre Kubernetes-ressourcer defineres netværkspolitikker i YAML-sprog. I det følgende eksempel får anvendelsen balance adgang til 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 
(Bem. overs.: dette screenshot, ligesom alle følgende lignende, er skabt ved hjælp af værktøjet Tufin Orca, som er udviklet af forfatteren til den oprindelige artikel og nævnes i slutningen af materialet.)
For at definere en egen netværkspolitik kræves grundlæggende kendskab til YAML. Dette sprog er baseret på indrykning (som skal angives med mellemrum, ikke tabulatorer). Et element med indrykning tilhører det nærmeste overliggende element med indrykning. Et nyt listeelement starter med en bindestreg, og alle andre elementer fremstår som nøgle-værdi.
Når du har beskrevet politikken i YAML, skal du bruge , for at oprette den i klyngen:
kubectl create -f policy.yamlSpecifikation af netværkspolitik
Specifikationen af Kubernetes-netværkspolitikken består af fire elementer:
-
podSelector: definerer de pods, der omfattes af denne politik (mål) - obligatorisk; -
policyTypes: angiver, hvilke typer politikker der er inkluderet: ingress og/eller egress - valgfrit, men jeg anbefaler at skrive det klart i alle tilfælde; -
ingress: definerer den tilladte indgående trafik til de målrettede pods - valgfrit; -
egress: definerer den tilladte udgående trafik fra de målrettede pods - valgfrit.
Et eksempel hentet fra Kubernetes' hjemmeside (jeg har ændret rolle og få en fungerende kommando. app), viser hvordan alle fire elementer anvendes:
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 

Bemærk, at det ikke er obligatorisk at inkludere alle fire elementer. Kun podSelectorer nødvendigt, mens de øvrige parametre kan bruges valgfrit.
Hvis du udelader policyTypes, vil politikken blive fortolket som følger:
- Som standard antages det, at den definerer ingress-siden. Hvis der ikke er eksplicitte angivelser i politikken, vil systemet betragte al trafik som forbudt.
- Adfærden på egress-siden bestemmes af tilstedeværelsen eller fraværet af den tilsvarende egress-parameter.
For at undgå fejl anbefaler jeg altid at angive eksplicit policyTypes.
I overensstemmelse med den ovenstående logik, hvis parametrene ingress og/eller egress udelades, vil politikken forbyde al trafik (se "Rydningsregel" nedenfor).
Standardpolitikken er at tillade
Hvis der ikke er defineret politikker, tillader Kubernetes som standard al trafik. Alle pods kan frit kommunikere indbyrdes. Set fra et sikkerhedsperspektiv kan det synes illogisk, men husk at Kubernetes oprindeligt blev skabt af udviklerne med det formål at muliggøre interaktion mellem applikationer. Netværkspolitikker blev tilføjet senere.
Navnerum
Navnerum (Namespaces) er et mekanisme til kollektivt arbejde i Kubernetes. De er beregnet til at isolere logiske miljøer fra hinanden, mens dataudveksling mellem navnerum som standard er tilladt.
Som med de fleste Kubernetes-komponenter lever netværkspolitikker i et bestemt navnerum. I blokken metadata kan du angive, hvilket navnerum politikken tilhører:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: test-network-policy
namespace: my-namespace # <<<
spec:
... Hvis navnerummet i metadata ikke er angivet eksplicit, vil systemet bruge det navnerum, der er angivet i kubectl (som standard namespace=default):
kubectl apply -n my-namespace -f namespace.yamlJeg anbefaler eksplicit at angive navnerummet, medmindre du skriver en politik, der er beregnet til flere navnerum på én gang.
Primær element podSelector i politikken vil vælge pods fra det navnerum, som politikken tilhører (den har ikke adgang til pods fra andre navnerum).
Tilsvarende kan podSelectors i ingress- og egress-blokke kun vælge pods fra deres eget navnerum, medmindre du sammenkæder dem ved hjælp af namespaceSelector (dette vil blive diskuteret i sektionen “Filtrering efter navnerum og pods”).
Navngivningsregler for politikker
Politiknavnene er unikke inden for et enkelt navnerum. Der kan ikke være to politikker med samme navn i ét navnerum, men der kan være politikker med samme navne i forskellige navnerum. Dette er praktisk, når du vil genbruge den samme politik på flere navnerum.
Jeg kan især godt lide en af måderne at navngive på. Den går ud på at kombinere navnet på navnerummet med de målrettede pods. For eksempel:
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
Brugerdefinerede labels kan knyttes til Kubernetes-objekter såsom pods og navnerum. Labels (labels — etiketter) svarer til tags i skyen. Kubernetes netværkspolitikker bruger labels til at vælge pods, som de anvendes på:
podSelector:
matchLabels:
role: db… eller navnerum, som de anvendes på. I dette eksempel vælges alle pods i navnerum med de tilsvarende labels:
namespaceSelector:
matchLabels:
project: myproject Én advarsel: når du bruger namespaceSelector skal du sikre dig, at de valgte navnerum indeholder den ønskede label. Vær opmærksom på, at indbyggede navnerum, såsom default og kube-system, som standard ikke indeholder labels.
For at tilføje en label til et navnerum kan du gøre følgende:
kubectl label namespace default namespace=default Her skal namespace i sektionen metadata henvise til det faktiske navn på navnerummet og ikke til labelen:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: test-network-policy
namespace: default # <<<
spec:
...Kilde og modtager
Firewall-politikker består af regler med kilder og modtagere. Netværkspolitikker i Kubernetes defineres for et mål - et sæt pod'er, som de anvendes på, og etablerer derefter regler for indgående (ingress) og/eller udgående (egress) trafik. I vores eksempel vil målet for politikken være alle pod'er i navnerummet default med et label med nøgle app og værdi db:
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 

Underafsnit ingress i denne politik åbner indgående trafik til mål-pod'erne. Med andre ord fungerer ingress som kilde, og målet er den tilsvarende modtager. Tilsvarende er egress modtageren, og målet er dens kilde.

Dette svarer til to firewall-regler: Ingress → Mål; Mål → Egress.
Egress og DNS (vigtigt!)
Når du begrænser udgående trafik, særligt vær opmærksom på DNS — Kubernetes bruger denne tjeneste til at kortlægge tjenester til IP-adresser. For eksempel vil følgende politik ikke fungere, da du ikke har tilladt applikationen balance at få adgang til DNS:
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 
Du kan rette det ved at åbne for adgangen til DNS-tjenesten:
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 
Det sidste element til — er tomt, og derfor vælger det indirekte alle pod'er i alle navnerum, hvilket tillader balance at sende DNS-forespørgsler til den relevante Kubernetes-tjeneste (den kører typisk i navnerummet kube-system).
Denne tilgang fungerer, men den er alt for tilladende og usikker, da den tillader at sende DNS-forespørgsler udenfor klyngen.
Det kan forbedres i tre trin.
1. Tillad DNS-forespørgsler kun indenfor klyngen ved at tilføje 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. Tillad DNS-forespørgsler kun inden for navnerummet kube-system.
For dette skal du tilføje et label til navnerummet kube-system: kubectl label namespace kube-system namespace=kube-system — og angive det i politikken ved hjælp af 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. Paranoide kan gå endnu længere og begrænse DNS-forespørgsler til en bestemt DNS-tjeneste i kube-system. I sektionen "Filtrer efter navnerum og pods" vil det blive forklaret, hvordan dette kan gøres.
En anden mulighed er at tillade DNS på navnerumsniveau. I så fald behøver det ikke at åbnes for hver tjeneste:
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 Tom podSelector vælger alle pods i navnerummet.

Den første overensstemmelse og rækkefølge for regler
I almindelige firewalls bestemmes handlingen ("Tillad" eller "Forbyd") for en pakke af den første regel, den opfylder. I Kubernetes har rækkefølgen af politikker ingen betydning.
Som standard, når der ikke er nogen politikker defineret, er kommunikation mellem pods tilladt, og de kan frit udveksle oplysninger. Så snart du begynder at formulere politikker, bliver hver pod, der berøres af mindst en af dem, isoleret i henhold til disjunktion (logisk ELLER) af alle politikker, der vælger den. Pods, der ikke påvirkes af nogen politik, forbliver åbne.
Denne adfærd kan ændres med et rydderegulativ.
Rydde-regulativet ("Forbyd")
Firewall-politikker forbyder normalt enhver trafik, der ikke er eksplicit tilladt.
I Kubernetes findes der ikke nogen handling "forbyd" (deny),, men en tilsvarende effekt kan opnås med en almindelig (tilladende) politik ved at vælge en tom gruppe af pod-kilder (ingress):
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: deny-all
namespace: default
spec:
podSelector: {}
policyTypes:
- Ingress 
Denne politik vælger alle pods i navnerummet og lader ingress være udefineret, hvilket forbyder al indgående trafik.
På samme måde kan man begrænse al udgående trafik fra navnerummet:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: deny-all-egress
namespace: default
spec:
podSelector: {}
policyTypes:
- Egress 
Bemærk, at enhver yderligere politik, der tillader trafik til pods i navnerummet, vil have prioritet over denne regel (svarende til at tilføje en tilladende regel før en forbudt i firewall-konfigurationen).
Tillad alt (Any-Any-Any-Allow)
For at oprette en "Tillad alt" politik, skal du supplere ovenstående forbudspolitik med et tomt element ingress:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-all
namespace: default
spec:
podSelector: {}
ingress: # <<<
- {} # <<<
policyTypes:
- Ingress 
Den åbner adgang fra alle pods i alle navnerum (og alle IP-adresser) til enhver pod i navnerummet default. Denne adfærd er aktiveret som standard, så normalt behøver den ikke at blive defineret yderligere. Dog kan det nogle gange være nødvendigt midlertidigt at deaktivere nogle specifikke tilladelser for at diagnosticere et problem.
Reglen kan indsnævres og tillade adgang kun til et bestemt sæt pods (app:balance) i navnerummet default:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-all-to-balance
namespace: default
spec:
podSelector:
matchLabels:
app: balance
ingress:
- {}
policyTypes:
- Ingress 
Den følgende politik tillader al indgående (ingress) og udgående (egress) trafik, inklusive adgang til enhver IP uden for klyngen:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-all
spec:
podSelector: {}
ingress:
- {}
egress:
- {}
policyTypes:
- Ingress
- Egress 

Kombinering af flere politikker
Politikker kombineres ved hjælp af logisk ELLER på tre niveauer; tilladelserne for hver pod er baseret på disjunktion af alle politikker, der påvirker dem:
1. I felterne fra og til kan du definere tre typer elementer (alle kombineres med ELLER):
-
namespaceSelector— vælger navnerummet som helhed; -
podSelector— vælger pods; -
ipBlock— vælger subnet.
Der er ingen grænse for antallet af elementer (selv de samme) i underafsnit fra/til Alle vil blive kombineret logisk ELLER.
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. Inden for politikafsnittet ingress kan der være mange elementer fra (kombineres med logisk ELLER). Tilsvarende kan afsnittet egress omfatte mange elementer til (også kombineres med disjunktion):
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. Forskellige politikker kombineres også med logisk ELLER
Men når de kombineres, er der en begrænsning, som : Kubernetes kan kun kombinere politikker med forskellige policyTypes (Ingress eller Egress). Politikker, der definerer ingress (eller egress), vil overskrive hinanden.
Forbindelse mellem navnerum
Som standard er informationsudveksling mellem navnerum tilladt. Dette kan ændres med en restriktiv politik, som begrænser udgående og/eller indgående trafik i et navnerum (se "Cleansing rule" ovenfor).
Ved at blokere adgangen til et navnerum (se "Cleansing rule" ovenfor) kan du lave undtagelser i den restriktive politik ved at tillade forbindelser fra et bestemt navnerum ved hjælp af 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 
Som et resultat vil alle pod’ene i navnerummet default få adgang til pod’ene postgres i navnerummet database. Men hvad nu, hvis du vil åbne adgangen til postgres kun specifikke pod’ere i navnerummet default?
Filtrering efter navnerum og pod’ere
Kubernetes version 1.11 og højere tillader kombination af operatorer namespaceSelector og podSelector ved hjælp af logisk OG. Det ser således ud:
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 
Hvorfor tolkes dette som OG i stedet for det sædvanlige ELLER?
Bemærk venligst, at podSelector starter ikke med et bindestreg. I YAML betyder det, at podSelector og det, der står før det namespaceSelector tilhører det samme listeelement. Derfor kombineres de med logisk OG.
Tilføjelse af et bindestreg foran podSelector vil føre til oprettelsen af et nyt listeelement, der kombineres med det forrige namespaceSelector ved hjælp af en logisk ELLER.
For at vælge pods med et bestemt label i alle navnerum, indtast et tomt 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 
Flere labels kombineres med OG
Firewall-regler med flere objekter (hosts, netværk, grupper) kombineres ved hjælp af logisk ELLER. Den følgende regel gælder, hvis kildepakken matcher Host_1 . Host_2:
| Kilde | Destination | Tjeneste | Handling |
| ----------------------------------------|
| Host_1 | Subnet_A | HTTPS | Tillad |
| Host_2 | | | |
| ----------------------------------------| Omvendt i Kubernetes kombineres forskellige labels med podSelector eller namespaceSelector logisk OG. For eksempel vil den følgende regel vælge pods med begge labels, role=db Og version=v2:
podSelector:
matchLabels:
role: db
version: v2Den samme logik gælder for alle typer operatører: målpolitikkere, pod-selektorer og navnerums-selektorer.
Subnet og IP-adresser (IPBlocks)
For at segmentere netværket bruger firewalls VLAN, IP-adresser og subnets.
I Kubernetes tildeles IP-adresser automatisk til pods og kan ofte ændre sig, så labels bruges til at vælge pods og navnerum i netværkspolitikker.
Subnets (ipBlocks) bruges til at håndtere indgående (ingress) eller udgående (egress) eksterne (North-South) forbindelser. For eksempel åbner denne politik for alle pods i navnerummet default adgang til Googles DNS-tjeneste:
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 
En tom pod-selektor i dette eksempel betyder "vælg alle pods i navnerummet".
Denne politik åbner kun adgang til 8.8.8.8; adgang til enhver anden IP er forbudt. Dermed har du i praksis blokeret adgangen til Kubernetes interne DNS-tjeneste. Hvis du alligevel vil åbne det, skal du angive det eksplicit.
Normalt ipBlocks og podSelectors er gensidigt udelukkende, da interne IP-adresser for pods ikke bruges i ipBlocks. Ved at angive interne pod IP-adresser, vil du faktisk tillade forbindelser til/fra pod’ere med disse adresser. I praksis vil du ikke vide, hvilken IP-adresse du skal bruge, derfor skal de ikke anvendes til at vælge pod’ere.
Som et modbevis inkluderer følgende politik alle IP’er og tillader derfor adgang til alle andre pod’ere:
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 
Adgang kan kun åbnes til eksterne IP’er, mens interne IP-adresser fra pod’erne udelukkes. For eksempel, hvis din pod’s subnet er 10.16.0.0/14:
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 
Porter og protokoller
Normalt lytter pod’ere på én port. Det betyder, at man simpelthen kan undlade at angive portnumre i politikkerne og lade alt være som standard. Dog anbefales det, at politikkerne gøres så begrænsende som muligt, så i nogle tilfælde kan det være nødvendigt at angive porte:
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 
Bemærk, at selektor ports anvendes på alle elementer i blokken til eller fra, hvori den er indeholdt. For at angive forskellige porte for forskellige sætbredder, del ingress eller egress op i flere underafsnit med til eller fra og angiv de nødvendige porte for hver:
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 
Standard portdrift:
- Hvis du helt udelader portdefinitioner (
ports), betyder det alle protokoller og alle porte; - Hvis du udelader protokoldefinitionen (
protocol), betyder det TCP; - Hvis du udelader portdefinitionen (
port), betyder det alle porte.
Bedste praksis: stol ikke på standardværdier, angiv det, du har brug for, eksplicit.
Bemærk, at du skal bruge pod's porte i stedet for tjenester (læs mere om dette i næste afsnit).
Er politikkerne defineret for pod's eller tjenester?
Normalt kommunikerer pod's i Kubernetes med hinanden via en service — en virtuel belastningsfordeler, der omdirigerer trafik til de pod's, der implementerer servicen. Man kunne tro, at netværkspolitikker kontrollerer adgangen til tjenester, men det er ikke tilfældet. Netværkspolitikker i Kubernetes arbejder med pod's porte og ikke tjenester.
For eksempel, hvis en service lytter på port 80, men videresender trafik til port 8080 på sine pod's, skal den netværkspolitik angive præcist 8080.
En sådan mekanisme anses for suboptimal: ved ændringer af den interne struktur af servicen (hvis portene bliver lyttet på af pod's) skal netværkspolitikkerne opdateres.
En ny arkitektonisk tilgang ved brug af Service Mesh (for eksempel se om Istio nedenfor — bem. overs.) løser dette problem.
Skal både Ingress og Egress angives?
Det korte svar er ja, for at pod A kan kommunikere med pod B, skal det tillades at oprette en udgående forbindelse (for dette skal der konfigureres en egress-politik), og pod B skal kunne modtage en indgående forbindelse (for dette kræves en ingress-politik).
Men i praksis kan man stole på standardpolitikken, som tillader forbindelser i en eller begge retninger.
Hvis en pod-kilde bliver valgt af en eller flere egress-politikker, vil de begrænsninger, der pålægges den, blive bestemt af deres disjunktion. I dette tilfælde vil det være nødvendigt at tillade forbindelse til pod-modtageren. Hvis pod'en ikke er valgt af nogen politik, er dens udgående (egress) trafik tilladt som standard.
På samme måde vil skæbnen for pod-modtageren, valgt af en eller flere ingress-politikker, blive bestemt af deres disjunktion. I dette tilfælde skal det tillades, at den kan modtage trafik fra pod-kilden. Hvis en pod ikke er valgt af nogen politik, er al indgående (ingress) trafik for den tilladt som standard.
Se punktet 'Stateful eller Stateless' nedenfor.
Logs
Netværkspolitikker i Kubernetes har ikke mulighed for at registrere trafik. Det gør det svært at afgøre, om politikken fungerer korrekt og komplicerer analysen inden for sikkerhed.
Kontrol over trafikken til eksterne tjenester
Kubernetes-netværkspolitikker tillader ikke at angive et fuldt domænenavn (DNS) i egress-sektionerne. Denne situation skaber betydelige udfordringer ved forsøg på at begrænse trafik til eksterne adresser, der ikke har en fast IP-adresse (såsom aws.com).
Politik kontrol
Firewalls vil advare dig eller endda nægte at acceptere en fejlagtig politik. Kubernetes udfører også en vis validering. Når du angiver netværkspolitikken via kubectl, kan Kubernetes erklære, at den er ugyldig og nægte at acceptere den. I andre tilfælde vil Kubernetes acceptere politikken og supplere den med manglende detaljer. Disse kan ses med følgende kommando:
kubernetes get networkpolicy -o yamlVær opmærksom på, at Kubernetes' valideringssystem ikke er ufejlbarligt og kan overse nogle typer fejl.
Udførelse
Kubernetes implementerer ikke netværkspolitikker selv, men fungerer blot som en API-gateway, der pålægger kontrollen til et underliggende system kaldet Container Networking Interface (CNI). At angive politikker i et Kubernetes-kluster uden at tildele den relevante CNI svarer til at oprette politikker på en firewall-administrationsserver uden at installere dem i firewalls. Du skal selv sikre, at der er en passende CNI tilgængelig, eller i tilfælde af Kubernetes-platforme i skyen (se listen over udbydere — red.), aktivere netværkspolitikker, der vil etablere CNI for dig.
Bemærk, at Kubernetes ikke vil advare dig, hvis du angiver en netværkspolitik uden den relevante CNI.
Stateful eller Stateless?
Alle Kubernetes CNI'er, jeg har stiftet bekendtskab med, er stateful (for eksempel bruger Calico Linux conntrack). Dette gør det muligt for en pod at modtage svar på en TCP-forbindelse, den har initieret, uden at skulle etablere den igen. Jeg kender dog ikke til nogen Kubernetes-standard, der garanterer statefulness.
Avanceret sikkerhedspolitikstyring
Her er nogle måder at øge effektiviteten af sikkerhedspolitikudførelse i Kubernetes:
- Arkitekturmønsteret Service Mesh bruger sidecar-containere til at levere detaljeret telemetri og trafikstyring på serviceniveau. Et eksempel kunne være .
- Nogle af CNI-leverandørerne har forbedret deres værktøjer, så de går udover netværkspolitikkerne i Kubernetes.
- giver gennemsigtighed og automatisering af netværkspolitikkerne i Kubernetes.
Tufin Orca-pakken administrerer netværkspolitikkerne i Kubernetes (og fungerer som kilde til de ovenfor nævnte skærmbilleder).
Yderligere oplysninger
- ;
- ;
- ;
- .
Konklusion
Netværkspolitikkerne i Kubernetes tilbyder et godt sæt værktøjer til segmentering af klynger, men de er ikke intuitive og har mange nuancer. Jeg mener, at på grund af denne kompleksitet indeholder mange eksisterende klynger fejl. Mulige løsninger på dette problem er automatisering af politikdefinitioner eller brug af andre segmenteringsværktøjer.
Jeg håber, at denne guide vil hjælpe med at klarlægge nogle spørgsmål og løse de problemer, du måtte støde på.
P.S. fra oversætteren
Læs også på vores blog:
- «Tilbage til mikrotjenester sammen med Istio»: , , ;
- «Illustreret guide til netværksopbygning i Kubernetes»: , ;
- «»;
- «»;
- «».
Kilde: habr.com
