CKAD考试实操指南(三)---舞动容器:多容器Pod实践指南

80 阅读15分钟

一、多容器Pod实践指南

在这份CKAD考试实操指南中,我将为你详细介绍如何利用CKAD-exercises项目和知十平台进行CKAD考试的准备和复习。通过CKAD-exercises提供的练习题,你可以在知十平台的云原生环境中进行实践和模拟。在这个过程中,你将熟悉Kubernetes的各种操作和场景,并在实践中加深对知识的理解。这种结合实践和理论的学习方式将为你在考试中取得优异成绩提供强有力的支持。

首先,打开浏览器,访问知十平台。在页面右上角点击“登录”,然后使用微信扫码登录即可。

在未登录状态下,每个环境只能体验15分钟,每天有5次机会使用。登录后,每个环境可用时长为1小时,每天登录也有5次的使用机会。

当选择好要进入环境后,通常只需要等待约一分钟左右,就能进入环境中。在等待期间,你可以浏览环境说明文档,了解该环境包含哪些组件及版本。

二、官网链接及访问路径

现在开始第二个主题----多容器pod的实操

这里使用到官网的链接及访问路径如下:

kubernetes.io > Documentation > Reference > Command line tool (kubectl) > kubectl

kubernetes.io/docs/refere…

kubernetes.io > Documentation > Concepts > Workloads > Pods > Init Containers

kubernetes.io/docs/concep…

三、题目

1、Create a Pod with two containers, both with image busybox and command "echo hello; sleep 3600". Connect to the second container and run 'ls'

译:创建一个带有两个容器的Pod,两个容器都使用的busybox镜像,并且都执行命令"echo hello;sleep 3600"。然后连接到第二个容器并运行'ls'命令。

#先创建一个单容器的pod并保存到yaml文件中# run: 是kubectl的一个子命令,用于在Kubernetes集群中运行一个新的Pod或作业(Job)。# busybox: 是要创建的Pod的名称,本例中为"busybox"。# --image=busybox: 指定了Pod要使用的容器镜像,这里使用的是busybox镜像,busybox是一个轻量的Linux发行版,常用于测试和调试。# --restart=Never: 这个选项指定了Pod的重启策略。在本例中,设置为"Never"表示该Pod不会自动重启,即只运行一次。# -o yaml: 这个选项告诉kubectl输出YAML格式的资源配置,而不是直接在集群中创建资源。# --dry-run=client: 这告诉 Kubernetes 在实际创建POD之前只运行客户端验证,而不会真正地执行创建操作。# -- /bin/sh -c 'echo hello;sleep 3600': 这部分是在Pod中要运行的命令。在本例中,它运行了一个shell命令,首先输出"hello",然后休眠3600秒(1小时)。kubectl run busybox --image=busybox --restart=Never -o yaml --dry-run=client -- /bin/sh -c 'echo hello;sleep 3600' > pod.yaml#复制/粘贴容器相关的配置,因此最终的YAML应该包含以下两个容器(确保这些容器具有不同的名称,以下只是包含了容器部分的示例配置):...containers:  - args:    - /bin/sh    - -c    - echo hello;sleep 3600    image: busybox    imagePullPolicy: IfNotPresent    name: busybox    resources: {}  - args:    - /bin/sh    - -c    - echo hello;sleep 3600    image: busybox    name: busybox2...#------------------------------完整pod.yaml示例----------------------------apiVersion: v1kind: Podmetadata:  creationTimestamp: null  labels:    run: busybox  name: busyboxspec:  #  containers:  - args:  #    - /bin/sh    - -c    - echo hello;sleep 3600    image: busybox    name: busybox    resources: {}  - args:  #    - /bin/sh    - -c    - echo hello;sleep 3600    image: busybox    name: busybox2    resources: {}  dnsPolicy: ClusterFirst  restartPolicy: Neverstatus: {}# ---------------------------------------------#创建podkubectl create -f pod.yaml#或kubectl apply -f pod.yaml#连接到第二个容器中执行ls命令# kubectl exec: 用于在 Pod 中执行命令。# -it: 这是两个参数的组合,表示以交互式终端的方式运行命令,使得可以在终端中与 Pod 的容器进行交互。# busybox: 这是要在其上执行命令的 Pod 的名称,将在名为 "busybox"Pod 中执行命令。# -c busybox2: 这个选项用于指定要在POD中的哪个容器中执行命令。一个Pod可以包含多个容器,通过这个选项,可以指定在哪个容器中执行命令。在本例中,要在名为"busybox2"的容器中执行命令。# --: 这个分隔符表示命令选项的结束,后面的内容将被视为要在容器中执行的命令。# /bin/sh:这是要在容器中执行的Shell命令的路径。在本例中,指定了/bin/sh作为Shell。kubectl exec -it busybox -c busybox2 -- /bin/sh
#执行命令ls#退出podexit#或一条命令执行全部步骤kubectl exec -it busybox -c busybox2 -- ls#清理podkubectl delete po busybox

