Der ultimative Leitfaden für Pods und Dienste in Kubernetes

Kubernetes ist eine leistungsstarke Container-Orchestrierungsplattform, aber um ihr volles Potenzial zu nutzen, ist es wichtig, ihre Kernkomponenten zu verstehen, wobei Pods und Services grundlegende Rollen spielen. In diesem Artikel werden wir darauf eingehen, was sie sind und wie sie zusammenarbeiten, um den Zugriff auf Anwendungen innerhalb eines Kubernetes-Clusters freizulegen und zu verwalten.

Was ist ein Pod?

Pods sind die kleinsten bereitstellbaren Recheneinheiten, die Sie in Kubernetes erstellen und verwalten können.

Bevor wir einen Pod erstellen, überprüfen wir die verfügbaren API-Ressourcen in Ihrem Kubernetes-Cluster; Sie können den Befehl kubectl api-resources verwenden. Dieser Befehl listet die von dem Kubernetes-API-Server unterstützten API-Ressourcen auf, einschließlich ihrer Kurznamen, API-Gruppen und ob sie einem Namespace zugeordnet sind oder nicht. Dies ist nützlich, um die Fähigkeiten Ihres Clusters zu verstehen, insbesondere wenn Sie mit benutzerdefinierten Ressourcen arbeiten oder neue Kubernetes-Funktionen erkunden. Der Befehl kubectl explain ergänzt dies, indem er detaillierte Informationen zu einzelnen Ressourcen bereitstellt.

Erstellen wir eine grundlegende Pod-Konfigurationsdatei für einen Pod, der einen einfachen Nginx-Container ausführt.

Erstellen Sie eine Datei mit dem Namen nginx-pod.yaml:

YAML

 

apiVersion: v1
kind: Pod
metadata:
  name: nginx-pod
  labels:
    app: nginx
spec:
  containers:
  - name: nginx
    image: nginx:latest
    ports:
    - containerPort: 80

Hier ist eine kurze Erklärung der verwendeten Begriffe:

  • apiVersion: v1: Gibt die API-Version an.
  • kind: Pod: Zeigt an, dass es sich bei dieser Konfiguration um einen Pod handelt.
  • metadata:name: Der Name des Pods.
  • Metadaten: Labels: Schlüssel-Wert-Paare, die zur Organisation und Auswahl des Pods verwendet werden können.
  • Spezifikation:Container: Eine Liste von Containern, die im Pod ausgeführt werden sollen.
  • Spezifikation:Container:Name: Der Name des Containers.
  • Spezifikation:Container:Abbildung: Das Container-Abbild, das verwendet werden soll (in diesem Fall das neueste Nginx-Abbild).
  • Spezifikation:Container:Ports: Die Ports, die vom Container freigegeben werden sollen.

Verwenden Sie kubectl, um die Konfigurationsdatei anzuwenden und den Pod zu erstellen:

  • kubectl apply -f nginx-pod.yaml

Überprüfen Sie den Status des Pods, um sicherzustellen, dass er erstellt wurde und läuft:

  • kubectl get pods

Sie sollten eine Ausgabe sehen, die ähnlich aussieht wie diese:

Shell

 

NAME         READY   STATUS    RESTARTS    AGE
nginx-pod    1/1     Running   0           10s

Als nächstes löschen Sie den Pod:

  • kubectl delete pod nginx-pod

Die Ausgabe sollte ähnlich aussehen wie folgt:

Shell

 

kubectl get pod
No resources found in default namespace.

Was ist ein Dienst?

Das Erstellen eines Dienstes für einen Nginx-Pod in Kubernetes ermöglicht es Ihnen, die Nginx-Anwendung freizugeben und innerhalb oder außerhalb des Clusters zugänglich zu machen. Hier ist eine schrittweise Anleitung zur Erstellung eines Dienstes für einen Nginx-Pod.

Um sicherzustellen, dass ein Nginx-Pod ausgeführt wird, erstellen Sie, falls nicht bereits vorhanden, eine YAML-Datei mit dem Namen nginx-pod.yaml:

