多容器与 Init 容器考点全解析)
CKAD 实战Multi-container Pods10%多容器与 Init 容器考点全解析【免费下载链接】CKAD-exercisesA set of exercises to prepare for Certified Kubernetes Application Developer exam by Cloud Native Computing Foundation项目地址: https://gitcode.com/gh_mirrors/ck/CKAD-exercises本文基于 CKAD-exercises 仓库中 b.multi_container_pods.md 的官方练习题展开聚焦 CNCF 认证 Kubernetes 应用开发者CKAD考试中多容器 PodMulti-container Pods占 10%这一核心考点。通过两道由浅入深的实战题——双容器 sidecar Pod 与 nginx init 容器 emptyDir 共享卷组合你将掌握多容器 Pod 的 YAML 编写、kubectl exec -c指定容器交互、init 容器串行初始化语义以及如何用共享卷实现容器间数据交换并学会用一条命令完成获取 Pod IP → wget 验证的完整链路。为什么多容器 Pod 值得单独占 10%Kubernetes 中 Pod 是最小的调度与部署单元而多容器 Pod 正是单 Pod 内多个容器如何协作的答案。CKAD 考试把这一主题单独划分为 10% 的考区因为它考察的不是简单地把多个容器塞进一个 Pod而是对以下机制的综合理解共享生命周期同一 Pod 内的容器被调度到同一节点、同生共死主容器与辅助容器sidecar天然形成一个整体共享网络命名空间容器间可通过localhost直接通信练习中直接使用 Pod IP 访问 nginx 即依赖此特性共享存储卷通过emptyDir、PVC 等卷类型容器之间可以读写同一份数据init 容器initContainers在主容器启动前按顺序执行初始化任务失败则整个 Pod 重启。仓库中该主题的练习文件 b.multi_container_pods.md 提供了两道经典题目下面逐一完整还原并深入拆解。实战一双容器 sidecar Pod 与kubectl exec -c题目要求创建一个包含两个容器的 Pod两个容器都使用busybox镜像命令均为echo hello; sleep 3600。随后连接到第二个容器执行ls。第一步用kubectl run生成单容器骨架直接手写多容器 YAML 容易出错官方推荐的做法是先让 kubectl 生成单容器模板再复制扩展kubectl run busybox --imagebusybox --restartNever -o yaml --dry-runclient -- /bin/sh -c echo hello;sleep 3600 pod.yaml vi pod.yaml逐项拆解这条命令参数含义kubectl run busybox声明一个名为busybox的 Pod或控制器取决于后续参数--imagebusybox指定容器镜像--restartNever关键参数让 kubectl 直接创建裸 Podkind: Pod而不是 Deployment-o yaml --dry-runclient只在本机客户端侧渲染 YAML、不真正提交到 API Server用于生成模板-- /bin/sh -c echo hello;sleep 3600--之后的参数会写入容器的args字段覆盖镜像默认的启动命令生成出的骨架 YAML 中spec.containers只有一个名为busybox的容器且带有args、image、imagePullPolicy: IfNotPresent、resources: {}等字段——这正是后续复制粘贴的模板单元。第二步复制容器定义形成两个容器编辑pod.yaml把容器定义整段复制一份务必修改name同一 Pod 内容器名必须唯一否则创建会被 API Server 拒绝。最终spec应包含如下两个容器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注意第一份定义保留了imagePullPolicy: IfNotPresent和resources: {}骨架自动生成第二份也可以显式补上——两者效果等价IfNotPresent表示本地已缓存该镜像则不再拉取在考试环境能明显加快 Pod 启动。第三步创建 Pod 并进入第二个容器kubectl create -f pod.yaml连接到指定容器的核心语法是kubectl exec -it pod -c container -- cmdkubectl exec -it busybox -c busybox2 -- /bin/sh ls exit这里-c busybox2明确指定进入第二个容器。由于该 Pod 内两个容器共享网络命名空间进入任意一个容器看到的网络环境IP、端口、网络接口是完全一致的而ls列出的是该容器自身文件系统的内容。第四步一行命令的等价写法如果只是想在第二个容器里跑一条命令而不进入交互式 shell可以去掉-it -- /bin/sh的交互层直接执行kubectl exec -it busybox -c busybox2 -- ls两种写法效果等价--之后的内容是被执行命令及其参数/bin/sh只是提供了一个 shell 解释器。考试中按题目要求连接并运行ls两种方式都符合题意。清理kubectl delete po busybox裸 Pod 被删除后不会由任何控制器重建因此删除即彻底清理。实战二init 容器 emptyDir 共享卷nginx 网页初始化题目要求创建一个 Pod主容器为nginx暴露 80 端口附加一个busyboxinit 容器执行echo Test /work-dir/index.html写入页面内容使用emptyDir类型卷vol在 init 容器中挂载到/work-dir在 nginx 容器中挂载到/usr/share/nginx/htmlnginx 的站点根目录。完成后获取 Pod IP用临时 busybox Pod 执行wget -O- IP验证页面内容。这道题考察两个高频考点init 容器的执行时机与emptyDir 的共享语义。第一步生成 nginx 骨架kubectl run box --imagenginx --restartNever --port80 --dry-runclient -o yaml pod-init.yaml与实战一相比多了--port80它会在生成的 YAML 中写入ports: - containerPort: 80信息性声明告诉观察者容器监听的端口并不会真正开放或映射端口。第二步加入卷与挂载编辑pod-init.yaml先给主容器增加volumeMounts再在spec顶层声明volumescontainers: - image: nginx ... volumeMounts: - name: vol mountPath: /usr/share/nginx/html volumes: - name: vol emptyDir: {}关键字段说明字段作用volumeMounts[].name必须与spec.volumes[].name一致两者通过名字关联volumeMounts[].mountPath卷在容器内的挂载路径volumes[].emptyDir: {}声明一个 emptyDir 卷初始为空、随 Pod 创建而创建、随 Pod 删除而销毁生命周期与 Pod 绑定与节点磁盘无关默认介质为节点工作目录可配合medium: Memory改用内存第三步加入 init 容器在spec中containers的同级追加initContainers... initContainers: - args: - /bin/sh - -c - echo Test /work-dir/index.html image: busybox name: box volumeMounts: - name: vol mountPath: /work-dirinit 容器与普通容器写在 YAML 中的区别只有两点字段名为initContainers且必须位于containers之前API 顺序要求。其运行语义则完全不同串行执行Pod 中所有 init 容器按定义顺序逐个执行前一个成功退出exit 0后才会启动下一个先于主容器所有 init 容器全部成功完成后主容器才被创建启动失败即重启整个 Pod任意 init 容器失败kubelet 会按restartPolicy重启该 init 容器若为Always/OnFailure主容器始终不会启动。在本例中init 容器先把Test写入共享卷的/work-dir/index.html当 nginx 主容器启动并把同一卷挂到/usr/share/nginx/html时站点根目录下已经有index.html——nginx 进程一启动就能对外提供Test页面这正是 init 容器前置准备模式的经典应用。完整 YAML可直接复制apiVersion: v1 kind: Pod metadata: labels: run: box name: box spec: initContainers: - args: - /bin/sh - -c - echo Test /work-dir/index.html 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: {}第四步获取 Pod IP 并验证kubectl apply -f pod-init.yaml # 获取 Pod IP-o wide 会额外显示 NODE 与 IP 列 kubectl get po -o wide随后用一条命令完成创建临时 busybox Pod → wget 该 IP → 自动清理kubectl run box-test --imagebusybox --restartNever -it --rm -- /bin/sh -c wget -O- $(kubectl get pod box -o jsonpath{.status.podIP})这条命令是仓库中典型的复合写法拆开看有三层$(kubectl get pod box -o jsonpath{.status.podIP})命令替换动态取出boxPod 的status.podIP无需手工抄写 IPwget -O- IP把页面内容输出到标准输出-O-表示输出到 stdout 而非落盘应看到 nginx 返回的Test-it --rm --restartNever--rm使 Pod 在命令退出后被自动删除-it保证交互式输出可见全程无需手动清理测试 Pod。执行成功后输出为Test即证明init 容器写入的内容通过 emptyDir 卷被 nginx 容器成功读取并对外服务。清理kubectl delete po box仓库内的交叉印证与延伸这一主题并非孤立存在CKAD-exercises 仓库中多个练习文件都与多容器/共享卷机制强相关可互相印证g.state.mdState Persistence其中第一题与本主题几乎同构——创建两个 busybox 容器、都挂载同一个emptyDir到/etc/foo然后在第二个容器把/etc/passwd第一列写入共享卷再到第一个容器读取。它进一步展示了kubectl exec -it busybox -c busybox2 -- /bin/sh的完整双容器协作流程以及command: [/bin/sh, -c, sleep 3600]在忘记在kubectl run里附加参数时的 YAML 补救写法对应 g.state.md 中in case you forget…的说明。该文件还明确指出此题更适合放在 Multi-container-pods 部分可见两主题在考试中本就彼此交织。c.pod_design.mdPod design金丝雀canary发布示例中的 Deployment 使用了与本练习完全相同的组合——initContainers写version-1/version-2到共享卷volumeMounts挂到 nginx 的/usr/share/nginx/htmlemptyDir承载数据。这证明 init 容器 emptyDir 模式不是考试专用技巧而是生产环境内容初始化的真实范式。d.configuration.mdConfiguration其中 Secret 卷挂载示例展示了同一套volumes[].name↔volumeMounts[].name关联机制的另一种卷类型secret可帮助理解卷声明的通用结构pod.spec.volumes负责定义卷的来源容器内的volumeMounts负责决定挂到哪、怎么挂。此外若不确定字段应放在 YAML 的哪个层级可使用仓库练习中反复出现的导航技巧见 c.pod_design.mdkubectl explain po.spec kubectl explain po.spec.initContainers kubectl explain po.spec.volumes.emptyDirkubectl explain直接输出 API 字段的结构化文档是考试中核对 YAML 层级最可靠的工具。易错点与考试要点速查容器名必须唯一复制容器定义时忘记改名会导致 API Server 拒绝创建Duplicate name类错误。--restartNever不能省省略它kubectl run会创建 Deployment 而非 Pod-o yaml得到的将是完全不同的资源类型。init 容器写initContainers字段写在containers下不会被识别为 init 容器而是成为普通 sidecar。卷名一一对应volumeMounts[].name与spec.volumes[].name必须精确匹配拼写错误时 Pod 会进入CreateContainerConfigError状态。exec指定容器用-c多容器 Pod 中不带-c时kubectl 默认进入第一个容器考试题明确要求第二个容器时必须使用-c busybox2。emptyDir 是临时的Pod 被删除或被调度迁移后数据即消失跨节点持久化需改用 PVC见 g.state.md 中关于 hostPath 多节点不可见的讨论。验证链路用命令替换$(kubectl get pod name -o jsonpath{.status.podIP})可动态取 IP避免手抄出错是考试中的高效写法。完成这两道题后多容器 Pod 的核心能力——共享生命周期、共享卷、init 前置初始化、指定容器交互——已经全部覆盖。它们既是 CKAD 10% 考区的全部内容也是理解 sidecar、数据初始化、健康检查准备等生产模式的基础。建议按仓库 README.md 的指引先阅读官方文档再动手练习并关注各练习文件开头的面包屑导航对应 kubernetes.io 文档位置以建立系统认知。【免费下载链接】CKAD-exercisesA set of exercises to prepare for Certified Kubernetes Application Developer exam by Cloud Native Computing Foundation项目地址: https://gitcode.com/gh_mirrors/ck/CKAD-exercises创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考