在 Kubernetes 中 Pod 和服務的最終指南

Kubernetes 是一個強大的容器編排平台,但要充分發揮其潛力,了解其核心組件是很重要的,其中 pod 和服務扮演著基礎角色。在本文中,我們將深入探討它們是什麼,以及它們如何共同工作來暴露和管理運行在 Kubernetes 集群內應用程式的訪問。

什麼是 Pod?

Pod是您可以在 Kubernetes 中創建和管理的最小部署單位。

在我們創建一個 pod 之前,讓我們檢查一下您的 Kubernetes 集群中可用的 API 資源;您可以使用 kubectl api-resources 命令。該命令列出了 Kubernetes API 伺服器支援的 API 資源,包括它們的簡稱、API 群組,以及它們是否有命名空間。這對於了解您的集群的能力是很有用的,特別是在使用自定義資源或探索新的 Kubernetes 功能時。kubectl explain 命令通過提供有關單個資源的詳細信息來補充這一點。

讓我們為運行一個簡單的 Nginx 容器的 pod 創建一個基本的 pod 配置文件。

創建一個名為 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

這裡是使用的術語的簡要解釋:

  • apiVersion: v1:指定 API 版本。
  • kind: Pod:表示此配置是為一個 pod。
  • metadata:name:pod 的名稱。
  • metadata: labels:可以用來組織和選擇 Pod 的鍵-值對。
  • spec:containers:將運行在 Pod 中的容器列表。
  • spec:containers:name:容器的名稱。
  • spec:containers:image:要使用的容器映像(在本例中為最新的 Nginx 映像)。
  • spec:containers:ports:從容器中暴露的端口。

使用 kubectl 來應用配置文件並創建 Pod:

  • kubectl apply -f nginx-pod.yaml

檢查 Pod 的狀態,確保已創建並運行:

  • kubectl get pods

您應該看到類似於以下的輸出:

Shell

 

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

接下來,刪除 Pod:

  • kubectl delete pod nginx-pod

輸出應該類似於以下內容:

Shell

 

kubectl get pod
No resources found in default namespace.

服務是什麼?

在 Kubernetes 中為 Nginx Pod 創建服務允許您暴露 Nginx 應用程序並使其在集群內部或外部可訪問。以下是為 Nginx Pod 創建服務的逐步指南。

確保您正在運行一個 Nginx Pod,如果還沒有,請創建一個名為 nginx-pod.yaml 的 YAML 文件:

YAML

 

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

應用 Pod 配置:

創建一個名為nginx-service.yaml的YAML文件來定義Service:

YAML

 

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

以下是一些注意事項:

  • selector: 用於匹配Nginx pod的標籤選擇器。
  • app: nginx: 這應該與Nginx pod中的標籤匹配。
  • type: ClusterIP: Service的類型。ClusterIP使Service僅在集群內可訪問。您也可以使用NodePort或LoadBalancer將Service暴露到外部。

使用kubectl應用Service配置:

  • 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

由於Service的類型是ClusterIP,因此僅在集群內可訪問。如果要從集群外訪問它,可以將Service類型更改為NodePort或LoadBalancer。

使用NodePort來外部暴露Service,修改nginx-service.yaml文件:

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

應用更新後的Service配置:

  • kubectl apply -f nginx-service.yaml

現在可以使用節點的IP地址和節點端口訪問Nginx應用程序(例如,http://<node-ip>:30007)。

多容器Pods

使用每个 pod 一个容器提供了最大的细粒度和解耦性。然而,在某些情况下,部署多个容器,有时被称为复合容器,在单个 pod 内是有益的。这些次要容器可以执行各种角色:处理日志或增强主容器(边车概念),充当对外系统的代理(大使概念),或修改数据以适应外部格式(适配器概念)。这些次要容器通过执行主容器无法处理的任务来补充主容器。

以下是一个 Kubernetes Pod 配置的示例,其中包括一个运行 Nginx 服务器的主容器和一个充当处理日志的边车的次要容器。边车容器使用类似 BusyBox 的简单日志容器来演示它如何追踪 Nginx 访问日志。

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: {}

然后,您需要执行以下操作:

  • 将 YAML 配置保存到文件中,例如 nginx-with-logging-sidecar.yaml
  • 使用 kubectl apply -f nginx-with-logging-sidecar.yaml 应用配置。
  • 验证 Pod 是否正在运行: kubectl get pods
  • 检查边车容器的日志以查看 Nginx 访问日志:kubectl logs -f <pod-name> -c log-sidecar

通過以下步驟,您將刪除現有的 Pod 並應用新配置,設置一個具有 Nginx 容器和一個用於記錄的 sidecar 容器的 Pod。這將確保新配置在您的 Kubernetes 集群中處於活動並運行狀態。

在 Kubernetes 中的多容器 Pod 提供了幾個優勢,使應用部署和管理更靈活和高效。

多容器 Pod 模式

Sidecar 模式

Sidecar 容器可以通過提供輔助功能(如記錄、配置管理或代理)來增強主要應用。此模式有助於擴展功能,而無需修改主要容器。Sidecar 容器可以通過從主應用容器收集和轉發日誌來處理記錄。

大使模式

大使容器充當代理,管理主要應用與外部服務之間的通信。這可以簡化集成和配置。大使容器可能處理 SSL 終止或 API 網關功能。

大使模式涉及使用 sidecar 容器來管理主要應用與外部服務之間的通信。此模式可以處理代理、負載均衡或管理安全連接等任務,從而將復雜性從主應用容器中抽象出來。

  • 主要應用容器:用於發送 HTTP 請求的簡單網絡伺服器
  • 大使容器:配置為管理對外部 API 的請求的 Envoy 代理
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

這個例子演示了在Kubernetes中的Ambassador模式,其中Envoy代理充當中介,管理主應用容器的外部通信。這種模式有助於抽象通信的複雜性,增強模塊化和可維護性。

適配器模式

適配器容器可以在主應用和外部系統之間修改或轉換數據,確保兼容性和集成。例如,適配器容器可以重新格式化日誌數據以滿足外部日誌服務的要求。

在Kubernetes中的適配器模式涉及使用側車容器在主應用容器和外部系統之間轉換數據。當主應用需要的數據格式與外部系統提供的或需要的格式不同時,這將非常有用。

假設您有一個主應用容器生成自定義格式的日誌。您需要將這些日誌發送到需要特定標準格式日誌的外部日誌服務。可以使用適配器容器將日誌數據轉換為所需格式,然後再發送到外部服務。

  • 主應用容器: 一個簡單的應用程序,以自定義格式寫入日誌。
  • 適配器容器: 一個讀取自定義日誌,將其轉換為JSON格式並發送到外部日誌服務的容器。
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: {}

這個例子展示了 Kubernetes 中的適配器模式,其中一個適配器容器將主應用容器的數據轉換為所需格式,然後發送到外部系統。這種模式通過在側載容器內處理數據格式轉換來幫助將應用程序與外部服務集成。

總結

總的來說,Pods:

  • 是 Kubernetes 中最小的可部署單元。
  • 代表正在運行的進程的單個實例。
  • 可以包含一個或多個容器。

Services:

  • 為訪問 Pods 提供穩定的 IP 地址和 DNS 名稱。
  • 在一組 Pods 中實現負載均衡。
  • 促進集群內的服務發現。

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