使用 KRAWL 扫描 Kubernetes 错误

KRAWL 脚本识别 Kubernetes Pod 和容器中的错误。
83 位读者喜欢这篇文章。
Ship captain sailing the Kubernetes seas

当您使用 Kubernetes 运行容器时,您经常会发现它们堆积起来。 这是按设计进行的。 这是容器的优势之一:每当需要一个新的容器时,启动它们的成本都很低。 您可以使用像 OpenShift 或 OKD 这样的前端来管理 Pod 和容器。 这些前端可以很容易地可视化您设置的内容,并且拥有一组丰富的命令,可以进行快速交互。

但是,如果管理容器的平台不符合您的要求,您也可以仅使用 Kubernetes 工具链来获取该信息,但您需要大量命令才能全面了解复杂的环境。 因此,我编写了 KRAWL,这是一个简单的脚本,用于扫描 Kubernetes 集群上命名空间下的 Pod 和容器,并显示事件的输出(如果找到任何事件)。 它也可以用作 Kubernetes 插件以达到相同的目的。 这是一种快速简便的方法来获取大量有用的信息。

先决条件

  • 您必须安装 kubectl。
  • 您的集群的 kubeconfig 必须位于其默认位置 ($HOME/.kube/config) 或已导出 (KUBECONFIG=/path/to/kubeconfig)。

用法

$ ./krawl

KRAWL script

脚本

#!/bin/bash
# AUTHOR: Abhishek Tamrakar
# EMAIL: abhishek.tamrakar08@gmail.com
# LICENSE: Copyright (C) 2018 Abhishek Tamrakar
#
#  Licensed under the Apache License, Version 2.0 (the "License");
#  you may not use this file except in compliance with the License.
#  You may obtain a copy of the License at
#
#       https://apache.ac.cn/licenses/LICENSE-2.0
#
#   Unless required by applicable law or agreed to in writing, software
#   distributed under the License is distributed on an "AS IS" BASIS,
#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#   See the License for the specific language governing permissions and
#   limitations under the License.
##
#define the variables
KUBE_LOC=~/.kube/config
#define variables
KUBECTL=$(which kubectl)
GET=$(which egrep)
AWK=$(which awk)
red=$(tput setaf 1)
normal=$(tput sgr0)
# define functions

# wrapper for printing info messages
info()
{
  printf '\n\e[34m%s\e[m: %s\n' "INFO" "$@"
}

# cleanup when all done
cleanup()
{
  rm -f results.csv
}

# just check if the command we are about to call is available
checkcmd()
{
  #check if command exists
  local cmd=$1
  if [ -z "${!cmd}" ]
  then
    printf '\n\e[31m%s\e[m: %s\n' "ERROR"  "check if $1 is installed !!!"
    exit 1
  fi
}