YAML

 

apiVersion: v1
kind: Pod
metadata:
  name: nginx-pod
  labels:
    app: nginx
spec:
  containers:
  - name: nginx
    image: nginx:latest
    ports:
    - containerPort: 80

Wenden Sie die Pod-Konfiguration an:

  • kubectl apply -f nginx-pod.yaml

Erstellen Sie eine YAML-Datei mit dem Namen nginx-service.yaml, um den Service zu definieren:

YAML

 

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

Hier sind einige Dinge zu beachten:

  • selector: Ein Label-Selektor zum Abgleichen des Nginx-Pods.
  • app: nginx: Dies sollte dem Label im Nginx-Pod entsprechen.
  • type: ClusterIP: Der Typ des Services. ClusterIP macht den Service nur innerhalb des Clusters zugänglich. Sie können auch NodePort oder LoadBalancer verwenden, um den Service extern verfügbar zu machen.

Wenden Sie die Service-Konfiguration mit kubectl an:

  • kubectl apply -f nginx-service.yaml
  • kubectl get services
Shell

 

NAME             TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)    AGE
nginx-service    ClusterIP   10.96.0.1        <none>        80/TCP    10s

Da der Service vom Typ ClusterIP ist, ist er nur innerhalb des Clusters zugänglich. Um von außerhalb des Clusters darauf zuzugreifen, können Sie den Servicetyp in NodePort oder LoadBalancer ändern.

Um den Service extern über NodePort verfügbar zu machen, ändern Sie die nginx-service.yaml-Datei:

YAML

 

apiVersion: v1
kind: Service
metadata:
  name: nginx-service
spec:
  selector:
    app: nginx
  ports:
    - protocol: TCP
      port: 80
       targetPort: 80
      nodePort: 30007  # Specify a node port in the range 30000-32767 (optional)
  type: NodePort

Wenden Sie die aktualisierte Service-Konfiguration an:

  • kubectl apply -f nginx-service.yaml

