Skip to content

Latest commit

 

History

History
252 lines (221 loc) · 12 KB

问题排查.md

File metadata and controls

252 lines (221 loc) · 12 KB

认证要求

  • Troubleshooting 问题排查 10%
    • 排查应用失败故障
    • 排查控制层(control panel)故障
    • 排查工作节点(work node)故障
    • 排查网络故障

trouble shooting

学会看termination message

容器退出时, 会往容器的/dev/termination-log写终止日志。 可以通过命令查看这个日志内容:

  kubectl get pod termination-demo -o go-template="{{range .status.containerStatuses}}{{.lastState.terminated.message}}{{end}}"

这个终止日志的路径默认是/dev/termination-log, 但是可以自定义。 比如你的应用退出时会往/tmp/my-log写终止日志。 你希望改变终止日志的路径, 就可以指定terminationMessagePath 的值。

apiVersion: v1
kind: Pod
metadata:
  name: msg-path-demo
spec:
  containers:
  - name: msg-path-demo-container
    image: debian
    terminationMessagePath: "/tmp/my-log"

参考 官方文档之Determine the Reason for Pod Failure

调试Pod, Replication Controller 和 Service

调试一个pod的第一个步骤是查看它的状态。 可以通过命令查看pod的最新的状态和最近的event。

$ kubectl describe pods ${POD_NAME}

pod的几种状态及可能原因

  • pending状态

这种情况pod没有被调度成功,一般情况下可能的原因是是资源不足(pod reqeust的的资源大于当前集群所能提供的资源), hostPort冲突

  • waiting 状态

pod已被成功调度, 但是不能成功在工作节点上启动, 最常见的原因是不能下载镜像, 需要你做如下检查: 1. 镜像名称是否正确? 2. 是否有push镜像到镜像蹭课 3. 手动运行docker pull 看是否能正常拉取镜像

  • crash状态或者unhealthy状态

$ kubectl logs ${POD_NAME} ${CONTAINER_NAME}, 通过日志查看 $ kubectl logs --previous ${POD_NAME} ${CONTAINER_NAME} 查看上次crash状态的日志 kubectl exec ${POD_NAME} -c ${CONTAINER_NAME} -- ${CMD} ${ARG1} ${ARG2} ... ${ARGN} 在运行中的pod里执行命令 比如$ kubectl exec cassandra -- cat /var/log/cassandra/system.log

replication controller

kubectl describe pods <pod_name>

service 假定别人告诉我们创建了service, 叫hostnames。有个pod要连接这个service时, 报了一个错误

u@pod$ wget -qO- hostnames
wget: bad address 'hostname'

接下来就是排障过程:

  1. service是否存在?
$ kubectl get svc hostnames
Error from server (NotFound): services "hostnames" not found

说明service不存在, 赶紧创建一个

$ kubectl expose deployment hostnames --port=80 --target-port=9376
service "hostnames" exposed

重新检查一遍

$ kubectl get svc hostnames
NAME        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
hostnames   10.0.0.226   <none>        80/TCP    5s

service已经创建了, 但是服务依然不可用 2. DNS是否能为解析这个service的名称?

# 假设service的namespace是default
# 在default namespace的pod里做dns解析
u@pod$ nslookup hostnames
Server:         10.0.0.10
Address:        10.0.0.10#53

Name:   hostnames
Address: 10.0.1.175

# 在其它 namespace的pod里做dns解析
u@pod$ nslookup hostnames.default
Server:         10.0.0.10
Address:        10.0.0.10#53

Name:   hostnames.default
Address: 10.0.1.175

# 在其它 namespace的pod里做dns解析完整域名,其中cluster.local是你的集群域名, 这个域名根据你创建集群的情况确定, 默认是cluster.local
u@pod$ nslookup hostnames.default.svc.cluster.local
Server:         10.0.0.10
Address:        10.0.0.10#53

Name:   hostnames.default.svc.cluster.local
Address: 10.0.1.175

如果dns能正常解析完整域名,但是不能解析部分域名, 那么需要你检查下kubelet的--cluster-dns和--cluster-domain两个参数的配置

如果上面的检查都失败了,接下来可以看看是否DNS能解析kubernetes的service , kubernetes master的service总是存在的

  1. 检查是否dns中有存在任何的service
u@pod$ nslookup kubernetes.default
Server:    10.0.0.10
Address 1: 10.0.0.10

