Kubernetes networking
Kubernetes Services
In Kubernetes worden Services gebruikt om een stabiele netwerkinterface te bieden voor toegang tot één of meerdere pods, zelfs als de onderliggende pods dynamisch worden gepusht of geüpdatet. Een Service abstracteert de netwerkcommunicatie naar de pods en zorgt ervoor dat het verkeer betrouwbaar naar de juiste container wordt gestuurd, ongeacht welke pods draaien of waar ze zich bevinden in de cluster. Er zijn verschillende typen services in Kubernetesm, afhankelijk van de netwerkbehoeften: ClusterIP, NodePort en LoadBalancer.
ClusterIP
ClusterIP is de standaard service type in Kubernetes. Het zorgt ervoor dat de service alleen binnen de cluster toegankelijk is via een virtueel IP-adres, wat betekent dat het verkeer binnen de cluster wordt gerouteerd.
Kenmerken:
- Intern bereik: De service is alleen beschikbaar binnen het Kubernetes-cluster.
- Geen externe toegang: Je kunt de service alleen bereiken vanaf andere pods binnen dezelfde cluster. Dit betekent dat je geen externe toegang hebt tot de service via internet of via het lokale netwerk.
- Standaard type: Als je geen type opgeeft, wordt een service standaard als ClusterIP aangemaakt.
Wanneer gebruik je het?
- Interne communicatie: Wanneer je wilt dat de pods alleen binnen de cluster met elkaar communiceren, bijvoorbeeld voor microservices die elkaar aanroepen.
- Backend-diensten: Bijvoorbeeld voor een database of cachingservice die alleen door andere applicaties in de cluster moet worden benaderd.
Voorbeeld van een ClusterIP-service:
apiVersion: v1
kind: Service
metadata:
name: my-clusterip-service
spec:
selector:
app: my-app
ports:
- protocol: TCP
port: 80
targetPort: 8080
type: ClusterIP # Dit is de standaard en kan weggelaten worden
In dit voorbeeld heeft de service het ClusterIP type, wat betekent dat het alleen binnen de cluster beschikbaar is op poort 80 en het verkeer wordt doorgestuurd naar poorten 8080 van de geselecteerde pods.
NodePort
NodePort maakt de service beschikbaar buiten het Kubernetes-cluster door een statische poort op elke node in de cluster te openen. Het verkeer naar de opgegeven poort op de node wordt doorverwezen naar de service binnen de cluster.
Kenmerken:
- Externe toegang: De service is beschikbaar via een poort op elke node van de cluster, wat betekent dat je de service kunt benaderen via
<NodeIP>:<NodePort>. - Handmatig toegewezen poort: Kubernetes wijst automatisch een poort toe in het bereik 30000-32767, tenzij je een specifieke poort instelt.
- Externe toegang zonder LoadBalancer: Dit kan nuttig zijn voor simpele scenario’s waar je de service beschikbaar wilt maken op externe netwerken, maar zonder een load balancer in te schakelen.
Wanneer gebruik je het?
- Externe toegang tot applicaties: Wanneer je een applicatie beschikbaar wilt stellen via een specifieke poort op je Kubernetes-nodes. Dit is vaak geschikt voor development, testomgevingen of eenvoudige scenario’s.
- Statische poorttoegang: Je hebt een specifieke poort nodig op de nodes die altijd beschikbaar is, bijvoorbeeld voor een webserver.
Voorbeeld van een NodePort-service:
apiVersion: v1
kind: Service
metadata:
name: my-nodeport-service
spec:
selector:
app: my-app
ports:
- protocol: TCP
port: 80
targetPort: 8080
nodePort: 30007 # Handmatig toegewezen poort
type: NodePort
In dit voorbeeld is de service van het type NodePort en wordt de poort 30007 geopend op elke node in de cluster, die het verkeer doorverwijst naar de applicatie op poort 8080 binnen de pods.
LoadBalancer
Het LoadBalancer type maakt gebruik van externe load balancing, meestal via een cloudprovider zoals AWS, GCP of Azure. Het creëert automatisch een externe load balancer die toegang biedt tot de service via een extern IP-adres.
Kenmerken:
- Externe toegang met load balancing: Een load balancer wordt automatisch geconfigureerd en biedt een vast extern IP-adres voor toegang tot de service.
- Cloud-integratie: Dit type service is meestal geïntegreerd met de cloudprovider. Kubernetes zorgt voor de provisioning van de load balancer.
- Verkeersverdeling: De load balancer verdeelt automatisch het verkeer over de beschikbare pods die achter de service draaien.
Wanneer gebruik je het?
- Productieomgevingen: Dit is ideaal voor scenario’s waar je een betrouwbare, schaalbare toegang wilt tot je applicaties in de cloud.
- High Availability: Als je applicaties met hoge beschikbaarheid wilt draaien, omdat de load balancer automatisch het verkeer over meerdere pods kan verdelen en redundantie biedt.
Voorbeeld van een LoadBalancer-service:
apiVersion: v1
kind: Service
metadata:
name: my-loadbalancer-service
spec:
selector:
app: my-app
ports:
- protocol: TCP
port: 80
targetPort: 8080
type: LoadBalancer
In dit voorbeeld heeft de service het LoadBalancer type, en Kubernetes (in combinatie met de cloudprovider) zal automatisch een externe load balancer en een extern IP-adres toewijzen voor de toegang tot deze service.
Vergelijking van de Service Types
| Kenmerk | ClusterIP | NodePort | LoadBalancer |
|---|---|---|---|
| Toegankelijkheid | Alleen binnen de cluster | Van buiten de cluster via een node | Van buiten de cluster via een extern IP |
| Externe toegang | Nee | Ja, via <NodeIP>:<NodePort> | Ja, via extern IP (load balancer) |
| Gebruik | Interne communicatie tussen pods | Toegang voor eenvoudige externe toegang | Hoge beschikbaarheid, productieomgevingen |
| Cloud Integratie | Geen | Geen | Ja, werkt vaak met cloudproviders (AWS, GCP, etc.) |
| Load Balancing | Nee | Nee | Ja, automatische load balancing |
| Poort | Dynamisch binnen de cluster | Statische poort per node | Dynamisch toegewezen door cloudprovider |
Netwerken tussen containers
In een Kubernetes-cluster worden containers die binnen pods draaien met elkaar verbonden via een netwerk dat deel uitmaakt van de Kubernetes-netwerkarchitectuur. Het netwerk is cruciaal om de communicatie tussen containers, pods en zelfs tussen clusters mogelijk te maken.
Kubernetes Netwerkmodel
Kubernetes heeft een aantal fundamentele netwerkvereisten die het netwerkmodel bepalen:
-
Elke Pod krijgt een eigen IP-adres: Binnen een Kubernetes-cluster krijgt elke pod zijn eigen IP-adres, wat betekent dat containers binnen een pod met elkaar kunnen communiceren via localhost (127.0.0.1) en containers in verschillende pods kunnen met elkaar communiceren via hun pod-IP-adressen. Dit maakt een schaalbare en flexibele netwerkarchitectuur mogelijk.
-
Pod-to-Pod communicatie: Pods kunnen communiceren met andere pods, zelfs als ze zich op verschillende nodes bevinden. Dit wordt mogelijk gemaakt door een flat network waarin alle pods in de cluster rechtstreeks via hun IP-adressen kunnen communiceren.
-
Geen Network Address Translation (NAT): Kubernetes netwerken gebruiken geen NAT tussen pods. Dit betekent dat elk pod-IP uniek en routable is binnen de cluster, wat de complexiteit van netwerkcommunicatie vereenvoudigt.
Kubernetes Netwerkarchitectuur
Het netwerk in Kubernetes is opgebouwd uit verschillende lagen en componenten. Hier zijn de belangrijkste onderdelen:
-
Pods: Zoals hierboven aangegeven, heeft elke pod een uniek IP-adres, zodat containers binnen een pod via localhost kunnen communiceren en containers in verschillende pods via de pod-IP's kunnen communiceren.
-
Services: Een Kubernetes Service is een abstractie die een toegangspunt biedt voor pods en wordt gebruikt om verkeer naar een set van pods te routeren, zelfs als de pods in de loop van de tijd dynamisch veranderen. Services bieden load balancing, DNS-resolutie en andere functies.
-
Kubernetes CNI (Container Network Interface): Kubernetes maakt gebruik van de CNI-standaard om netwerkplugins te integreren. Deze plugins bieden verschillende netwerkconfiguraties zoals overlay-netwerken, bridged-netwerken of netwerkvirtualisatie. Voorbeelden van CNI-plugins zijn Calico, Weave, Flannel, en Cilium.
Netwerkcommunicatie tussen Containers
In Kubernetes kunnen containers binnen een pod en tussen verschillende pods met elkaar communiceren via hun IP-adressen. Dit kan op verschillende manieren worden ingericht:
Communicatie Binnen een Pod
Containers die binnen dezelfde pod draaien, kunnen communiceren via localhost (127.0.0.1), omdat ze hetzelfde netwerk en dezelfde namespace delen. Containers kunnen bijvoorbeeld een webserver en een databasecontainer hebben, en ze kunnen via localhost met elkaar communiceren.
Communicatie Tussen Pods
Pod-to-Pod communicatie vindt plaats via het pod IP-adres, wat betekent dat als je een pod aanmaakt, Kubernetes deze automatisch een uniek IP-adres toekent binnen de cluster. Hierdoor kunnen pods met elkaar communiceren zonder NAT, zelfs als ze op verschillende nodes draaien.
Een voorbeeld:
- Pod A heeft IP 10.0.0.1
- Pod B heeft IP 10.0.0.2
Pod A kan verbinding maken met Pod B door simpelweg de IP van Pod B te gebruiken: curl http://10.0.0.2.
Kubernetes Services voor Netwerkverkeer
Een Service in Kubernetes biedt een consistente toegangspunt voor communicatie met een set van pods, wat het schaalbaar en robuust maakt. Services kunnen op verschillende manieren worden geconfigureerd, afhankelijk van hoe de communicatie moet plaatsvinden:
-
ClusterIP: Dit is de standaard service type die alleen toegankelijk is binnen de cluster. Kubernetes wijst een intern IP-adres toe aan de service, en via dat IP kunnen andere pods in de cluster met de service communiceren.
-
NodePort: Dit maakt de service toegankelijk via een poort op elke node in de cluster. Dit type service kan verkeer van buiten de cluster doorsturen naar de juiste pod binnen de cluster via het opgegeven poortnummer.
-
LoadBalancer: Dit type service biedt toegang via een externe load balancer (meestal in een cloudomgeving). Het is geschikt voor het exposeren van je applicaties aan het internet.
Een service fungeert als een abstractie die verkeer naar de juiste pod(s) kan routeren, zelfs als de pods dynamisch worden gecreëerd of verwijderd. Dit zorgt ervoor dat de communicatie met de pods consistent blijft, zelfs wanneer ze veranderen.
Kubernetes Networking Policies
Kubernetes biedt Network Policies die je kunt gebruiken om de communicatie tussen pods te controleren. Met netwerkbeleid kun je bepalen welke pods met elkaar kunnen communiceren, op basis van labels, IP-adressen en poorten.
Een voorbeeld van een eenvoudige NetworkPolicy om het verkeer van een specifieke pod te beperken:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-pod-communication
spec:
podSelector:
matchLabels:
app: my-app
ingress:
- from:
- podSelector:
matchLabels:
app: my-other-app
Dit netwerkbeleid zou alleen verkeer toestaan van pods met de label app: my-other-app naar pods met de label app: my-app.
Netwerk Plugins (CNI)
Kubernetes maakt gebruik van de Container Network Interface (CNI) voor het beheren van netwerken in containers. Dit stelt Kubernetes in staat om verschillende netwerkprotocollen en plugins te gebruiken om pods met elkaar te verbinden.
Enkele populaire CNI-plugins zijn:
- Calico: Een veelgebruikte CNI-plugin die zowel netwerkfunctionaliteit als netwerkbeveiliging biedt.
- Flannel: Een eenvoudige CNI-plugin die een overlay-netwerk maakt voor Kubernetes-clusters.
- Weave: Een ander overlay-netwerk voor Kubernetes dat ook netwerksplitsing en netwerksegmentatie ondersteunt.
- Cilium: Een CNI-plugin gebaseerd op eBPF (extended Berkeley Packet Filter), waarmee geavanceerde netwerkbeveiliging en observatie mogelijk is.
De keuze van een CNI-plugin heeft invloed op de prestaties, netwerkbeveiliging en complexiteit van je Kubernetes-cluster.
DNS en Service Discovery
Kubernetes biedt ingebouwde DNS-service discovery, waardoor het mogelijk is om met services te communiceren via DNS-namen in plaats van IP-adressen. Wanneer een service wordt gemaakt, wordt automatisch een DNS-naam toegewezen, bijvoorbeeld: <service-name>.<namespace>.svc.cluster.local. Pods binnen de cluster kunnen via deze naam communiceren met de service.
Bijvoorbeeld, een pod die verbinding wil maken met een service my-service in de namespace default, zou het volgende kunnen gebruiken:
http://my-service.default.svc.cluster.local
Dit maakt het makkelijker om applicaties te koppelen zonder direct afhankelijk te zijn van IP-adressen, die kunnen veranderen.
Introductie tot Ingress voor HTTP/S-routing
In Kubernetes wordt Ingress gebruikt om externe HTTP- en HTTPS-verkeer naar je services binnen de cluster te routeren. Het is een krachtige manier om toegang te krijgen tot applicaties die draaien in een Kubernetes-cluster, zonder dat je een LoadBalancer of NodePort hoeft in te schakelen voor elke service. Ingress biedt geavanceerde routingmogelijkheden, zoals het afhandelen van meerdere domeinen, paden en SSL-terminatie, waardoor het ideaal is voor het beheren van webverkeer naar verschillende applicaties.
Belangrijkste Kenmerken van Ingress:
- HTTP(S)-Routing: Ingress maakt het mogelijk om HTTP(S)-verkeer naar specifieke services binnen je cluster te routeren op basis van domeinnamen (host) en URL-paden.
- SSL/TLS-Termination: Ingress ondersteunt SSL/TLS-terminatie, wat betekent dat je HTTPS-verkeer kunt versleutelen, zodat het verkeer van de buitenwereld naar de cluster beveiligd is.
- Centralisatie van Toegang: Ingress biedt een gecentraliseerde manier om toegang te regelen voor meerdere applicaties binnen een cluster via één ingangspunt.
- Load Balancing: Ingress kan verkeer distribueren over meerdere pods en services, waardoor je een load balancer krijgt zonder dat je extra infrastructuur hoeft in te zetten.
- Aangepaste Routing: Het kan gedetailleerde regels bevatten voor het routeren van verkeer, zoals het routeren van verkeer naar verschillende services op basis van de hostnaam of URL-pad.
Hoe werkt Ingress?
Ingress werkt door het toevoegen van een Ingress Resource die specifieke regels en routes bevat om HTTP(S)-verkeer naar de juiste services in je Kubernetes-cluster te sturen. Om Ingress in Kubernetes te gebruiken, moet je een Ingress Controller implementeren die de inkomende HTTP(S)-verzoeken afhandelt en doorstuurt naar de juiste services.
De Ingress-controller is een kubernetes component die ervoor zorgt dat de Ingress-regels daadwerkelijk worden toegepast en het verkeer van buiten de cluster naar de juiste service binnen de cluster kan worden geleid.
Stappen om Ingress te Gebruiken:
-
Installeren van een Ingress Controller
- Ingress zelf is slechts een set van regels en configuraties. Om het verkeer daadwerkelijk te routeren, moet een Ingress Controller in je cluster worden geïnstalleerd. Er zijn verschillende opties voor Ingress Controllers, zoals:
- NGINX Ingress Controller (meest populaire keuze)
- Traefik
- HAProxy Ingress
- Envoy
De NGINX Ingress Controller kan bijvoorbeeld eenvoudig worden geïnstalleerd via een Helm chart:
helm install my-ingress nginx-ingress/nginx-ingress - Ingress zelf is slechts een set van regels en configuraties. Om het verkeer daadwerkelijk te routeren, moet een Ingress Controller in je cluster worden geïnstalleerd. Er zijn verschillende opties voor Ingress Controllers, zoals:
-
Definiëren van een Ingress Resource Zodra de Ingress Controller is geïnstalleerd, kun je een Ingress Resource aanmaken die bepaalt hoe het verkeer wordt gerouteerd naar je services. Een Ingress Resource kan regels bevatten voor meerdere domeinen en paden, evenals SSL-certificaten voor versleuteling.
Voorbeeld van een Ingress Resource: Dit voorbeeld laat zien hoe je HTTP-verkeer voor verschillende domeinen en paden naar verschillende services binnen je cluster kunt routeren.
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: my-ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
rules:
- host: myapp.example.com
http:
paths:
- path: /api
pathType: Prefix
backend:
service:
name: api-service
port:
number: 80
- path: /web
pathType: Prefix
backend:
service:
name: web-service
port:
number: 80
- host: anotherapp.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: another-service
port:
number: 80Uitleg:
- Host: De hostnaam (domeinnaam) die de inkomende HTTP(S)-verzoeken zal gebruiken.
- Paths: Het pad (bijv.
/apiof/web) waarmee je verkeer naar specifieke services binnen je cluster kunt sturen. - Backend: De service waar het verkeer naartoe wordt gestuurd en de poort van die service.
- Annotations: In dit voorbeeld gebruiken we een annotatie om de rewrite-target in te stellen, wat inhoudt dat de inkomende URL-voorvoegsels worden herschreven wanneer ze naar de service worden doorgestuurd.
-
SSL/TLS Configuratie: Voor HTTPS-verkeer moet je een SSL-certificaat configureren. Kubernetes ondersteunt TLS-terminatie in de Ingress-regels, zodat je HTTPS-verkeer kunt ontvangen en naar de juiste service kunt sturen.
Voorbeeld van Ingress met TLS:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: my-secure-ingress
spec:
tls:
- hosts:
- myapp.example.com
secretName: myapp-tls-secret # Het secret bevat je TLS-certificaten
rules:
- host: myapp.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: myapp-service
port:
number: 80In dit voorbeeld wordt verkeer naar
myapp.example.comversleuteld met TLS (HTTPS), en de TLS-certificaten worden opgehaald uit een Kubernetes secret (myapp-tls-secret). -
Externe Toegang Tot de Ingress Controller: Nadat je Ingress hebt ingesteld, kun je de toegang naar de Ingress Controller extern maken. Meestal wordt dit gedaan via een LoadBalancer-service of een NodePort-service. Dit zorgt ervoor dat inkomend verkeer vanaf het internet via de Ingress Controller naar je services in de cluster kan worden geleid.
Als je bijvoorbeeld de NGINX Ingress Controller met een LoadBalancer hebt geïnstalleerd, wordt automatisch een extern IP toegewezen voor de toegang. Dit IP kun je gebruiken om toegang te krijgen tot de applicatie via het ingestelde domein.