Skip to main content

Best Practices für Kubernetes-Netzwerkrichtlinien

Artikel von

Peter De Tender

Kubernetes Blog

21. Dezember 2022

0 Min. Lesezeit

Die Steuerung und Filterung des Datenverkehrs beim Ausführen einer containerisierten Workload in Kubernetes-Pods ist genauso wichtig wie eine Firewall in einer herkömmlichen Netzwerkkonfiguration. Der Unterschied: In diesem Fall stellt die Kubernetes NetworkPolicy API diese Funktionen bereit.

In diesem Artikel lernen wir Kubernetes NetworkPolicy kennen. Dazu erstellen wir eine Beispiel-Netzwerkrichtlinie und untersuchen ihre wichtigsten Parameter. Anschließend sehen wir uns gängige Anwendungsfälle für NetworkPolicy an und erfahren, wie Sie sie mit kubectl überwachen. Zum Schluss erfahren Sie, wie Sie die Container Network Interface (CNI) mithilfe von Kubernetes-Erweiterungen von Drittanbietern implementieren.

Warum Sie sich nicht vor Kubernetes-Netzwerkrichtlinien scheuen sollten

Die Implementierung von Netzwerkrichtlinien ist für den Betrieb einer Kubernetes-Umgebung entscheidend. Ohne konfigurierte Netzwerkrichtlinie können standardmäßig alle Pods innerhalb eines Clusters miteinander kommunizieren. Enthält unser Pod also sensible Daten, etwa eine Backend-Datenbank mit vertraulichen Informationen, müssen wir sicherstellen, dass nur bestimmte Frontend-Pods eine Verbindung herstellen können.

Alternativ können wir den Netzwerkverkehr zwischen Pods in einer Entwicklungsumgebung von dem der Pods in einer Produktionsumgebung isolieren. Ohne Netzwerkrichtlinien kann der gesamte Datenverkehr ungehindert zu und von allen Punkten im Netzwerk fließen.

Zum Glück ist die Konfiguration von Kubernetes NetworkPolicy eine einfache, effektive und ganzheitliche Möglichkeit, sicherzustellen, dass unser Netzwerkverkehr nur wie vorgesehen fließt.

Kubernetes-Netzwerkrichtlinien definieren

Sehen wir uns eine Beispiel-NetworkPolicy an. Stellen Sie sich eine Beispiel-Workload mit einem WordPress-Frontend und einer MySQL-Backend-Datenbank vor. Sie umfasst mehrere Pods mit Web- und Datenbankdiensten, die alle im Kubernetes-Namespace default bereitgestellt werden. Die Sicherheitsprotokolle des Unternehmens verlangen, dass wir den Netzwerkverkehr für bestimmte Workloads isolieren und nur den unbedingt erforderlichen ein- und ausgehenden Datenverkehr zu diesen Workloads zulassen.

Diese Strategie umfasst die folgenden Bedingungen:

  • Das standardmäßige Kubernetes-Verhalten unterbinden, bei dem sämtlicher Datenverkehr zugelassen wird.

  • Sicherstellen, dass nur Pods mit dem Label wordpress im Namespace default miteinander kommunizieren können.

  • Eingehende Verbindungen (ingress) aus dem öffentlichen Internet über die Ports 80/443 und den IP-Bereich 172.16.0.0 zulassen.

  • Nur Pods mit dem Label wordpress Verbindungen zu den MySQL-Datenbank-Pods über Port 3306 erlauben.

  • Verbindungen zum Kubernetes-DNS-Dienst (Port 53) stets zulassen.

  • Jegliche ausgehende Verbindung außerhalb des Clusters unterbinden.

Das folgende Netzwerkdiagramm veranschaulicht, wie diese Regeln aussehen könnten.

Diagramm mit standardmäßigen Deny-Richtlinien für Ingress und Egress im Kubernetes-Namespace. Ausgewählter Port 80, 443 und DNS-Datenverkehr sind zugelassen.