Name:      kubernetes
Address 1: 10.0.0.1

如果上述失败了, 就要检查下dns或者kube-proxy

  1. service的ip是否可以正常工作 在node上发起访问
u@node$ curl 10.0.1.175:80
hostnames-0uton

u@node$ curl 10.0.1.175:80
hostnames-yp2kp

u@node$ curl 10.0.1.175:80
hostnames-bvc05

如果service正常工作, 你会得到正确的响应,如果不能正常工作, 那么需要做一堆检查了。

  1. service是否正确?
$ kubectl get service hostnames -o json
{
    "kind": "Service",
    "apiVersion": "v1",
    "metadata": {
        "name": "hostnames",
        "namespace": "default",
        "selfLink": "/api/v1/namespaces/default/services/hostnames",
        "uid": "428c8b6c-24bc-11e5-936d-42010af0a9bc",
        "resourceVersion": "347189",
        "creationTimestamp": "2015-07-07T15:24:29Z",
        "labels": {
            "app": "hostnames"
        }
    },
    "spec": {
        "ports": [
            {
                "name": "default",
                "protocol": "TCP",
                "port": 80,
                "targetPort": 9376,
                "nodePort": 0
            }
        ],
        "selector": {
            "app": "hostnames"
        },
        "clusterIP": "10.0.1.175",
        "type": "ClusterIP",
        "sessionAffinity": "None"
    },
    "status": {
        "loadBalancer": {}
    }
}

检查下spec.ports[]里的内容,比如target port是否是你要的应用实例暴露的port, 端口的协议(protocol)是否正确,是TCP, UDP, 还是HTTP

  1. service是否有对应的Endpoint?
$ kubectl get endpoints hostnames
NAME        ENDPOINTS
hostnames   10.244.0.5:9376,10.244.0.6:9376,10.244.0.7:9376

如果上述结果为空, 那么要确认下service的spec.selector和pods的metadata.labels是否能对应上

  1. Pod是否正常工作? 直接访问pod的ip + 端口
u@pod$ wget -qO- 10.244.0.5:9376
hostnames-0uton

pod $ wget -qO- 10.244.0.6:9376
hostnames-bvc05

u@pod$ wget -qO- 10.244.0.7:9376
hostnames-yp2kp

如果不能返回正确的结果, 就要用kubectl logs查看pod的日志, 或者使用kubectl exec 进到pod一探究竟

  1. kube-proxy是否正常工作 假定你的service正常运行,也有对应的endpoint, pod也正常服务。如果服务还是不能正常访问, 那么就要怀疑kube-proxy是否正常工作了。
# 先看下kube-proxy有没有在你的node里正常运行
u@node$ ps auxw | grep kube-proxy
root  4194  0.4  0.1 101864 17696 ?    Sl Jul04  25:43 /usr/local/bin/kube-proxy --master=https://kubernetes-master --kubeconfig=/var/lib/kube-proxy/kubeconfig --v=2
#  再看kube-proxy的日志是否正常
tail /var/log/kube-proxy.log 或者 journalctl -u kube-proxy
# 接着看kube-proxy是否有写入iptables规则
u@node$ iptables-save | grep hostnames
-A KUBE-SEP-57KPRZ3JQVENLNBR -s 10.244.3.6/32 -m comment --comment "default/hostnames:" -j MARK --set-xmark 0x00004000/0x00004000
-A KUBE-SEP-57KPRZ3JQVENLNBR -p tcp -m comment --comment "default/hostnames:" -m tcp -j DNAT --to-destination 10.244.3.6:9376
-A KUBE-SEP-WNBA2IHDGP2BOBGZ -s 10.244.1.7/32 -m comment --comment "default/hostnames:" -j MARK --set-xmark 0x00004000/0x00004000
-A KUBE-SEP-WNBA2IHDGP2BOBGZ -p tcp -m comment --comment "default/hostnames:" -m tcp -j DNAT --to-destination 10.244.1.7:9376
-A KUBE-SEP-X3P2623AGDH6CDF3 -s 10.244.2.3/32 -m comment --comment "default/hostnames:" -j MARK --set-xmark 0x00004000/0x00004000
-A KUBE-SEP-X3P2623AGDH6CDF3 -p tcp -m comment --comment "default/hostnames:" -m tcp -j DNAT --to-destination 10.244.2.3:9376
-A KUBE-SERVICES -d 10.0.1.175/32 -p tcp -m comment --comment "default/hostnames: cluster IP" -m tcp --dport 80 -j KUBE-SVC-NWV5X2332I4OT4T3
-A KUBE-SVC-NWV5X2332I4OT4T3 -m comment --comment "default/hostnames:" -m statistic --mode random --probability 0.33332999982 -j KUBE-SEP-WNBA2IHDGP2BOBGZ
-A KUBE-SVC-NWV5X2332I4OT4T3 -m comment --comment "default/hostnames:" -m statistic --mode random --probability 0.50000000000 -j KUBE-SEP-X3P2623AGDH6CDF3
-A KUBE-SVC-NWV5X2332I4OT4T3 -m comment --comment "default/hostnames:" -j KUBE-SEP-57KPRZ3JQVENLNBR