知识点:

  • kubectl create -f 和kubectl allpy -f 命令,都可以通过yaml文件创建资源,但是如果这个资源名称在集群中已经存在,那么kubectl create -f 命令可能会失败,因为有些资源的名称必须是唯一的。如果资源名称不存在,kubectl apply 命令将会创建一个新的资源,如果这个资源名称在集群中已经存在kubectl apply 命令将会更新资源的的配置以匹配 yaml 文件中的配置。通常使用apply。

  • 多容器Pod中的所有容器共享相同的网络命名空间。它们可以使用localhost地址来相互通信,避免了通过网络接口进行通信的复杂性。共享网络命名空间使容器之间的通信更加高效。

  • 多容器Pod中的容器可以共享相同的存储卷。这允许它们在同一路径下读写相同的数据,方便数据共享和同步。共享存储卷对于实现日志聚合、共享配置文件等场景非常有用。

  • 多容器Pod中,容器之间的端口不能冲突。每个容器必须在Pod中独立地监听不同的端口,以确保它们可以通过各自的端口进行通信。

  • 多容器Pod中,每个容器必须具有唯一的名称。容器名称用于在Pod内部标识不同的容器。

  • 针对题目中完整的pod.yaml文件的解析如下:

    apiVersion: v1 # 指定使用的Kubernetes API版本(v1)kind: Pod # 指定资源类型,这里是一个Pod。metadata: # 定义资源的元数据,包括名称、标签等。 creationTimestamp: null # 创建时间戳,这里为空,因为执行命令中包含--dry-run=client,只向客户端验证,资源尚未创建。 labels: # 为Pod添加标签,这里设置一个名为"run",值为"busybox"的标签。如果涉及到service,那么service筛选的标签要和此标签一致。 run: busybox name: busybox #指定Pod的名称为"busybox"。spec: # 定义了Pod的规格,包括容器和其他配置 containers: # 定义了Pod中的容器列表。 - args: # 定义容器运行时执行的命令及参数。 - /bin/sh - -c - echo hello;sleep 3600 image: busybox # 定义容器所使用的镜像,这里使用了busybox镜像。 name: busybox # 定义容器的名称为"busybox"。 resources: {} #定义容器使用的资源,这里为空,表示未定义资源限制。 - args: # 定义容器运行时执行的命令及参数。 - /bin/sh - -c - echo hello;sleep 3600 image: busybox # 定义容器所使用的镜像,这里同样使用了busybox镜像。 name: busybox2 # 定义容器的名称为"busybox2"。 resources: {} # 定义容器使用的资源,这里为空,表示未定义资源限制。 dnsPolicy: ClusterFirst # 定义Pod中容器的DNS策略。在此处设置为"ClusterFirst",表示使用Kubernetes集群中的DNS服务来解析域名。 # Default: 这个选项已经被弃用,推荐使用ClusterFirst。 # None: 在该策略下,Pod中的容器不会使用Kubernetes的DNS解析服务,而是完全依赖于宿主节点的DNS配置。 # 这意味着容器只能解析宿主节点能够解析的域名。 restartPolicy: Never # Never: 定义Pod的重启策略。表示Pod不会自动重启。即使容器发生了非正常退出也不会重启。 #这种策略通常用于一次性任务或者需要手动控制容器生命周期的场景。 # Always: 表示容器将始终自动重启,无论是因为正常退出还是非正常退出(如失败、OOM等)。 # 使用该策略,Kubernetes会持续监控容器的运行状态,并在容器终止后自动重启。 # OnFailure: 表示只有在容器以非正常状态(如失败、OOM等)终止时才会自动重启。 # 如果容器是因为退出码为0的正常退出,则不会自动重启。这种策略通常用于需要保证容器稳定性的应用场景。status: {} # 定义了Pod的状态信息,这里为空,表示当前Pod的状态还未生成。

2、Create a pod with an nginx container exposed on port 80. Add a busybox init container which create a file using "touch /work-dir/test". Make a volume of type emptyDir and mount it in both containers. For the nginx container, mount it on "/usr/share/nginx/html" and for the initcontainer, mount it on "/work-dir". When done, get the IP of the created pod and create a busybox pod and run "wget -O- IP"

译:创建一个nginx容器的pod,暴露80端口。添加一个busybox的初始化容器,该容器使用“touch /work-dir/test”创建文件。创建一个emptyDir类型的卷,并将其挂载至两个容器中。对于nginx容器,挂载到“/usr/share/nginx/html”,对于初始化容器,挂载到“/work-dir”。完成后,获取创建的pod的IP,创建一个busybox的pod并运行“wget -O- IP”命令。

