7.3. CRI-O 容器运行时问题故障排除
7.3.1. 关于 CRI-O 容器运行时引擎
CRI-O 是 Kubernetes 的原生容器引擎实现,可与操作系统紧密集成来提供高效和优化的 Kubernetes 体验。CRI-O 容器引擎作为 systemd 服务在每个 OpenShift Container Platform 集群节点上运行。
当出现容器运行时问题时,验证每个节点上的 crio
systemd 服务的状态。从具有容器运行时问题的节点收集 CRI-O journald 单元日志。
7.3.2. 验证 CRI-O 运行时引擎状态
您可以在每个集群节点上验证 CRI-O 容器运行时引擎状态。
先决条件
-
您可以使用具有
cluster-admin
角色的用户访问集群。 -
已安装 OpenShift CLI(
oc
)。
流程
通过在节点上查询 debug pod 中的
crio
systemd 服务来查看 CRI-O 状态。为节点启动 debug pod:
$ oc debug node/my-node
将
/host
设为 debug shell 中的根目录。debug pod 在 pod 中的/host
中挂载主机的 root 文件系统。将根目录改为/host
,您可以运行主机可执行路径中包含的二进制文件:# chroot /host
注意运行 Red Hat Enterprise Linux CoreOS (RHCOS) 的 OpenShift Container Platform 4.17 集群节点不可变,它依赖于 Operator 来应用集群更改。不建议使用 SSH 访问集群节点。但是,如果 OpenShift Container Platform API 不可用,或 kubelet 在目标节点上无法正常工作,
oc
操作将会受到影响。在这种情况下,可以使用ssh core@<node>.<cluster_name>.<base_domain>
来访问节点。检查
crio
systemd 服务在该节点上是否活跃:# systemctl is-active crio
输出更详细的
crio.service
状态概述:# systemctl status crio.service
7.3.3. 收集 CRI-O journald 单元日志
如果遇到 CRI-O 问题,您可以从节点获取 CRI-O journald 单元日志。
先决条件
-
您可以使用具有
cluster-admin
角色的用户访问集群。 - API 服务仍然可以正常工作。
-
已安装 OpenShift CLI(
oc
)。 - 您有 control plane 或 control plane 机器的完全限定域名。
流程
收集 CRI-O journald 单元日志。以下示例从所有 control plane 节点(在集群中)收集日志:
$ oc adm node-logs --role=master -u crio
从特定节点收集 CRI-O journald 单元日志:
$ oc adm node-logs <node_name> -u crio
如果 API 无法正常工作,使用 SSH 来查看日志。将
<node>.<cluster_name>.<base_domain>
替换为适当的值:$ ssh core@<node>.<cluster_name>.<base_domain> journalctl -b -f -u crio.service
注意运行 Red Hat Enterprise Linux CoreOS (RHCOS) 的 OpenShift Container Platform 4.17 集群节点不可变,它依赖于 Operator 来应用集群更改。不建议使用 SSH 访问集群节点。在尝试通过 SSH 收集诊断数据前,请运行
oc adm must gather
和其他oc
命令看它们是否可以提供足够的数据。但是,如果 OpenShift Container Platform API 不可用,或 kubelet 在目标节点上无法正常工作,oc
操作将会受到影响。在这种情况下,可以使用ssh core@<node>.<cluster_name>.<base_domain>
来访问节点。
7.3.4. 清理 CRI-O 存储
如果遇到以下问题,您可以手动清除 CRI-O 临时存储:
节点无法在任何 pod 上运行,并出现以下错误:
Failed to create pod sandbox: rpc error: code = Unknown desc = failed to mount container XXX: error recreating the missing symlinks: error reading name of symlink for XXX: open /var/lib/containers/storage/overlay/XXX/link: no such file or directory
您无法在工作节点上创建新容器,并出现 “can’t stat lower layer” 错误:
can't stat lower layer ... because it does not exist. Going through storage to recreate the missing symlinks.
-
在集群升级后或尝试重启节点时,您的节点处于
NotReady
状态。 -
容器运行时实施 (
crio
) 无法正常工作。 -
您无法使用
oc debug node/<node_name>
在节点上启动 debug shell,因为容器运行时实例 (crio
) 无法正常工作。
按照以下步骤完全擦除 CRI-O 存储并解决错误。
先决条件
-
您可以使用具有
cluster-admin
角色的用户访问集群。 -
已安装 OpenShift CLI(
oc
)。
流程
在节点上使用
cordon
。这是为了避免在节点处于Ready
状态时调度任何工作负载。当您的 Status 部分中存在SchedulingDisabled
时代表调度被禁用:$ oc adm cordon <node_name>
以 cluster-admin 用户身份排空节点:
$ oc adm drain <node_name> --ignore-daemonsets --delete-emptydir-data
注意pod 或 pod 模板的
terminationGracePeriodSeconds
属性控制安全终止的时间。此属性的默认值为 30 秒,但可以根据需要针对每个应用程序进行自定义。如果设置的值大于 90 秒,则 pod 可能会标记为SIGKILL
,且无法成功终止。当节点返回时,通过 SSH 或控制台连接节点。然后连接到 root 用户:
$ ssh core@node1.example.com $ sudo -i
手动停止 kubelet:
# systemctl stop kubelet
停止容器和 pod:
使用以下命令停止
HostNetwork
中没有的 pod。必须首先删除它们,因为它们依赖于HostNetwork
中的网络插件 pod。.. for pod in $(crictl pods -q); do if [[ "$(crictl inspectp $pod | jq -r .status.linux.namespaces.options.network)" != "NODE" ]]; then crictl rmp -f $pod; fi; done
停止所有其他 pod:
# crictl rmp -fa
手动停止 crio 服务:
# systemctl stop crio
运行这些命令后,您可以完全擦除临时存储:
# crio wipe -f
启动 crio 和 kubelet 服务:
# systemctl start crio # systemctl start kubelet
如果 crio 和 kubelet 服务启动,且节点处于
Ready
状态时,代表清理操作已正常工作:$ oc get nodes
输出示例
NAME STATUS ROLES AGE VERSION ci-ln-tkbxyft-f76d1-nvwhr-master-1 Ready, SchedulingDisabled master 133m v1.30.3
将节点标记为可以调度。当状态中不再有
SchedulingDisabled
时代表启用了调度:$ oc adm uncordon <node_name>
输出示例
NAME STATUS ROLES AGE VERSION ci-ln-tkbxyft-f76d1-nvwhr-master-1 Ready master 133m v1.30.3