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
的文件:
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
您應該看到類似於以下的輸出:
NAME READY STATUS RESTARTS AGE
nginx-pod 1/1 Running 0 10s
接下來,刪除 Pod:
kubectl delete pod nginx-pod
輸出應該類似於以下內容:
kubectl get pod
No resources found in default namespace.
服務是什麼?
在 Kubernetes 中為 Nginx Pod 創建服務允許您暴露 Nginx 應用程序並使其在集群內部或外部可訪問。以下是為 Nginx Pod 創建服務的逐步指南。
確保您正在運行一個 Nginx 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
應用 Pod 配置:
創建一個名為nginx-service.yaml
的YAML文件來定義Service:
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
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
文件:
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 访问日志。
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 代理
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格式並發送到外部日誌服務的容器。
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