一文帶您探索 Kubernetes 中的容器類型
前言
在 Kubernetes 中,containers被部署和管理在 Pod 中。Pod 是 Kubernetes 對(duì)象模型中最小和最簡(jiǎn)單的單元,可以被創(chuàng)建、部署和管理。在這里,您可以在單個(gè) pod 中使用不同的容器類型來實(shí)現(xiàn)特定的功能。以下是在 Kubernetes 中常用的一些容器類型:
- Init Container: 初始化容器
- Sidecar Container: 邊車容器
- Ephemeral Container: 臨時(shí)容器
- Multi Container: 多容器
Init Container
一個(gè)Pod 可以在其中運(yùn)行多個(gè)容器來運(yùn)行應(yīng)用程序,但它也可以有一個(gè)或多個(gè) init 容器,在應(yīng)用程序容器啟動(dòng)之前運(yùn)行。Init 容器旨在在主應(yīng)用程序容器啟動(dòng)之前運(yùn)行初始化任務(wù)。它們可用于設(shè)置配置文件、初始化數(shù)據(jù)庫或等待外部服務(wù)準(zhǔn)備就緒等任務(wù)。Init 容器與常規(guī)容器完全相同,只是:
- 初始化容器始終運(yùn)行至完成。
- 每個(gè)初始化容器必須在下一個(gè)初始化容器開始之前成功完成。
案例
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 將使用數(shù)據(jù)卷的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
創(chuàng)建Pod和Service
kubectl apply -f nginx-init.yaml
kubectl apply -f nginx-service.yaml
現(xiàn)在,如果您嘗試通過瀏覽器訪問nginx端點(diǎn),您將會(huì)得到以下輸出。
image
Sidecar Container
邊車容器是與主應(yīng)用容器在同一個(gè) Pod 中運(yùn)行的次要容器。這些容器用于通過提供額外的服務(wù)或功能,如日志記錄、監(jiān)控、安全性或數(shù)據(jù)同步,來增強(qiáng)或擴(kuò)展主應(yīng)用容器的功能,而無需直接修改主應(yīng)用程序代碼。
使用邊車容器的示例:
創(chuàng)建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 包含兩個(gè)容器,一個(gè)是應(yīng)用容器(nginx),另一個(gè)是 sidecar 容器,我們使用它來收集主應(yīng)用程序的 nginx 訪問日志。
創(chuàng)建 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
創(chuàng)建Pod和Service
kubectl apply -f nginx-sidecar.yaml
kubectl apply -f nginx-svc.yaml
現(xiàn)在,如果您嘗試通過瀏覽器訪問nginx端點(diǎn),您將看到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 與其他容器不同之處在于它們?nèi)狈Y源或執(zhí)行的保證,并且永遠(yuǎn)不會(huì)自動(dòng)重新啟動(dòng),因此不適合用于構(gòu)建應(yīng)用程序。Ephemeral containers 使用與常規(guī)容器相同的 ContainerSpec 進(jìn)行描述,但許多字段對(duì)于臨時(shí)容器是不兼容且被禁止的。
臨時(shí)容器可能沒有端口,因此禁止使用端口、存活探針、就緒探針等字段。Pod資源分配是不可變的,因此禁止設(shè)置資源。
臨時(shí)容器對(duì)于交互式故障排除非常有用,當(dāng)使用 kubectl exec 不足以解決問題時(shí),比如容器崩潰或容器鏡像不包含調(diào)試工具。
我們可以通過兩種方式調(diào)試一個(gè) Pod。
a. 使用臨時(shí)容器進(jìn)行調(diào)試
如果您的 Pod 正在運(yùn)行但無法執(zhí)行到它,那么您可以使用這種方法。您可以使用 kubectl debug 命令向正在運(yùn)行的 Pod 添加臨時(shí)容器。這種方法將在同一 Pod 中創(chuàng)建一個(gè)新容器。
kubectl debug -it <RUNNING-POD> --image=<DEBUG-IMAGE>:<DEBUG-IMAGE-TAG> --target=<RUNNING-CONTAINER>
請(qǐng)將替換為您現(xiàn)有的 Pod 名稱,將替換為您想要調(diào)試的現(xiàn)有容器。此命令將添加一個(gè)新的 busybox 容器并附加到它上。
b. 使用該 pod 的副本進(jìn)行調(diào)試
如果您的 Pod 崩潰并且無法執(zhí)行到它,那么您可以使用這種方法。這種方法將創(chuàng)建一個(gè)新的 Pod,其中包含新的調(diào)試容器以及原始 Pod 中的容器。
kubectl debug <ORIGINAL-POD> -it --image=<DEBUG-IMAGE>:<DEBUG-IMAGE-TAG> --share-processes --copy-to=<NEW-DEBUG-POD>
請(qǐng)將原始 Pod 名稱替換為 ORIGINAL-POD,將新的調(diào)試 Pod 名稱替換為 NEW-DEBUG-POD,新的調(diào)試 Pod 是原始 Pod 的副本。
案例
創(chuàng)建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
這個(gè) YAML 文件將創(chuàng)建一個(gè)暫停容器鏡像,不包含調(diào)試工具。
kubectl apply -f ephermeral-pod.yaml
以上命令將在默認(rèn)命名空間中創(chuàng)建一個(gè)臨時(shí) Pod。
k get po
NAME READY STATUS RESTARTS AGE
ephemeral-pod 1/1 Running 0 3m41s
讓我們嘗試使用下面的命令來執(zhí)行它。
kubectl exec -it ephemeral-pod -- sh
但是會(huì)出現(xiàn)下面的錯(cuò)誤,因?yàn)檫@個(gè)容器鏡像中沒有 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
現(xiàn)在讓我們嘗試使用調(diào)試容器,即臨時(shí)容器,進(jìn)入到該 Pod 中。
使用以下命令創(chuàng)建一個(gè)臨時(shí)容器,并將其附加到上述 Pod,即 ephemeral-pod。
kubectl debug -it ephemeral-pod --image=busybox --target=ephemeral-container
這個(gè)命令會(huì)添加一個(gè)新的 busybox 容器并將其附加到臨時(shí) pod 上。--target 參數(shù)指定我們要執(zhí)行的容器。此外,該命令將自動(dòng)連接到臨時(shí)容器的控制臺(tái)。
輸出:
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.
/ #
/ #
現(xiàn)在您可以訪問實(shí)際的容器,即臨時(shí)容器,并進(jìn)行調(diào)試
Multi Container
Kubernetes允許您定義具有多個(gè)并行運(yùn)行的容器的Pod。這些容器共享相同的網(wǎng)絡(luò)命名空間,并可以通過localhost相互通信。這些多容器Pod旨在用于需要緊密耦合的進(jìn)程一起運(yùn)行、共享資源和數(shù)據(jù)的場(chǎng)景。
案例
創(chuàng)建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: {}
以上清單文件中有兩個(gè)容器,一個(gè)是主應(yīng)用程序,即 nginx,另一個(gè)是額外的容器,將幫助我們持續(xù)更新 nginx 網(wǎng)頁應(yīng)用的主頁。
創(chuàng)建 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
創(chuàng)建 Pod 和 Service
kubectl apply -f nginx-multi-container-pod.yaml
kubectl apply -f nginx-svc.yaml
現(xiàn)在,如果您嘗試通過瀏覽器訪問nginx端點(diǎn),您將看到由上面的額外容器更新的日期。