get_namespaces()
{
  #get namespaces
  namespaces=( \
          $($KUBECTL get namespaces --ignore-not-found=true | \
          $AWK '/Active/ {print $1}' \
          ORS=" ") \
          )
#exit if namespaces are not found
if [ ${#namespaces[@]} -eq 0 ]
then
  printf '\n\e[31m%s\e[m: %s\n' "ERROR"  "No namespaces found!!"
  exit 1
fi
}

#get events for pods in errored state
get_pod_events()
{
  printf '\n'
  if [ ${#ERRORED[@]} -ne 0 ]
  then
      info "${#ERRORED[@]} errored pods found."
      for CULPRIT in ${ERRORED[@]}
      do
        info "POD: $CULPRIT"
        info
        $KUBECTL get events \
        --field-selector=involvedObject.name=$CULPRIT \
        -ocustom-columns=LASTSEEN:.lastTimestamp,REASON:.reason,MESSAGE:.message \
        --all-namespaces \
        --ignore-not-found=true
      done
  else
      info "0 pods with errored events found."
  fi
}

#define the logic
get_pod_errors()
{
  printf "%s %s %s\n" "NAMESPACE,POD_NAME,CONTAINER_NAME,ERRORS" > results.csv
  printf "%s %s %s\n" "---------,--------,--------------,------" >> results.csv
  for NAMESPACE in ${namespaces[@]}
  do
    while IFS=' ' read -r POD CONTAINERS
    do
      for CONTAINER in ${CONTAINERS//,/ }
      do
        COUNT=$($KUBECTL logs --since=1h --tail=20 $POD -c $CONTAINER -n $NAMESPACE 2>/dev/null| \
        $GET -c '^error|Error|ERROR|Warn|WARN')
        if [ $COUNT -gt 0 ]
        then
            STATE=("${STATE[@]}" "$NAMESPACE,$POD,$CONTAINER,$COUNT")
        else
        #catch pods in errored state
            ERRORED=($($KUBECTL get pods -n $NAMESPACE --no-headers=true | \
                awk '!/Running/ {print $1}' ORS=" ") \
                )
        fi
      done
    done< <($KUBECTL get pods -n $NAMESPACE --ignore-not-found=true -o=custom-columns=NAME:.metadata.name,CONTAINERS:.spec.containers[*].name --no-headers=true)
  done
  printf "%s\n" ${STATE[@]:-None} >> results.csv
  STATE=()
}
#define usage for seprate run
usage()
{
cat << EOF

  USAGE: "${0##*/} </path/to/kube-config>(optional)"

  This program is a free software under the terms of Apache 2.0 License.
  COPYRIGHT (C) 2018 Abhishek Tamrakar

EOF
exit 0
}

#check if basic commands are found
trap cleanup EXIT
checkcmd KUBECTL
#
#set the ground
if [ $# -lt 1 ]; then
  if [ ! -e ${KUBE_LOC} -a ! -s ${KUBE_LOC} ]
  then
    info "A readable kube config location is required!!"
    usage
  fi
elif [ $# -eq 1 ]
then
  export KUBECONFIG=$1
elif [ $# -gt 1 ]
then
  usage
fi
#play
get_namespaces
get_pod_errors

printf '\n%40s\n' 'KRAWL'
printf '%s\n' '---------------------------------------------------------------------------------'
printf '%s\n' '  Krawl is a command line utility to scan pods and prints name of errored pods   '
printf '%s\n\n' ' +and containers within. To use it as kubernetes plugin, please check their page '
printf '%s\n' '================================================================================='

cat results.csv | sed 's/,/,|/g'| column -s ',' -t
get_pod_events

最初以 README 的形式发布在 KRAWL 的 GitHub 仓库中,并已获得许可重复使用。

接下来阅读什么
iamabhi
我是一名 Lead DevOps 工程师,也是一名程序员。 我是开源爱好者、博主、作家。 你会发现我主要在帮助人们学习。

2 条评论

嗨 Abhishek,

我测试了这个脚本,它运行得不太好,这是我遇到的问题..

1. 一些 prods 计数错误,但计数事件通常返回为空,因此当使用 kubectl get events 时,你不能依靠它来获取错误信息。
2. 一般来说,使用 "--field-selector=involvedObject.name=$CULPRIT" 运行的过滤,变量设置不正确,因此它会过滤所有内容。

这是一个我的输出示例

~$ ./krawl.sh

KRAWL
=================================================================================
NAMESPACE |POD_NAME |CONTAINER_NAME |ERRORS
--------- |-------- |-------------- |------
default |ABC-server-1234567-abcd |key-server |1
default |ABC-server-postgresql-0 |key-server-postgresql |4
kube-system |coredns-1234567-abcd |coredns |20
kube-system |coredns-123456789-abcdef |coredns |20
kube-system |ingress-nginx-ingress-controller-123456789-abcdef |nginx-ingress-controller |8

INFO: 发现 0 个具有错误事件的 Pod。

嗨 Obada,

您是否检查过您的 Pod 是否有任何错误事件? 有日志错误的 Pod 不一定也有错误事件。

在我看来,它运行正常。 如果没有错误 Pod 的事件,它应该给出它所拥有的消息。 如果您的事件中确实有内容,请告诉我。

谢谢

回复 作者 Obada Abu Alhiga

Creative Commons License本作品根据 Creative Commons Attribution-Share Alike 4.0 International License 许可。
© . All rights reserved.