Für dieses Beispiel können wir die Netzwerkrichtlinien entweder auf mehrere Richtliniendefinitionsdateien verteilen oder alle Richtlinien in einer einzigen YAML-Manifestdatei zusammenfassen. Da unser Beispiel eine Workload (webapp) verwendet, ist eine einzelne Regeldefinitionsdatei sinnvoll. Da dieses Beispiel jedoch mehrere Ingress- und Egress-Verbindungen enthält, könnten wir alternativ für jede Verbindung innerhalb des Clusters eine eigene Konfigurationsdatei erstellen.

Sehen wir uns einige der oben verwendeten Parameter an, um zu verstehen, wie sie mit der Konfiguration zusammenhängen und das Verhalten des Netzwerkverkehrs beeinflussen.

API und Metadaten

In der ersten Zeile der folgenden YAML-Datei geben wir die Networking-API (networking.k8s.io) und ihre Version (v1) an. Außerdem legen wir den Typ der YAML-Datei als NetworkPolicy fest. Damit informieren wir den Kubernetes-API-Controller, dass wir Netzwerkrichtlinien konfigurieren. Die Einträge name und namespace im Abschnitt metadata enthalten den Namen unseres Regelsatzes und den Namespace, dem er zugeordnet ist.

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: sample-network-policy
  namespace: default

Der nächste Teil der YAML-Datei enthält den Abschnitt mit den Spezifikationen (specs), in dem wir Filter festlegen können, für die die Netzwerkrichtlinie gilt.

Der folgende Abschnitt enthält mehrere wichtige Parameter:

  • podSelector — Gibt an, für welche Pods die festgelegten Datenverkehrsrichtlinien gelten. In unserem Beispiel wird der Parameter matchLabels verwendet, damit die Netzwerkrichtlinie für alle Pods mit dem Label app: wordpress gilt. Gleichzeitig schließt dieser Parameter alle anderen Pods von der Netzwerkrichtlinie aus.

  • policyTypes — Umfasst zwei Kategorien: Ingress und Egress

  • Ingress — Definiert den gesamten eingehenden Datenverkehr von Pods, Namespaces und Pod-Sammlungen

  • Egress — Definiert den gesamten ausgehenden Datenverkehr von Pods, Namespaces und Pod-Sammlungen

spec:
  podSelector:
    matchLabels:
      app: wordpress
  policyTypes:
    - Egress
    - Ingress

Als Nächstes definiert der Abschnitt ingress der Netzwerkrichtlinie die Arten des zulässigen eingehenden Datenverkehrs. Im folgenden Abschnitt wird Ingress über die Ports 443 und 80 zugelassen von:

  • Allen Pods mit dem Label wordpress

  • Dem gesamten Datenverkehr aus dem öffentlichen Internet (cidr: 0.0.0.0/0)

  • Allen IP-Adressen im Bereich 172.16.0.0/16, der beispielsweise einen Unternehmens-IP-Bereich (VPN, VLAN oder Subnetz) darstellen könnte.

Der YAML-Ausschnitt, der den oben beschriebenen Datenverkehr ermöglicht, sieht so aus:

  ingress:
    - from:
      - podSelector:
          matchLabels:
            app: wordpress
      ports:
        - port: 443
        - port: 80  
    - from:
      - ipBlock:
          cidr: 172.16.0.0/16
      ports:
        - port: 443
        - port: 80
    - from:
      - ipBlock:
          cidr: 0.0.0.0/0
      ports:
        - port: 443
        - port: 80

Abschließend beschreiben wir im Abschnitt egress die Regeln für ausgehenden Datenverkehr. Wir erlauben den gesamten ausgehenden Datenverkehr von Pods mit dem Label webapp über die Ports 1433 (SQL) und 53 (DNS).

