一文带您探索 Kubernetes 中的容器类型

云计算 云原生
一个Pod 可以在其中运行多个容器来运行应用程序,但它也可以有一个或多个 init 容器,在应用程序容器启动之前运行。Init 容器旨在在主应用程序容器启动之前运行初始化任务。

前言

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


责任编辑:武晓燕 来源: 云原生运维圈
相关推荐

2023-09-22 10:45:47

云原生云计算

2010-10-08 13:45:20

MYSQL中TIMES

2023-04-26 15:43:24

容器编排容器编排工具

2022-08-09 09:10:43

Kubernetes容器

2024-01-03 08:54:17

Kubernetes策略工具

2020-06-03 08:19:00

Kubernetes

2023-07-07 08:00:00

KafkaSpringBoo

2022-05-12 08:01:18

KubernetesDocker容器

2023-02-10 10:56:56

KubernetesLimitsRequests

2023-09-20 16:20:20

2022-08-18 15:52:13

开发者阿里云

2019-03-21 09:45:11

TypeScript编程语言Javascript

2023-09-13 22:39:23

Minikube开源

2022-03-28 11:27:17

Kubernetes运维服务发现

2022-05-13 10:59:14

容器网络通信

2023-09-27 07:13:59

Spring框架通信

2010-10-12 13:14:11

mysql索引类型

2023-07-31 07:25:27

2021-02-22 09:44:03

KubernetesDNSLinux

2022-09-05 09:25:53

KubernetesService
点赞
收藏

51CTO技术栈公众号