Sie können nun auf die Nginx-Anwendung über die IP-Adresse des Knotens und den Knotenport zugreifen (z.B. http://<knoten-ip>:30007).

Multi-Container-Pods

Die Verwendung eines einzelnen Containers pro Pod bietet maximale Granularität und Entkopplung. Es gibt jedoch Szenarien, in denen es vorteilhaft ist, mehrere Container, manchmal als Composite-Container bezeichnet, innerhalb eines einzelnen Pods bereitzustellen. Diese sekundären Container können verschiedene Aufgaben übernehmen: das Handling von Protokollen oder die Verbesserung des primären Containers (Sidecar-Konzept), das Agieren als Proxy für externe Systeme (Ambassador-Konzept) oder das Anpassen von Daten an ein externes Format (Adapter-Konzept). Diese sekundären Container ergänzen den primären Container, indem sie Aufgaben ausführen, die er nicht übernimmt.

Im Folgenden finden Sie ein Beispiel für eine Kubernetes-Pod-Konfiguration, die einen primären Container enthält, der einen Nginx-Server ausführt, und einen sekundären Container, der als Sidecar für das Protokollieren dient. Der Sidecar-Container verwendet einen einfachen Protokollcontainer wie BusyBox, um zu demonstrieren, wie er die Nginx-Zugriffsprotokolle verfolgen kann.

YAML

 

apiVersion: v1
kind: Pod
metadata:
  name: nginx-with-logging-sidecar
spec:
  containers:
  - name: nginx
    image: nginx:latest
    ports:
    - containerPort: 80
    volumeMounts:
    - name: shared-logs
      mountPath: /var/log/nginx
  - name: log-sidecar
    image: busybox:latest
    command: ["sh", "-c", "tail -f /var/log/nginx/access.log"]
    volumeMounts:
    - name: shared-logs
      mountPath: /var/log/nginx
  volumes:
  - name: shared-logs
    emptyDir: {}

Dann werden Sie Folgendes tun:

  • Speichern Sie die YAML-Konfiguration in einer Datei, z. B. nginx-with-logging-sidecar.yaml
  • Wenden Sie die Konfiguration mit kubectl:kubectl apply -f nginx-with-logging-sidecar.yaml an. 
  • Überprüfen Sie, ob der Pod läuft: kubectl get pods
  • Überprüfen Sie die Protokolle des Sidecar-Containers, um die Nginx-Zugriffsprotokolle zu sehen: kubectl logs -f <pod-name> -c log-sidecar.

Indem Sie diesen Schritten folgen, werden Sie das vorhandene Pod löschen und die neue Konfiguration anwenden, um ein Pod mit einem Nginx-Container und einem Sidecar-Container für das Logging einzurichten. Dadurch wird sichergestellt, dass die neue Konfiguration aktiv ist und in Ihrem Kubernetes-Cluster läuft.

Mehrcontainer-Pods in Kubernetes bieten mehrere Vorteile, die eine flexiblere und effizientere Bereitstellung und Verwaltung von Anwendungen ermöglichen.

Mehrcontainer-Pod-Muster

Sidecar-Muster

Sidecar-Container können die primäre Anwendung verbessern, indem sie Hilfsfunktionen wie Logging, Konfigurationsverwaltung oder Proxying bereitstellen. Dieses Muster hilft dabei, die Funktionalität zu erweitern, ohne den primären Container zu ändern. Ein Sidecar-Container kann das Logging übernehmen, indem er Protokolle von dem Hauptanwendungscontainer sammelt und weiterleitet.

Ambassador-Muster

Ambassador-Container fungieren als Proxy, der die Kommunikation zwischen der primären Anwendung und externen Diensten verwaltet. Dadurch kann die Integration und Konfiguration vereinfacht werden. Ein Ambassador-Container könnte die SSL-Terminierung oder API-Gateway-Funktionen übernehmen.

Das Ambassador-Muster beinhaltet die Verwendung eines Sidecar-Containers zur Verwaltung der Kommunikation zwischen der primären Anwendung und externen Diensten. Dieses Muster kann Aufgaben wie Proxying, Lastverteilung oder das Verwalten sicherer Verbindungen übernehmen und damit die Komplexität vom primären Anwendungscontainer abstrahieren.

  • Primärer Anwendungscontainer: Ein einfacher Webserver, der HTTP-Anfragen stellt
  • Ambassador-Container: Envoy-Proxy konfiguriert zur Verwaltung von Anfragen an die externe API
YAML

 

apiVersion: v1
kind: Pod
metadata:
  name: app-with-ambassador
spec:
  containers:
  - name: web-app
    image: python:3.8-slim
    command: ["python", "-m", "http.server", "8000"]
    volumeMounts:
    - name: config-volume
      mountPath: /etc/envoy
  - name: envoy-proxy
    image: envoyproxy/envoy:v1.18.3
    args: ["-c", "/etc/envoy/envoy.yaml"]
    ports:
    - containerPort: 8080
    volumeMounts:
    - name: config-volume
      mountPath: /etc/envoy
  volumes:
  - name: config-volume
    configMap:
      name: envoy-config

---
apiVersion: v1
kind: ConfigMap
metadata:
  name: envoy-config
data:
  envoy.yaml: |
    static_resources:
      listeners:
      - name: listener_0
        address:
          socket_address:
            address: 0.0.0.0
            port_value: 8080
        filter_chains:
        - filters:
          - name: envoy.filters.network.http_connection_manager
            typed_config:
              "@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
              stat_prefix: ingress_http
              route_config:
                name: local_route
                virtual_hosts:
                - name: local_service
                  domains: ["*"]
                  routes:
                  - match:
                      prefix: "/"
                    route:
                      cluster: external_service
              http_filters:
              - name: envoy.filters.http.router
      clusters:
      - name: external_service
        connect_timeout: 0.25s
        type: LOGICAL_DNS
        lb_policy: ROUND_ROBIN
        load_assignment:
          cluster_name: external_service
          endpoints:
          - lb_endpoints:
            - endpoint:
                address:
                  socket_address:
                    address: api.example.com
                    port_value: 80

Dieses Beispiel demonstriert das Botschafter-Muster in Kubernetes, bei dem ein Envoy-Proxy als Vermittler fungiert, um die externe Kommunikation für den primären Anwendungscontainer zu verwalten. Dieses Muster hilft dabei, Kommunikationskomplexitäten zu abstrahieren und die Modularität sowie die Wartbarkeit zu verbessern.

Adapter-Muster

Adaptercontainer können Daten zwischen der primären Anwendung und externen Systemen modifizieren oder transformieren, um Kompatibilität und Integration sicherzustellen. Zum Beispiel kann ein Adaptercontainer Logdaten neu formatieren, um den Anforderungen eines externen Protokollierungsdienstes zu entsprechen.

Das Adaptermuster in Kubernetes beinhaltet die Verwendung eines Sidecar-Containers zur Datenübertragung zwischen dem primären Anwendungscontainer und externen Systemen. Dies kann nützlich sein, wenn die primäre Anwendung Daten in einem spezifischen Format benötigt, das sich vom bereitgestellten Format externer Systeme unterscheidet.

Angenommen, Sie haben einen primären Anwendungscontainer, der Protokolle in einem benutzerdefinierten Format generiert. Diese Protokolle müssen an einen externen Protokollierungsdienst gesendet werden, der Protokolle in einem spezifischen standardisierten Format erfordert. Ein Adaptercontainer kann verwendet werden, um die Protokolldaten in das erforderliche Format zu transformieren, bevor sie an den externen Dienst gesendet werden.

  • Primärer Anwendungscontainer: Eine einfache Anwendung, die Protokolle in einem benutzerdefinierten Format schreibt.
  • Adaptercontainer: Ein Container, der die benutzerdefinierten Protokolle liest, sie in JSON-Format umwandelt und an einen externen Protokollierungsdienst sendet.
YAML

 

apiVersion: v1
kind: Pod
metadata:
  name: app-with-adapter
spec:
  containers:
  - name: log-writer
    image: busybox
    command: ["sh", "-c", "while true; do echo \"$(date) - Custom log entry\" >> /var/log/custom/app.log; sleep 5; done"]
    volumeMounts:
    - name: shared-logs
      mountPath: /var/log/custom
  - name: log-adapter
    image: busybox
    command: ["sh", "-c", "tail -f /var/log/custom/app.log | while read line; do echo \"$(echo $line | sed 's/ - / - {\"timestamp\": \"/;s/$/\"}/')\" >> /var/log/json/app.json; done"]
    volumeMounts:
    - name: shared-logs
      mountPath: /var/log/custom
    - name: json-logs
      mountPath: /var/log/json
  - name: log-sender
    image: busybox
    command: ["sh", "-c", "while true; do cat /var/log/json/app.json | grep -v '^$' | while read line; do echo \"Sending log to external service: $line\"; done; sleep 10; done"]
    volumeMounts:
    - name: json-logs
      mountPath: /var/log/json
  volumes:
  - name: shared-logs
    emptyDir: {}
  - name: json-logs
    emptyDir: {}

Dieses Beispiel demonstriert das Adapter-Muster in Kubernetes, bei dem ein Adapter-Container Daten vom primären Anwendungscontainer in das erforderliche Format umwandelt, bevor er sie an ein externes System sendet. Dieses Muster hilft dabei, Anwendungen mit externen Diensten zu integrieren, indem Datenformat-Transformationen im Sidecar-Container behandelt werden.

Zusammenfassung

Zusammenfassend, Pods:

  • Sind die kleinsten bereitstellbaren Einheiten in Kubernetes.
  • Stellen eine einzelne Instanz eines laufenden Prozesses dar.
  • Können einen oder mehrere Container enthalten.

Services:

  • Stellen eine stabile IP-Adresse und DNS-Namen für den Zugriff auf Pods bereit.
  • Ermöglichen Lastenausgleich über eine Gruppe von Pods.
  • Erleichtern die Dienstsuche innerhalb des Clusters.

Source:
https://dzone.com/articles/the-ultimate-guide-to-kubernetes-pods-and-services