侧边栏壁纸
博主头像
汪洋

即使慢,驰而不息,纵会落后,纵会失败,但一定可以达到他所向的目标。 - 鲁迅

  • 累计撰写 190 篇文章
  • 累计创建 74 个标签
  • 累计收到 108 条评论

K8S - 临时容器 - 官方调试机制 - `Kubernetes v1.25 [stable]`

汪洋
2022-11-07 / 2 评论 / 0 点赞 / 605 阅读 / 2,566 字

内容展示

临时容器

特性状态: Kubernetes v1.25 [stable]

临时容器:一种特殊的容器,该容器在现有 Pod 中临时运行,以便完成用户发起的操作,例如故障排查。 你会使用临时容器来检查服务,而不是用它来构建应用程序

概念

Pod 是 Kubernetes 应用程序的基本构建块。 由于 Pod 是一次性且可替换的,因此一旦 Pod 创建,就无法将容器加入到 Pod 中。 取而代之的是,通常使用 Deployment 以受控的方式来删除并替换 Pod

有时有必要检查现有 Pod 的状态。例如,对于难以复现的故障进行排查。 在这些场景中,可以在现有 Pod 中运行临时容器来检查其状态并运行任意命令

什么是临时容器?

临时容器与其他容器的不同之处在于,它们缺少对资源或执行的保证,并且永远不会自动重启, 因此不适用于构建应用程序。 临时容器使用与常规容器相同的 ContainerSpec 节来描述,但许多字段是不兼容和不允许的。

  • 临时容器没有端口配置,因此像 portslivenessProbereadinessProbe 这样的字段是不允许的。

  • Pod 资源分配是不可变的,因此 resources 配置是不允许的。

临时容器是使用 API 中的一种特殊的 ephemeralcontainers 处理器进行创建的, 而不是直接添加到 pod.spec 段,因此无法使用 kubectl edit 来添加一个临时容器。与常规容器一样,将临时容器添加到 Pod 后,将不能更改或删除临时容器

用途

当由于容器崩溃或容器镜像不包含调试工具而导致 kubectl exec 无用时, 临时容器对于交互式故障排查很有用。尤其是,Distroless 镜像 允许用户部署最小的容器镜像,从而减少攻击面并减少故障和漏洞的暴露。 由于 distroless 镜像不包含 Shell 或任何的调试工具,因此很难单独使用 kubectl exec 命令进行故障排查。使用临时容器时,启用 进程名字空间共享 很有帮助,可以查看其他容器中的进程

https://github.com/GoogleContainerTools/distroless

使用临时调试容器来进行调试

例子

你可以使用 kubectl debug 命令来给正在运行中的 Pod 增加一个临时容器

kubectl run demo --image=wangyanglinux/myapp:v1 --restart=Never

# 如果你指定 -i 或者 --interactive 参数,kubectl 将自动挂接到临时容器的控制台。--target 参数指定另一个容器的进程命名空间。 这个指定进程命名空间的操作是必需的
kubectl debug -it demo --image=busybox:1.28 --target=demo
1.png
通过 Pod 副本调试
在添加新的容器时创建 Pod 副本

当应用程序正在运行但其表现不符合预期时,你会希望在 Pod 中添加额外的调试工具, 这时添加新容器是很有用的

kubectl run myapp --image=busybox:1.28 --restart=Never -- sleep 1d

# 通过运行以下命令,建立 myapp 的一个名为 myapp-debug 的副本, 新增了一个用于调试的 Ubuntu 容器
kubectl debug myapp -it --image=ubuntu --share-processes --copy-to=myapp-debug
	# 如果你没有使用 --container 指定新的容器名,kubectl debug 会自动生成的。
	# 默认情况下,-i 标志使 kubectl debug 附加到新容器上。 你可以通过指定 --attach=false 来防止这种情况
	# --share-processes 允许在此 Pod 中的其他容器中查看该容器的进程。 参阅在 Pod 中的容器之间共享进程命名空间 获取更多信息。
2.png
在改变 Pod 命令时创建 Pod 副本

有时更改容器的命令很有用,例如添加调试标志或因为应用崩溃

kubectl run --image=busybox:1.28 myapp -- false

# 你可以使用 kubectl debug 命令创建该 Pod 的一个副本, 在该副本中命令改变为交互式 shell:
kubectl debug myapp -it --copy-to=myapp-debug --container=myapp -- sh
	# 要更改指定容器的命令,你必须用 --container 命令指定容器的名字, 否则 kubectl debug 将建立一个新的容器运行你指定的命令
	# 默认情况下,标志 -i 使 kubectl debug 附加到容器。 你可通过指定 --attach=false 来防止这种情况
3.png
在更改容器镜像时拷贝 Pod

在某些情况下,你可能想要改动一个行为异常的 Pod,即从其正常的生产容器镜像更改为包含调试构建程序或其他实用程序的镜像

kubectl run myapp --image=busybox:1.28 --restart=Never -- sleep 1d

# 现在可以使用 kubectl debug 创建一个拷贝并将其容器镜像更改为 ubuntu
kubectl debug myapp --copy-to=myapp-debug --set-image=*=ubuntu
	# --set-image 与 container_name=image 使用相同的 kubectl set image 语法。 *=ubuntu 表示把所有容器的镜像改为 ubuntu
4.png
在同一个节点上创建 pod 进行调试

如果这些方法都不起作用,你可以找到运行 Pod 的节点,然后创建一个 Pod 运行在该节点上。 你可以通过 kubectl debug 在节点上创建一个交互式 Shell

kubectl debug node/mynode -it --image=ubuntu
    # kubectl debug 基于节点的名字自动生成新的 Pod 的名字
    # 节点的根文件系统会被挂载在 /host。
    # 新的调试容器运行在主机 IPC 名字空间、主机网络名字空间以及主机 PID 名字空间内, Pod 没有特权,因此读取某些进程信息可能会失败,并且 chroot /host 也会失败
    # 如果你需要一个特权 Pod,需要手动创建
5.png
0

评论区