Durch die Angabe des Labels webapp wird sichergestellt, dass keine anderen Pods mit den SQL-Server-Instanzen kommunizieren können. So werden alle damit verbundenen Sicherheitsrisiken beseitigt. Ebenso erlaubt die Konfiguration Verbindungen über Port 53 zu allen Pods im Cluster.

Diese Richtliniendefinition hat noch eine weitere wichtige Erkenntnis für uns: Sobald wir Netzwerkrichtlinien zur Steuerung der Pod-Konnektivität einsetzen, müssen wir die Zulassungs- und Ablehnungseinstellungen in beide Richtungen konfigurieren. Wenn wir ausgehenden Datenverkehr vom Frontend zulassen, aber eingehenden Datenverkehr zum Backend nicht, ist keine Kommunikation möglich.

Der YAML-Ausschnitt für diesen Teil des Datenverkehrs sieht wie im folgenden Beispiel aus:

  egress: 
    - to:
        - namespaceSelector: {}
          podSelector:
            matchLabels:
              k8s-app: kube-dns
      ports:
        - port: 53
          protocol: UDP

    - to:
        - podSelector:
            matchLabels:
              app: wordpress
      ports:
        - port: 3306

Kubernetes-Netzwerkrichtlinien anwenden

Unser Beispiel-YAML-Manifest für die Network Policy ist nun fertig und sieht so aus:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: sample-network-policy
  namespace: default
spec:
  podSelector:
    matchLabels:
      app: webapp
  policyTypes:
    - Egress
    - Ingress
  ingress:
    - from:
        - podSelector:
            matchLabels:
              app: webapp
      ports:
        - port: 443
        - port: 80
    - from:
        - podSelector: {}
    - from:
        - ipBlock:
            cidr: 172.16.0.0/16
      ports:
        - port: 443
        - port: 80
    - from:
        - ipBlock:
            cidr: 0.0.0.0/0
      ports:
        - port: 443
        - port: 80
  egress:
    - to:
        - namespaceSelector: {}
          podSelector:
            matchLabels:
              k8s-app: kube-dns
      ports:
        - port: 53
          protocol: UDP
    - to:
        - podSelector: {}
    - to:
        - podSelector:
            matchLabels:
              app: webapp
      ports:
        - port: 443
        - port: 80

Jetzt müssen wir unsere Datei in den Kubernetes-Cluster einspielen. Speichern Sie die Datei dazu zunächst unter dem Namen sample-network-policy.yaml.

Nun wenden wir die Definitionsdatei wie die meisten anderen Kubernetes-Konfigurationen mithilfe der kubectl-Befehlszeilenschnittstelle (CLI) an.

Führen Sie den folgenden Befehl aus:

kubectl apply -f sample-network-policy.yaml
Terminal, in dem kubectl apply die Kubernetes-Netzwerkrichtlinie für das Beispiel erstellt

Kubernetes-Netzwerkrichtlinien validieren und überwachen

Wie bei der Verwaltung herkömmlicher Firewalls erfordert auch die Validierung und Überwachung von Kubernetes-Netzwerkrichtlinien eine laufende Kontrolle. Gelegentlich müssen wir vorhandene Netzwerkregeln erneut bewerten, um festzustellen, ob sie weiterhin für die zugehörige Workload gelten.

Möglicherweise müssen wir den Regelsatz auch validieren, um Probleme mit dem Datenverkehr zu beheben oder Konflikte zwischen verschiedenen Netzwerkrichtlinien zu untersuchen. Zum Glück lassen sich Network Policies mit der kubectl-CLI validieren. Mit dem folgenden Befehl analysieren und überwachen Sie Ihre aktuellen Netzwerkrichtlinien:

kubectl describe networkpolicy <networkpolicy name as listed in the YAML manifest>

Im Folgenden sehen Sie eine Beispielausgabe für den Richtlinientyp ingress.

Terminalausgabe mit einer Kubernetes-NetworkPolicy, in der „Allowing ingress traffic“ hervorgehoben ist, sowie Regeln für die Ports 443 und 80.

