本篇主要分享一些处理故障和问题绝招,好比听诊三板斧:
1)查看日志html
2)查看资源详情和事件node
3)查看资源配置(YAML)linux
若是仍是不太好分析,那就祭出神器——kubectl-debug。git
最后,仅需根据问题对症下药便可。github
进一步诊断分析——听诊三板斧sql
容器调测 docker
对症下药 数据库
在初诊阶段,咱们每每只能得到一些表面的信息,好比节点挂了,Pod崩溃了,网络不通等等,这时,咱们须要根据咱们初诊的方向和范围使用一些工具以及结合日志进行具体的诊断。json
这里笔者推崇听诊三板斧:api
查看日志
查看资源详情和事件
查看资源配置
大部分状况下,想要得到具体的病因,查看日志是最为直接的方式,所以,咱们须要学会如何查看日志。
主流的Linux系统基本上都采用Systemd来集中管理和配置系统,若是使用的是Systemd机制,咱们可使用journalctl命令来查看服务日志:
好比docker:
journalctl -u docker
查看并追踪kubelet的日志:
journalctl -u kubelet -f
咱们的应用运行在Pod之中,以及k8s的一些组件,例如kube-apiserver、coredns、etcd、kube-controller-manager、kube-proxy、kube-scheduler等,也都运行在Pod之中(静态Pod),那么如何查看这些组件以及应用的日志呢?这里就要用到前面提到的“kubectl logs”命令。
语法以下所示:
kubectl logs [-f] [-p] (POD | TYPE/NAME) [-c CONTAINER] [options]
主要的参数说明以下表所示:
参数 |
说明 |
-f, --follow |
是否持续追踪日志,默认为false,指定了以后会持续输出日志。 |
-p, --previous |
输出Pod中曾经运行过,但目前已终止的容器的日志。 |
-c, --container |
容器名称。 |
--since |
仅返回相对时间范围(如5s、2m或3h)内的日志。默认返回全部日志。 |
--since-time |
仅返回指定时间以后的日志,默认返回全部。只能同时使用since和since-time中的一种。 |
--tail |
要显示的最新的日志条数,默认为-1,显示全部。 |
--timestamps |
输出的日志中包含时间戳。 |
-l, --selector |
使用Label选择器过滤 |
了解了主要的参数和说明,咱们查看几个示例:
查看Pod“mssql-58b6bff865-xdxx8”的日志
kubectl logs mssql-58b6bff865-xdxx8
查看24小时内的日志
kubectl logs mssql-58b6bff865-xdxx8 --since 24h
根据Pod标签查看日志
kubectl logs -lapp=mssql
查看指定命名空间下的Pod日志(注意系统组件的命名空间为“kube-system”)
kubectl logs kube-apiserver-k8s-master -f -n kube-system
除了查看日志以外,有时候咱们须要查看资源实例详情以帮助咱们解决问题。这就须要用到咱们上面提到过的“kubectl describe”命令。
“kubectl describe”命令用于查看一个或多个资源的详细状况,包括相关资源和事件。语法以下所示:
kubectl describe (-f FILENAME | TYPE [NAME_PREFIX | -l label] | TYPE/NAME)
主要的参数说明以下表所示:
参数 |
说明 |
-A,--all-namespaces |
查看全部命名空间下的资源 |
-f, --filename |
根据资源描述文件、目录、Url来查看 |
-R, --recursive |
以递归方式查看-f指定的全部资源 |
-l, --selector |
使用Label选择器过滤 |
--show-events |
显示事件 |
了解了主要的参数和说明,咱们经过示例来进行解说:
查看指定节点:
kubectl describe nodes k8s-node1
查看全部节点:
kubectl describe nodes
查看指定节点以及事件:
kubectl describe nodes k8s-node1--show-events
注意,若是Node状态为NotReady,经过查看节点事件能够有助于咱们排查问题。
查看指定Pod:
kubectl describe pods gitlab-84754bd77f-7tqcb
查看指定文件描述的全部资源
kubectl describe -f teamcity.yaml
不少应用的出错每每都是咱们的配置致使的,那么如何查看已部署资源的配置呢?这就须要用到强大的“kubectl get”命令了。
“kubectl get”命令咱们常用,在这以前咱们常常用其来查询资源,那么如何使用它来查看资源配置呢?咱们先来看其语法:
kubectl get [(-o|--output=)json|yaml|wide|custom-columns=...|custom-columns-file=...|go-template=...|go-template-file=...|jsonpath=...|jsonpath-file=...] (TYPE[.VERSION][.GROUP] [NAME | -l label] | TYPE[.VERSION][.GROUP]/NAME ...) [flags] [options]
如上述语法所示,“kubectl get”拥有强大的格式化输出能力,支持“json”、“yaml”等,在上面的kubectl一节中咱们已经讲解过了,这里咱们就主要用到“-o”来查看资源配置,具体如如下实例所示:
查看指定Pod配置
kubectl get pods mssql-58b6bff865-xdxx8 -o yaml
yaml奴家看不惯,想看JSON版的:
想看全部的:
kubectl get pods -o json
查看服务配置
kubectl get svc mssql -o yaml
查看部署(deployment)配置
kubectl get deployments mssql -o yaml
注意:“-o”用得好,不再用担忧yaml不会写了。
有时候光看日志还没发给出具体诊断,可能得动刀子或者进行进一步检查调测才能论证咱们的猜测。笔者推荐使用如下方案:
咱们可使用“kubectl exec”进入运行中的容器进行调测。这个命令和“docker exec”很相似,具体语法以下所示:
kubectl exec (POD | TYPE/NAME) [-c CONTAINER] [flags] -- COMMAND [args...] [options]
主要的参数说明以下表所示:
参数 |
说明 |
-c, --container |
指定容器名称 |
-i, --stdin |
启用标准输入 |
--tty , -t |
分配伪TTY(终端设备) |
接下来咱们结合示例说明:
进入容器查看配置
kubectl exec mssql-58b6bff865-xdxx8 -- cat /etc/resolv.conf
进入容器分配终端并将标准输入流转到bash
kubectl exec mssql-58b6bff865-xdxx8 -it bash
如上图所示,咱们进入MSSQL数据库的容器以后,使用sqlcmd工具执行了一个查询。这块操做若有疑问,请参阅数据库容器化一节。
kubectl-debug 是一个简单的开源的kubectl 插件, 能够帮助咱们便捷地进行 Kubernetes 上的 Pod 排障诊断,背后作的事情很简单: 在运行中的 Pod 上额外起一个新容器, 并将新容器加入到目标容器的 pid, network, user以及 ipc namespace中, 这时咱们就能够在新容器中直接用 netstat, tcpdump 这些熟悉的工具来诊断和解决问题了, 而旧容器能够保持最小化, 不须要预装任何额外的排障工具.
GitHub地址:https://github.com/aylei/kubectl-debug
安装脚本以下(CentOS 7):
export PLUGIN_VERSION=0.1.1 # linux x86_64,下载文件 curl -Lo kubectl-debug.tar.gz https://github.com/aylei/kubectl-debug/releases/download/v${PLUGIN_VERSION}/kubectl-debug_${PLUGIN_VERSION}_linux_amd64.tar.gz #解压 tar -zxvf kubectl-debug.tar.gz kubectl-debug #移动到用户的可执行文件目录 sudo mv kubectl-debug /usr/local/bin/
为了调试更快更方便,咱们还需安装debug-agent DaemonSet,安装命令以下:
kubectl apply -f https://raw.githubusercontent.com/aylei/kubectl-debug/master/scripts/agent_daemonset.yml
使用起来很是简单,如下是经常使用的使用示例:
# 输出帮助命令 kubectl debug -h # 启动Debug kubectl debug (POD | NAME) # 假如 Pod 处于 CrashLookBackoff 状态没法链接, 能够复制一个彻底相同的 Pod 来进行诊断 kubectl debug (POD | NAME) --fork # 假如 Node 没有公网 IP 或没法直接访问(防火墙等缘由), 请使用 port-forward 模式 kubectl debug (POD | NAME) --port-forward --daemonset-ns=kube-system --daemonset-name=debug-agent
接下来,咱们使用该工具调试一个已有Pod,以下所示:
kubectl debug teamcity-5997d4fc7f-ldt8w
执行该命令后,会自动拉取相关镜像并建立容器开启tty并进入容器内部,而且自带一些经常使用工具。这里咱们使用nslookup命令来测试Pod内的外网域名(好比xin-lai.com)解析:
如上图所示,这样就不用每次为了调测网络问题、应用问题并且安装各类工具了,费时费力不说,有时候网络不通就比较伤了。
根据“听诊”步骤,咱们须要得到具体的情报才能对症下药。好比Pod为啥没有调度,是资源(CPU、内存等)不足,仍是全部节点均不知足调度要求(好比指定了“nodeName”要求Pod强制调度到某个节点,而该节点宕机)。只有知道了具体缘由,咱们才能针对状况进行调整和处理,直到解决问题。
通常来讲,你们遇到的Pod问题比较多,这里笔者作个经验总结。
Pod一直处于Pending状态,经诊断为资源不足
Pending通常状况下表示这个pod没有被调度到一个节点上。一般这是由于资源不足引发的。
解决方案有:
添加工做节点
移除部分Pod以释放资源
下降当前Pod的资源限制
Pod一直处于Waiting状态,经诊断为镜像拉取失败
若是一个pod卡在Waiting状态,则表示这个pod已经调试到节点上,可是没有运行起来。
解决方案有:
检查网络问题,若是是网络问题,则保障网络通畅,能够考虑使用代理或国际网络(部分域名在国内网络没法访问,好比“k8s.gcr.io”)
若是是拉取超时,能够考虑使用镜像加速器(好比使用阿里云或腾讯云提供的镜像加速地址),也能够考虑适当调整超时时间
尝试使用docker pull <image>来验证镜像是否能够正常拉取
Pod一直处于CrashLoopBackOff状态,经检查为健康检查启动超时而退出
CrashLoopBackOff 状态说明容器曾经启动了,但又异常退出了。一般此Pod的重启次数是大于0的。
解决方案有:
重试设置合适的健康检查阈值
优化容器性能,提升启动速度
关闭健康检查