Kubernetes: networking


calendar icon

31 mei 2023

|
calendar icon 8 minuten

In een Kubernetes-cluster is het netwerk een essentieel onderdeel voor het verbinden van pods, services en externe gebruikers. Netwerkconfiguraties en concepten in Kubernetes(K8s) zijn cruciaal voor het bouwen van schaalbare en betrouwbare applicaties. In deze blog zullen we een overzicht geven van de belangrijkste netwerkconcepten en configuraties in Kubernetes.

Pods en IP-adressen

In K8s is een pod de kleinste instantie die bestaat uit één of meerdere containers die samen draaien op dezelfde host. Elke pod heeft een uniek IP-adres binnen het cluster. Het IP-adres wordt toegewezen aan de pod wanneer deze wordt gemaakt en blijft behouden zolang de pod actief is. Zonder een extra configuratie kunnen Pods binnen hetzelfde cluster rechtstreeks met elkaar communiceren via hun IP-adressen.

Een van de voordelen van K8s is de flexibiliteit op het gebied van schalen en recoverabillity. Als een pod niet meer reageert, zal de pod gedelete worden en zal K8s een nieuwe starten. Het gevolg van deze setup is dat IP-adressen van pods continue veranderen. Als de communicatie van je pods afhankelijk is van IP-adressen kan dit uitdagingen op het gebied van schaalbaarheid met zich meebgrengen. Gelukkig kan je met Kubernetes gebruik maken services om dit probleem op te lossen.

Services

Services in K8s bieden een abstractie voor het verbinden van pods en het bieden van een stabiel endpoint voor communicatie. Een service kan worden beschouwd als een vast IP-adres en poortnummer waarmee externe gebruikers of andere pods kunnen communiceren. Er zijn verschillende soorten services, zoals: ClusterIP, NodePort en LoadBalancer, die verschillende netwerkpatronen ondersteunen.

apiVersion: v1
kind: Service
metadata:
  name: mijn-service
spec:
  selector:
    app: mijn-app
  ports:
    - protocol: TCP
      port: 80
      targetPort: 8080
  type: ClusterIP

In het voorbeeld hierboven wordt een service met de naam "mijn-service" gemaakt. De service is gekoppeld aan pods met het label "app: mijn-app" via de selector. De service luistert op poort 80 en stuurt het verkeer door naar poort 8080 op de geselecteerde pods. Het protocol is ingesteld op TCP. De service wordt ingesteld als een ClusterIP-type. Dit betekent dat het alleen intern toegankelijk is binnen het K8s-cluster.

Let op: dit is een voorbeeld van een service met type ClusterIP. Afhankelijk van je vereisten, kun je ook NodePort of LoadBalancer-types gebruiken. Bij een NodePort-service zou je het type veld wijzigen naar NodePort. Voor een LoadBalancer-service zou je het type veld wijzigen naar LoadBalancer en mogelijk extra configuratie toevoegen. Dit is afhankelijk van je specifieke-/ cloudprovider.

ClusterIP

In het bovenstaande voorbeeld geven we een voorbeeld van een ClusterIP-service. Een ClusterIP-service biedt een stabiel IP-adres en poortnummer waarmee pods binnen het cluster kunnen communiceren. De service wordt intern toegankelijk gemaakt door een virtuele IP(VIP) te koppelen aan een set van pods met behulp van labels en selectors. Externe toegang tot een ClusterIP-service is niet mogelijk zonder aanvullende configuraties.

NodePort

Een NodePort-service maakt een poort beschikbaar op elke node in het cluster. Zo kun je extern verkeer doorsturen naar de service. Het maakt gebruik van een combinatie van een cluster-IP en een NodePort om de service toegankelijk te maken. Extern verkeer wordt doorgestuurd naar een willekeurige node in het cluster en van daaruit naar de service.

apiVersion: v1
kind: Service
metadata:
  name: mijn-service
