前言
在 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端点,您将看到由上面的额外容器更新的日期。