Dieses Bild zeigt außerdem eine Beispielausgabe für den Richtlinientyp egress:

Terminalausgabe mit zulässigem ausgehendem Datenverkehr zu kube-dns- und Web-App-Pods sowie den Richtlinientypen Egress und Ingress

Best Practices für die Anwendung von Kubernetes-Netzwerkrichtlinien

Wie bei jeder Netzwerksicherheitskonfiguration sollten wir auch für unsere Kubernetes-Netzwerkrichtlinien einige Best Practices beachten:

  • Verwenden Sie die standardmäßige Netzwerkrichtlinie deny-all, um sicherzustellen, dass nur ausdrücklich erlaubte Kommunikation stattfindet.

  • Gruppieren Sie Pods, die miteinander kommunizieren müssen, mithilfe des Parameters PodSelector.

  • Erlauben Sie die Kommunikation zwischen Namespaces nur, wenn sie erforderlich ist.

  • Erlauben Sie keine unnötige Netzwerkkommunikation – auch nicht innerhalb des Kubernetes-Clusters.

  • Seien Sie vorsichtig, wenn Sie Pods innerhalb des Clusters den Empfang von Netzwerkverkehr außerhalb des Clusters erlauben.

  • Das Unterbinden ausgehenden Datenverkehrs ins öffentliche Internet kann bestimmte Anwendungsupdates oder Validierungsprozesse beeinträchtigen.

Kubernetes-CNI-Plugins optimieren die Verwaltung von Netzwerkrichtlinien

Ein Vorteil von CNI-Plugins ist, dass sie die Implementierungsdetails der Network Policy abstrahieren. So können Cluster-Administratoren die für ihre Anforderungen beste Lösung auswählen, ohne sich mit der Komplexität der zugrunde liegenden Technologien auseinandersetzen zu müssen.

Bei Standardinstallationen von Kubernetes ist jedoch kein CNI-Plugin vorinstalliert, es sei denn, Ihre Distribution oder Ihr Anbieter hat eines hinzugefügt. Das bedeutet, dass Sie das Plugin auswählen und installieren müssen, das Ihren Anforderungen am besten entspricht. Selbst wenn Ihre Distribution ein Standard-Plugin enthält, erfüllt möglicherweise ein anderes Ihre Anforderungen besser.

Es gibt eine Vielzahl von CNI-Anbietern, darunter einige der beliebtesten:

Jedes Plugin bietet bestimmte einzigartige Funktionen. Möglicherweise müssen Sie daher mehrere ausprobieren, um herauszufinden, welche Option Ihren Anforderungen an Netzwerk und Netzwerksicherheit am besten entspricht.

Fazit

Die Konfiguration einer unternehmensweiten Netzwerktopologie mit komplexem Routing, Datenverkehrsregeln und Sicherheitsintegrationen kann mühsam sein. Zum Glück können Netzwerkrichtlinien in einer Kubernetes-Umgebung dieselben Aufgaben übernehmen, für die sich Firewalls in herkömmlichen Infrastrukturen bewährt haben.

Die Konfiguration von Netzwerkrichtlinien ist natürlich nur der erste Schritt in einem Prozess, der regelmäßige Neubewertungen und Wartung erfordert. Das integrierte kubenet-Plugin bietet zwar bestimmte Netzwerkfunktionen für die Verwaltung Ihrer Richtlinien, doch andere CNI-Plugins stellen erweiterte Funktionen bereit. Mit der passenden Kombination aus Richtlinien und Verwaltung bleibt Ihr Netzwerkverkehr sicher und effizient.

Weitere Ressourcen zur Kubernetes-Sicherheit

Sichern Sie Ihre Infrastruktur an der Quelle

Snyk automatisiert die IaC-Sicherheit und Compliance in Workflows und erkennt abweichende sowie fehlende Ressourcen.