spec:
  selector:
    app: mijn-app
  ports:
    - protocol: TCP
      port: 80
      targetPort: 8080
      nodePort: 30000
  type: NodePort

In dit voorbeeld wordt een service genaamd "mijn-service" gemaakt als een NodePort-type. De service is gekoppeld aan pods met het label "app: mijn-app" via de selector. De service luistert op poort 80 en stuurt het verkeer door naar poort 8080 op de geselecteerde pods. Het protocol is ingesteld op TCP. Het NodePort veld is ingesteld op 30000, maar je kunt een beschikbare poort kiezen binnen het bereik van 30000-32767.

De NodePort-service "mijn-service" in je K8s-cluster zal het verkeer naar de bijbehorende pods op de juiste poort doorsturen. De service zal ook toegankelijk zijn via het IP-adres van de nodes in je cluster, op de opgegeven NodePort (bijvoorbeeld http://:30000).

Zorg ervoor dat je het juiste poortbereik gebruikt. Houdt ook rekening met eventuele netwerkbeperkingen of firewallinstellingen in je omgeving.

Het gebruik van NodePort-services in K8s biedt zeker een aantal voordelen, maar het heeft ook beperkingen waarmee je rekening moet houden. Hier zijn enkele beperkingen van NodePort-services:

  • Poortbereik: Het poortbereik voor NodePort-services is beperkt tot een specifiek bereik in K8s. Meestal ligt dit tussen 30000 en 32767. Dit betekent dat je alleen NodePort-services kunt maken met poortnummers binnen dit bereik. Als je een specifieke poort wilt gebruiken die buiten dit bereik valt, moet je een LoadBalancer-service overwegen of een externe load balancer configureren.
  • Externe toegang: Met NodePort-services kun je externe toegang krijgen tot je services via het IP-adres van de nodes in je cluster, gevolgd door de opgegeven nodePort-poort. Dit betekent dat je het IP-adres van de nodes moet kennen om toegang te krijgen tot de services. Als de nodes in je cluster regelmatig veranderen of als je een grootschalig cluster hebt, kan het beheren van externe toegang en het bijhouden van de IP-adressen van de nodes een uitdaging zijn.
  • Beveiliging: NodePort-services maken services beschikbaar op alle nodes in je cluster via het opgegeven poortbereik. Dit kan de beveiliging beïnvloeden, omdat de services rechtstreeks toegankelijk zijn via de nodes. Zonder additionele beveiliging. Om ervoor te zorgen dat alleen de gewenste verkeerstypen en bronnen toegang hebben tot de services, moet je extra maatregelen nemen. Denk hierbij aan het configureren van Network Policies of een externe firewall.

Dit zijn belangrijke zaken om in overweging te nemen bij het kiezen van de juiste servicetype. Als je meer flexibiliteit, schaalbaarheid en mogelijkheden voor load balancing nodig hebt, kun je overwegen om een LoadBalancer-service of een Ingress-controller te gebruiken in plaats van NodePort-services.

LoadBalancer

Een LoadBalancer-service maakt gebruik van een externe load balancer om verkeer naar de service te routen. Dit type service is met name handig in cloudomgevingen waar een externe load balancer beschikbaar is. De externe load balancer wijst verkeer toe aan de nodes in het cluster waarop de service draait.

apiVersion: v1
kind: Service
metadata:
  name: mijn-service
spec:
  selector:
    app: mijn-app
  ports:
    - protocol: TCP
      port: 80
      targetPort: 8080
  type: LoadBalancer

In dit voorbeeld wordt een service genaamd "mijn-service" gemaakt als een LoadBalancer-type. De service is gekoppeld aan pods met het label "app: mijn-app" via de selector. De service luistert op poort 80 en stuurt het verkeer door naar poort 8080 op de geselecteerde pods. Het protocol is ingesteld op TCP. Exacte configuratie en mogelijkheden van de LoadBalancer-service kunnen variëren, afhankelijk van je K8s-implementatie en cloudprovider.

Ingress

Ingress is een K8s-resource die de toegang tot services van buiten het cluster mogelijk maakt. Het fungeert als een toegangspunt voor HTTP- en HTTPS-verkeer. En kan het verkeer routeren naar verschillende services op basis van domeinnamen en paden. Een Ingress-controller, zoals Ingress-nginx of Traefik, wordt gebruikt om het verkeer te routeren naar de juiste services.

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: mijn-ingress
  annotations:
    kubernetes.io/ingress.class: nginx
spec:
  rules:
    - host: mijn-domein.com
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: mijn-service
                port:
                  number: 80

In dit voorbeeld wordt een Ingress-resource genaamd "mijn-ingress" gemaakt. De Ingress maakt gebruik van de Ingress-nginx-controller, aangegeven met de kubernetes.io/ingress.class: nginx annotatie.

De Ingress heeft één regel (rule) gedefinieerd voor het hostdomein "mijn-domein.com". Het verkeer dat via dit domein wordt ontvangen, wordt doorgestuurd naar de backend-service "mijn-service" op poort 80. De Ingress-nginx-controller zal de Ingress-resource detecteren en configureren om zo het verkeer naar de juiste service door te sturen op basis van de regels die zijn gedefinieerd.

Om gebruik te maken van de Ingress-nginx-controller zal je de controller moeten implementeren in je K8s-cluster.

Network Policies

Network Policies stellen gebruikers in staat om verkeersregels te definiëren voor het beheer van inkomend en uitgaand verkeer binnen een K8s-cluster. Met Network Policies kunnen specifieke pods of podgroepen worden geïsoleerd of beveiligd. Je kunt dit doen door het verkeer te filteren op basis van bron- en doelpodlabels, poorten en protocollen.

Een Network Policy is een K8s-resource die wordt gedefinieerd met behulp van YAML. Hieronder vind je een voorbeeld van een network policy die het verkeer naar een specifieke pod beperkt:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: restrict-traffic-policy
spec:
  podSelector:
    matchLabels:
      app: mijn-app
  policyTypes:
    - Ingress
  ingress:
    - from:
        - podSelector:
            matchLabels:
              app: toegestane-app
      ports:
        - protocol: TCP
          port: 8080

In dit voorbeeld wordt de Network Policy "restrict-traffic-policy" toegepast op pods met het label "app: mijn-app". De policy staat alleen inkomend verkeer toe van pods met het label "app: toegestane-app" op poort 8080 en het TCP-protocol.

Door Network Policies te gebruiken, kunnen ontwikkelaars de communicatie tussen pods binnen het cluster beperken. Hier verbeter je de beveiliging en verklein je het risico op ongeautoriseerd verkeer. Het is belangrijk om netwerkbeleid zorgvuldig te plannen en te testen, zodat je ervoor kunt zorgen om ervoor dat de juiste toegangscontroles en beperkingen worden toegepast op het verkeer binnen het cluster.

Conclusie

Networking is een belangrijk aspect van K8s en speelt een cruciale rol bij het verbinden van pods, services en externe gebruikers in een K8s-cluster. Door het begrijpen en correct configureren van netwerkconcepten en -configuraties, zoals: pods, services, ingress en network policies, kunnen ontwikkelaars betrouwbare en veilige applicaties bouwen die naadloos communiceren binnen het cluster en met externe systemen.

Het toepassen van netwerkconfiguraties in K8s vereist zorgvuldige planning en configuratie. Zo zorg je ervoor dat de communicatie tussen pods en services goed wordt beheerd en beveiligd. Het gebruik van Network Policies kan bijdragen aan het versterken van de beveiliging en het beheren van het verkeer binnen het cluster.

Het begrijpen en toepassen van networking in K8s is een waardevolle vaardigheid voor ontwikkelaars en systeembeheerders die werken met K8s-omgevingen. Door de juiste networkingpraktijken te volgen, kunnen applicaties efficiënt communiceren en schalen binnen een K8s-cluster.

Deel:

Recente blogs