查找并移除影响集群性能的隐藏 pod
在某些情况下,pod 会被关闭,但会继续在后台运行。 从 OpenShift®
Console 中看不到 pod,运行 oc get pods 命令时也不会返回 pod。 但是,pod 会消耗集群资源,从而影响集群的性能。 清理隐藏的 pod 可以释放资源,提高集群性能。
故障现象
考虑到当前的工作量,群集使用的资源超出了您的预期。 例如:- 挂载硬盘的响应速度比平时慢。
- 群集使用的 CPU 超过当前请求和当前已知 pod 所定义的限制。
- 群集使用的内存超出了当前请求和当前已知 pod 所定义的限制。
原因
当关闭或删除 pod 时,Red Hat® OpenShift Container Platform 通常会完成一系列清理步骤,其中包括从容器运行时界面中删除 pod。 但是,如果 pod 被强行删除或杀死,则可能无法进行清理。 如果不进行清理,pod 将继续运行并消耗群集资源。环境
任何 Red Hat OpenShift Container Platform 集群都可能出现此问题。诊断问题
群集管理员 群集管理员可以使用以下任一方法识别隐藏的 pod:
- 手动检查每个节点是否有隐藏的 pod
- 运行以下命令可获得正在使用且Red Hat
OpenShift Container Platform已知的 pod 的完整列表:
oc get pods -owide此命令将返回每个已知 pod 运行所在节点的信息。
- 运行以下命令,以后续步骤所需的格式获取节点名称:
oc get nodes -oname - 群集中的每个节点
- 将
NODE_NAME环境变量设置为节点名称:export NODE_NAME=<node-name> - 以调试模式访问节点,并获取容器运行时接口已知的 pod 列表。
oc debug -q ${NODE_NAME} -- chroot /host /bin/bash -c "crictl pods --namespace <namespace> -o yaml"重要: 在运行命令前,请替换<namespace>。对群集上要调查的每个命名空间重复此步骤。
- 将
- 将
oc get pods -owide命令返回的 pod 列表与在每个节点上运行的crictl pods命令返回的 pod 列表进行比较。- 如果没有不同 pod 数量的节点,则无需采取其他措施。
- 如果有不同 pod 数量的节点,请继续下一步。
- 记录
crictl pods命令返回的 pod 数量与oc get pods -owide命令返回的 pod 数量不同的节点和命名空间列表。 然后,继续 解决问题。
- 运行以下命令可获得正在使用且Red Hat
OpenShift Container Platform已知的 pod 的完整列表:
- 运行脚本检查隐藏的 pod
您可以从群集节点或可以连接到群集的工作站运行脚本。 工作站必须有 OpenShift 命令行界面(
ocCLI)。- 在群集节点或可连接群集的工作站上保存以下脚本。
将脚本保存为 hidden-pods.sh
#!/usr/bin/env bash set -o pipefail -o noclobber -o nounset login() { token=$1 server=$2 namespace=$3 if [[ "${token}" != *"token"* ]] || [[ "${server}" != *"server"* ]]; then usage fi oc login "${token}" "${server}" oc project "${namespace}" } usage() { echo "Usage: hidden-pods.sh [-h|--help] --token=xxxx --server=xxxx <namespace>" echo "Example: ./hidden-pods.sh --token=xxxxx --server=xxxxx zen" exit 1 } print_warn() { echo "############# WARNING ###############" echo "Mismatch of replicas for ${1}" echo "Found ${2}, expected ${3}" echo "#####################################" } check_replicas() { namespace=$1 rs=$(oc get rs --no-headers | awk '{print $1}' | wc -l) echo "There are ${rs} replicasets" replicas=$(oc get rs --no-headers | awk '$3 = $4 {print $1}' | wc -l) echo "There are ${replicas} replicasets with correct replica count" for deploy in $(oc get rs --no-headers | awk '{print $1}'); do echo "ReplicaSet: ${deploy}" requiredReplicas=$(oc get rs ${deploy} --no-headers | awk '{print $3}') echo "Required replicas: ${requiredReplicas}" reportedReplicas=$(oc get rs ${deploy} --no-headers | awk '{print $4}') echo "Reported replicas: ${reportedReplicas}" if [ "${requiredReplicas}" -ne "${reportedReplicas}" ]; then print_warn ${deploy} ${reportedReplicas} ${requiredReplicas} fi actualReplicas=0 for node in ${nodeList}; do podDetected=$(grep "${deploy}" ${node}) numPodsDetected=$(grep -o "${deploy}" ${node} | wc -l) if [ ${numPodsDetected} -gt 0 ]; then echo "Node: ${node}" echo ${podDetected} echo "Number of pods: ${numPodsDetected}" ((actualReplicas = ${actualReplicas} + ${numPodsDetected})) fi done if [ "${actualReplicas}" -ne "${requiredReplicas}" ]; then print_warn ${deploy} ${actualReplicas} ${requiredReplicas} fi echo "Actual replicas: ${actualReplicas}" echo done } check_sts() { namespace=$1 statefulsets=$(oc get sts --no-headers | awk '{sub(/\//," ")} $2 = $3 {print $1}' | wc -l) echo "There are ${statefulsets} statefulsets with correct replica count" for sts in $(oc get sts --no-headers | awk '{print $1}'); do echo "StatefulSet: ${sts}" requiredReplicas=$(oc get sts ${sts} --no-headers | awk '{sub(/\//," ")} {print $2}') echo "Required replicas: ${requiredReplicas}" reportedReplicas=$(oc get sts ${sts} --no-headers | awk '{sub(/\//," ")} {print $3}') echo "Reported replicas: ${reportedReplicas}" if [ "${requiredReplicas}" -ne "${reportedReplicas}" ]; then print_warn ${sts} ${reportedReplicas} ${requiredReplicas} fi actualReplicas=0 for node in ${nodeList}; do podDetected=$(grep "${sts}" ${node}) numPodsDetected=$(grep -o "${sts}" ${node} | wc -l) if [ ${numPodsDetected} -gt 0 ]; then echo "Node: ${node}" echo ${podDetected} echo "Number of pods: ${numPodsDetected}" ((actualReplicas = ${actualReplicas} + ${numPodsDetected})) fi done if [ "${actualReplicas}" -ne "${requiredReplicas}" ]; then print_warn ${sts} ${actualReplicas} ${requiredReplicas} fi echo "Actual replicas: ${actualReplicas}" echo done } main() { creds=("$@") if [ "${#creds[@]}" -ne 3 ] || [ "${creds[0]}" = "-h" ] || [ "${creds[0]}" = "--help" ]; then usage fi login "${creds[0]}" "${creds[1]}" "${creds[2]}" numberNodes=$(oc get nodes -oname | wc -l) nodeList=$(oc get nodes -oname); mkdir node echo "Scanning ${numberNodes} nodes" for node in ${nodeList}; do oc debug -q ${node} -- chroot /host /bin/bash -c "crictl pods --namespace ${creds[2]} -o yaml" | grep "io.kubernetes.pod.name:" 1> ${node} 2>/dev/null done check_replicas "${creds[2]}" check_sts "${creds[2]}" # rm -rf node } main "$@" - 对于要调查的群集上的每个命名空间:
- 将
NAMESPACE环境变量设置为命名空间的名称 - 运行以下脚本:
./hidden-pods.sh ${SERVER_ARGUMENTS} ${LOGIN_ARGUMENTS} ${NAMESPACE} - 记录脚本返回警告的节点。 例如:
Node: node/<node-name> Number of pods: 1 ############# WARNING ############### Mismatch of replicas for zen-minio Found 4, expected 3 ##################################### Actual replicas: 4
- 将
- 在群集节点或可连接群集的工作站上保存以下脚本。
解决问题
本节中的步骤旨在解决发现的 pod 数量高于预期 pod 数量的警告。 例如:
Node: node/<node-name>
Number of pods: 1
############# WARNING ###############
Mismatch of replicas for zen-minio
Found 4, expected 3
#####################################
Actual replicas: 4
不过,当找到的 pod 数量少于预期数量时,脚本可能会返回警告:例如
Node: node/<node-name>
Number of pods: 1
############# WARNING ###############
Mismatch of replicas for zen-minio
Found 2, expected 3
#####################################
Actual replicas: 2
如果您看到这些警告,完成本节中的步骤并不能解决这些问题。 您必须分别调查这些问题。
要删除隐藏的 pod,请使用您在完成 诊断问题时编制的节点列表。 对于列表中的每个节点
- 将
NODE_NAME环境变量设置为节点名称:export NODE_NAME=<node-name> - 以调试模式访问节点,并运行以下命令重启容器运行时接口:
oc debug node/${NODE_NAME} -- chroot /host /bin/bash -c 'systemctl restart crio'
当容器运行时界面重新启动时,它只包含活动的已知 pod。