#先创建一个单容器的pod并保存到yaml文件中# run: 是kubectl的一个子命令,用于在Kubernetes集群中创建一个新的Pod或作业(Job)。# box: 是要创建的Pod的名称,本例中为"box"。# --image=nginx: 指定了Pod要使用的容器镜像,这里使用的是nginx镜像。# --restart=Never: 这个选项指定了Pod的重启策略。在本例中,设置为"Never"表示该Pod不会自动重启,即只运行一次。# --port=80: 这个选项指定了容器暴露的端口号。在容器内部暴露 80 端口,这使得可以从集群内部访问 Pod80 端口服务。# --dry-run=client: 这告诉 Kubernetes 在实际创建POD之前只运行客户端验证,而不会真正地执行创建操作。# -o yaml: 这个选项告诉kubectl输出YAML格式的资源配置。# > pod-init.yaml: 这部分是将输出的配置信息重定向到名为"pod-init.yaml"的文件中,这样就会将生成的Pod配置保存到文件中,而不是在集群中实际创建该Pod。kubectl run box --image=nginx --restart=Never --port=80 --dry-run=client -o yaml > pod-init.yaml#复制/粘贴容器相关配置,最终的YAML应该包含卷和初始化容器:...containers:- image: nginx...  volumeMounts: # 挂载点配置  - name: vol    mountPath: /usr/share/nginx/htmlvolumes: # 卷配置- name: vol  emptyDir: {}...#初始化容器配置...initContainers:- args:  - /bin/sh  - -c  - "touch /work-dir/test"  image: busybox  name: box  volumeMounts:  - name: vol    mountPath: /work-dir#-------------------------------一份完整的pod.yaml的示例-------------------------------apiVersion: v1kind: Podmetadata:  labels:    run: box  name: boxspec:  initContainers:   - args:     - /bin/sh     - -c     - "touch /work-dir/test"    image: busybox     name: box     volumeMounts:     - name: vol       mountPath: /work-dir   containers:  - image: nginx    name: nginx    ports:    - containerPort: 80    volumeMounts:     - name: vol       mountPath: /usr/share/nginx/html   volumes:   - name: vol     emptyDir: {} ---------------------------------------------------------------------------------------------# 创建podkubectl apply -f pod-init.yaml# 获取pod的ip地址# get po: 是kubectl的一个子命令,用于获取(获取)Pod资源。# -o wide: 这个选项用于指定输出的格式,这里设置为"wide",表示输出详细信息,包括IP地址、节点名称等。#   每个Pod的信息会包括以下列:#    NAME: Pod的名称。#    READY: 显示容器运行状态,例如 "1/1" 表示第一个容器运行正常。#    STATUS: 显示Pod的运行状态,例如 "Running" 表示Pod正在运行。#    RESTARTS: 显示容器重启的次数。#    AGE: 显示Pod创建的时间距离当前时间的长短。#    IP: 显示PodIP地址。#    NODE: 显示Pod所在的节点名称。
kubectl get po -o wide# 执行wget命令# run: 是 kubectl 的一个子命令,用于在 Kubernetes 集群中创建一个新的 Pod 或作业 (Job)。# box-test: 是要创建的 Pod 的名称,本例中为 "box-test"。# --image=busybox: 指定了 Pod 要使用的容器镜像,这里使用的是 busybox 镜像。# --restart=Never: 这个选项指定了 Pod 的重启策略。在本例中,设置为 "Never" 表示该 Pod 不会自动重启,即只运行一次。# -it: 这两个选项组合用于指定以交互模式运行命令,并且将命令的输入和输出连接到终端 (TTY)。这样,您可以与命令交互并查看输出。# --rm: 这个选项指定在 Pod 终止后自动删除该 Pod。这使得创建的 Pod 是临时性的,不会在集群中保留。# /bin/sh -c "wget -O- $(kubectl get pod box -o jsonpath='{.status.podIP}')": 这是要在容器中执行的命令。在本例中,它使用 busybox 镜像的 /bin/sh Shell 执行了一个命令,该命令使用 wget 下载了由 kubectl get pod box -o jsonpath='{.status.podIP}' 命令获取的 Pod IP 地址。
kubectl run box-test --image=busybox --restart=Never -it --rm -- /bin/sh -c "wget -O- $(kubectl get pod box -o jsonpath='{.status.podIP}')"
#或kubectl run box-test --image=busybox --restart=Never -it --rm -- /bin/sh -c "wget -O- x.x.x.x"# 清理容器kubectl delete po box

