使用 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
我是一名首席 DevOps 工程师,也是一名程序员。我是一名开源爱好者、博主和作家。你会发现我主要在帮助人们学习。

2 条评论

Hi Abhishek,

我测试了这个脚本,它似乎无法正常工作,以下是我遇到的问题:

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

这是我的输出示例

~$ ./krawl.sh

KRAWL
=================================================================================
命名空间 |Pod 名称 |容器名称 |错误
--------- |-------- |-------------- |------
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

信息:已找到 0 个包含错误事件的 Pod。

Hi Obada,

你检查过你的 Pod 是否有任何错误事件吗?并非日志中存在错误的 Pod 也一定会有错误事件。

在我看来,它工作正常。对于没有错误事件的 Pod,它应该给出它所显示的消息。请告诉我你的事件中是否确实存在某些内容。

谢谢

回复 作者:Obada Abu Alhiga

Creative Commons License本作品采用知识共享署名-相同方式共享 4.0 国际许可协议进行许可。
© . All rights reserved.