正常情况下有1条KUBE-SERVICES规则,每个endpoint会有1~2条KUBE-SVC-(hash)规则, 1个 KUBE-SEP-(hash)规则, 还有若干KUBE-SEP-(hash)的
  1. 其它问题 如service没有endpoint, 网络流量没有转发, pod 的ip不能访问自己的service的vip(一般和kubelet的hairpin-mode的设置有关), 请参考官方文档

参考 官方文档之Debug Pods and Replication Controllers 官方文档之Debug Services

集群故障调试

  1. kubectl get nodes 看有多少node处于ready状态
  2. 查看日志, 使用jounalctl或者tail查看master(kube-scheduler, kube-apiserver, kube-controller-manager), node(kubelet, kube-proxy)的日志
  3. 可能导致集群故障的原因(VM故障, 集群之中或集群和用户之间的网络中断隔离故障,kubernetes的软件崩溃, 持久化存储不可用或数据丢失, 操作错误比如错误配置了kubernetes集群等 )
故障   |   现象   |   缓解措施
Apiserver VM shutdown or apiserver crashing   |   1. 不能停止,更新, 启动pod, service, replication controller  2. 原有的pod和service不受影响, 除非它们依赖kubernetes api   |   1.主机自动重启 2. 使用高可用架构部署
Apiserver backing storage lost   |   1. apiserver不能启动  2. kubelet不能连接到apiserver  3.在apiserver restart之前, 手动恢复和重建apiserver的状态是必须的   |   1. 在主机上挂载可靠的存储,用于apiserver+etcd  2. 使用高可用架构部署3.定期对apiserver的数据做快照
安装kubernetes组件的vm宕机   |   因为目前apiserver, controller-manager, scheduler必须部署在一起,如果部署组件的虚机宕机 ,则三个组件会同时故障。未来可能会支持独立部署, 且不保留各自的持久化状态   |   1. 主机自动重启2. 使用高可用架构部署
个别的node宕机   |   在该node的pod停止运行   |   1. 主机自动重启 2. 使用replication controller和service,而不是单独创建pod 3. 应用设计上允许不可预期的重启
网络分区故障(network partition)   |   master和node互相认为对方宕掉   |   无
kubelet软件错误   |   1. crash掉的kubelet不能在node上启动新的pod, 2. kubelet可能会也可能不会删除pod, 3. 所在的node会被apiserver标记为unhealthy状态 4. replication controller会在别的node启动pod   |   1. 使用replication controller和service,而不是单独创建pod 2. 应用设计上允许不可预期的重启
集群操作错误   |   1. pods,service等对象丢失 2. apiserver的后端存储失联  3. 用户不能读取api 4. 其它   |   1.定期对apiserver的数据做快照

应用故障调试

pod的调试

  • pending: 资源不足,或者 启用了hostport导致端口冲突
  • waiting: 检查一下是否有正确的docker镜像名称, 或者仓库里有推送镜像, 可以手动在node上执行一下docker pull image 命令
  • crash / unhealthy: 查看应用的log(kubectl logs ), 或者进入到容器里检查(kubectl exec)
  • pod运行但是结果不是我想要的: 删除pod, 用kubectl create --validate -f mypod.yaml重建看看是否有报错, 或者 使用kubectl get pods/mypod -o yaml > mypod-on-apiserver.yaml ,和你的yaml做比较,看是否有重大差异

replication controller的调试, service的调试见前面的章节(调试Pod, Replicaton Controller, service)

常用工具

常见问题

参考文献