知识点:

  • 在 Pod 启动过程中,initContainers 是在主要应用容器运行之前执行的。主要容器只有在所有 initContainers 成功执行后才会启动。

  • initContainers 中的容器会按照在 Pod 配置中定义的顺序逐个执行。只有当前容器成功完成(退出状态码为0),下一个容器才会执行,直到所有的初始化容器执行完成。

  • 所有容器(包括 initContainers 和主要容器)在同一个 Pod 中共享相同的网络命名空间,它们可以通过 localhost 来相互通信。

  • initContainers 和主要容器之间共享相同的存储卷。这允许它们在同一路径下读写相同的数据,方便数据共享和同步。共享存储卷对于实现日志聚合、共享配置文件等场景非常有用。

  • 当 initContainers 发生错误时,Pod 的整个启动过程将被中断。在设计 initContainers 时,确保它们能够合理地处理错误情况。

  • Kubernetes支持多种类型的Volume,包括EmptyDir、HostPath、PersistentVolumeClaim(PVC)、ConfigMap、Secret、DownwardAPI等。每种类型的Volume都有不同的特性和用途。

  • EmptyDir:

EmptyDir是一种临时性的Volume类型,适用于在同一个Pod的不同容器之间共享临时数据。它在Pod创建时被创建,并且在Pod被删除时一同被删除。适用于临时缓存、共享数据等场景。

  • HostPath:

HostPath是将主机(宿主节点)上的文件或目录挂载到Pod中的Volume类型。它允许Pod中的容器直接访问主机上的文件系统。HostPath适用于需要直接访问宿主节点上文件系统的场景,但应该小心使用,因为它会带来安全和可移植性方面的隐患。

  • PersistentVolumeClaim(PVC):

PersistentVolumeClaim是用于持久化存储的Volume类型。它允许将持久化存储资源(如网络存储、云存储等)动态地绑定到Pod中。PVC可以使数据在Pod重启或重新调度时得到保留。适用于数据库、应用配置、日志等需要持久化的数据场景。

  • ConfigMap:

ConfigMap用于将配置数据以键值对的形式存储,并将其挂载到Pod中的Volume中。容器可以读取ConfigMap中的配置数据,实现配置和代码的解耦。适用于配置文件、环境变量等场景。

  • Secret:

Secret用于安全地存储敏感数据,如密码、API密钥等,并将其挂载到Pod中的Volume中。Secret可以加密保存数据,并仅供授权的容器使用。适用于存储敏感信息的场景。

  • DownwardAPI:

DownwardAPI允许将Pod和容器的一些元数据信息注入到Volume中,然后容器可以读取这些信息。适用于获取Pod名称、命名空间、标签等元数据的场景。

  • Volume是在Pod级别定义的,这意味着所有在同一个Pod中的容器都可以访问相同的Volume。

  • 针对题目中完整的pod.yaml文件的解析如下:

    apiVersion: v1 # 指定使用的Kubernetes API版本(v1)。kind: Pod # 指定资源类型,这里是一个Pod。metadata: # 定义资源的元数据,包括名称、标签等。 labels: # 标签用于标识Pod,此处使用run: box作为标签。 run: box name: box # 定义Pod的名称为"box"。spec: # 定义了Pod的规格,包括容器和其他配置 initContainers: # 这是一个包含一个initContainer的列表。initContainer会在主要容器启动之前执行。 - args: # 定义initContainer执行的命令。 - /bin/sh - -c - "touch /work-dir/test" image: busybox # 定义initContainer使用的镜像为"busybox"。 name: box # 定义initContainer的名称为"box"。 volumeMounts: # 将Volume "vol" 挂载到initContainer的 "/work-dir" 目录上。 - name: vol # 需要和volume中的name一致。 mountPath: /work-dir containers: # 这是一个包含一个主要容器的列表。 - image: nginx # 定义主要容器使用的镜像为"nginx"。 name: nginx # 定义主要容器的名称为"nginx"。 ports: # 定义主要容器监听的端口号为80。 - containerPort: 80 volumeMounts: # 将Volume "vol" 挂载到主要容器的 "/usr/share/nginx/html" 目录上。 - name: vol # 需要和volume中的name一致。 mountPath: /usr/share/nginx/html volumes: # 这是一个包含一个Volume的列表。 - name: vol # 定义Volume的名称为"vol"。 emptyDir: {} # 这是一个空的Volume类型,表示一个临时的Volume,在Pod被删除时,其中的数据也会被删除。

--------------------------------------------------------------------------------------------

系列文章

CKAD考试实操指南(一)---登顶CKAD:征服考试的完美蓝图

CKAD考试实操指南(二)---深入核心:探秘Kubernetes核心实操秘技

CKAD考试实操指南(三)---舞动容器:多容器Pod实践指南