一文帶您探索 Kubernetes 中的容器類型
前言
在 Kubernetes 中,containers被部署和管理在 Pod 中。Pod 是 Kubernetes 對象模型中最小和最簡單的單元,可以被創建、部署和管理。在這里,您可以在單個 pod 中使用不同的容器類型來實現特定的功能。以下是在 Kubernetes 中常用的一些容器類型:
- Init Container: 初始化容器
- Sidecar Container: 邊車容器
- Ephemeral Container: 臨時容器
- Multi Container: 多容器
Init Container
一個Pod 可以在其中運行多個容器來運行應用程序,但它也可以有一個或多個 init 容器,在應用程序容器啟動之前運行。Init 容器旨在在主應用程序容器啟動之前運行初始化任務。它們可用于設置配置文件、初始化數據庫或等待外部服務準備就緒等任務。Init 容器與常規容器完全相同,只是:
- 初始化容器始終運行至完成。
- 每個初始化容器必須在下一個初始化容器開始之前成功完成。
案例
apiVersion: v1
kind: Pod
metadata:
name: nginx-init
labels:
app: nginx
spec:
initContainers:
#Initializing container
- name: init-container
image: alpine
command: ['sh', '-c', 'echo "<h1>This is from INIT container</h1>" >> /usr/share/nginx/html/index.html']
volumeMounts:
- name: data
mountPath: /usr/share/nginx/html
containers:
# application container i.e., main container
- name: app
image: nginx
volumeMounts:
- name: data
mountPath: /usr/share/nginx/html
volumes:
- name: data
emptyDir: {}
這里的 init-container 將使用數據卷的data 覆蓋 nginx 主頁的 index.html。
Service編排文件
apiVersion: v1
kind: Service
metadata:
name: nginx-svc
labels:
app: nginx
spec:
type: NodePort
selector:
app: nginx
ports:
- port: 80
targetPort: 80
創建Pod和Service
kubectl apply -f nginx-init.yaml
kubectl apply -f nginx-service.yaml
現在,如果您嘗試通過瀏覽器訪問nginx端點,您將會得到以下輸出。
image
Sidecar Container
邊車容器是與主應用容器在同一個 Pod 中運行的次要容器。這些容器用于通過提供額外的服務或功能,如日志記錄、監控、安全性或數據同步,來增強或擴展主應用容器的功能,而無需直接修改主應用程序代碼。
使用邊車容器的示例:
創建nginx-sidecar.yaml:
apiVersion: v1
kind: Pod
metadata:
name: nginx-pod
labels:
app: nginx
spec:
containers:
#App container
- name: nginx-container
image: nginx:latest
ports:
- containerPort: 80
volumeMounts:
- name: logs
mountPath: /var/log/nginx
#This is side container
- name: sidecar-container
image: busybox
command: ["/bin/sh"]
args: ["-c", "tail -f /var/log/nginx/access.log"]
volumeMounts:
- name: logs
mountPath: /var/log/nginx
volumes:
- name: logs
emptyDir: {}
上述 Pod 包含兩個容器,一個是應用容器(nginx),另一個是 sidecar 容器,我們使用它來收集主應用程序的 nginx 訪問日志。
創建 nginx-svc.yaml:
apiVersion: v1
kind: Service
metadata:
name: nginx-svc
labels:
app: nginx
spec:
type: NodePort
selector:
app: nginx
ports:
- port: 80
targetPort: 80
創建Pod和Service
kubectl apply -f nginx-sidecar.yaml
kubectl apply -f nginx-svc.yaml
現在,如果您嘗試通過瀏覽器訪問nginx端點,您將看到nginx的歡迎頁面。然后,如果您嘗試使用下面的命令訪問邊車日志,您將獲得我們最近訪問的訪問日志。
kubectl logs nginx-pod -c sidecar-container
k logs nginx-pod -c sidecar-container
10.244.0.1 - - [17/Jan/2024:18:25:02 +0000] "GET / HTTP/1.1" 200 615 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36" "-"
10.244.0.1 - - [17/Jan/2024:18:25:02 +0000] "GET /favicon.ico HTTP/1.1" 404 555 "http://127.0.0.1:53471/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36" "-"
10.244.0.1 - - [17/Jan/2024:18:25:24 +0000] "GET / HTTP/1.1" 304 0 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36" "-"
10.244.0.1 - - [17/Jan/2024:18:25:25 +0000] "GET / HTTP/1.1" 304 0 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36" "-"
Ephemeral Container
Ephemeral containers 與其他容器不同之處在于它們缺乏資源或執行的保證,并且永遠不會自動重新啟動,因此不適合用于構建應用程序。Ephemeral containers 使用與常規容器相同的 ContainerSpec 進行描述,但許多字段對于臨時容器是不兼容且被禁止的。
臨時容器可能沒有端口,因此禁止使用端口、存活探針、就緒探針等字段。Pod資源分配是不可變的,因此禁止設置資源。
臨時容器對于交互式故障排除非常有用,當使用 kubectl exec 不足以解決問題時,比如容器崩潰或容器鏡像不包含調試工具。
我們可以通過兩種方式調試一個 Pod。
a. 使用臨時容器進行調試
如果您的 Pod 正在運行但無法執行到它,那么您可以使用這種方法。您可以使用 kubectl debug 命令向正在運行的 Pod 添加臨時容器。這種方法將在同一 Pod 中創建一個新容器。
kubectl debug -it <RUNNING-POD> --image=<DEBUG-IMAGE>:<DEBUG-IMAGE-TAG> --target=<RUNNING-CONTAINER>
請將替換為您現有的 Pod 名稱,將替換為您想要調試的現有容器。此命令將添加一個新的 busybox 容器并附加到它上。
b. 使用該 pod 的副本進行調試
如果您的 Pod 崩潰并且無法執行到它,那么您可以使用這種方法。這種方法將創建一個新的 Pod,其中包含新的調試容器以及原始 Pod 中的容器。
kubectl debug <ORIGINAL-POD> -it --image=<DEBUG-IMAGE>:<DEBUG-IMAGE-TAG> --share-processes --copy-to=<NEW-DEBUG-POD>
請將原始 Pod 名稱替換為 ORIGINAL-POD,將新的調試 Pod 名稱替換為 NEW-DEBUG-POD,新的調試 Pod 是原始 Pod 的副本。
案例
創建ephemeral-pod.yaml:
apiVersion: v1
kind: Pod
metadata:
name: ephemeral-pod
spec:
containers:
- image: registry.k8s.io/pause:3.1
name: ephemeral-container
restartPolicy: Never
這個 YAML 文件將創建一個暫停容器鏡像,不包含調試工具。
kubectl apply -f ephermeral-pod.yaml
以上命令將在默認命名空間中創建一個臨時 Pod。
k get po
NAME READY STATUS RESTARTS AGE
ephemeral-pod 1/1 Running 0 3m41s
讓我們嘗試使用下面的命令來執行它。
kubectl exec -it ephemeral-pod -- sh
但是會出現下面的錯誤,因為這個容器鏡像中沒有 shell。
kubectl exec -it ephemeral-pod -- sh
OCI runtime exec failed: exec failed: unable to start container process: exec: "sh": executable file not found in $PATH: unknown
command terminated with exit code 126
現在讓我們嘗試使用調試容器,即臨時容器,進入到該 Pod 中。
使用以下命令創建一個臨時容器,并將其附加到上述 Pod,即 ephemeral-pod。
kubectl debug -it ephemeral-pod --image=busybox --target=ephemeral-container
這個命令會添加一個新的 busybox 容器并將其附加到臨時 pod 上。--target 參數指定我們要執行的容器。此外,該命令將自動連接到臨時容器的控制臺。
輸出:
kubectl debug -it ephemeral-pod --image=busybox --target=ephemeral-container
Targeting container "ephemeral-container". If you don't see processes from this container it may be because the container runtime doesn't support this feature.
Defaulting debug container name to debugger-q6svq.
If you don't see a command prompt, try pressing enter.
/ #
/ #
現在您可以訪問實際的容器,即臨時容器,并進行調試
Multi Container
Kubernetes允許您定義具有多個并行運行的容器的Pod。這些容器共享相同的網絡命名空間,并可以通過localhost相互通信。這些多容器Pod旨在用于需要緊密耦合的進程一起運行、共享資源和數據的場景。
案例
創建nginx-multi-container-pod.yaml:
apiVersion: v1
kind: Pod
metadata:
name: nginx-pod
labels:
app: nginx
spec:
containers:
#App container
- name: nginx-container
image: nginx:latest
ports:
- containerPort: 80
volumeMounts:
- name: data
mountPath: /usr/share/nginx/html
#This is extra container
- name: extra-container
image: debian
command: ["/bin/sh", "-c"]
args:
- while true; do
date > /usr/share/nginx/html/index.html;
sleep 1;
done
volumeMounts:
- name: data
mountPath: /usr/share/nginx/html
volumes:
- name: data
emptyDir: {}
以上清單文件中有兩個容器,一個是主應用程序,即 nginx,另一個是額外的容器,將幫助我們持續更新 nginx 網頁應用的主頁。
創建 nginx-svc.yaml:
apiVersion: v1
kind: Service
metadata:
name: nginx-svc
labels:
app: nginx
spec:
type: NodePort
selector:
app: nginx
ports:
- port: 80
targetPort: 80
創建 Pod 和 Service
kubectl apply -f nginx-multi-container-pod.yaml
kubectl apply -f nginx-svc.yaml
現在,如果您嘗試通過瀏覽器訪問nginx端點,您將看到由上面的額外容器更新的日期。