k8s之连接异常(集群故障)
1.k8s集群的能力供应站(pod)的详解
Pod是k8s中的最小调度单元,当指派容器时,容器实际上并不会指派到物理硬件上,容器会被分配到一个pod里,pod代表集群上正在运行的一个进程,一个pod封装一个容器(也可以封装多个容器),pod里的容器共享存储、网络等。也就是说,应该把整个pod看作虚拟机,然后每个容器相当于运行在虚拟机的进程。
2.k8s集群中的pod的用途
运行单个容器的pod:
Pod里封装单个容器,k8s直接管理pod,pod调度到哪个物理节点,pod里的容器就跟随pod调度到哪个节点。
运行多个协同工作的容器的pod:
Pod里可以运行多个容器,如初始化容器、业务容器,这些容器之间的互相作用,共享资源。
3.k8s集群中pod一般哪些方面容易出现问题 与 遇到pod各种状态以及排查思路的方法
1)k8s资源配置错误
例如部署deployment和statefuset时,资源清单书写有问题,导致pod无法正常创建。
2)代码问题
应用程序代码在容器启动后失败,那就需要通过检查代码找错误。
3)网络问题
网络插件部署有问题,导致pod启动之后无法相互通信。
4)存储问题
Pod挂载存储,但是需要共享的存储连接不上导致pod启动异常。
pod的各种状态
1)启动时的错误包括:
ImagePullBackoff
ImageInspectError
ErrImagePull
ErrImageNeverPull
RegistryUnavailable
InvalidImageName
2)运行中的错误包括:
CrashLoopBackOff
RunContainerError
KillContainerError
VerifyNonRootError
RunInitContainerError
CreatePodSandboxError
ConfigPodSandboxError
KillPodSandboxError
SetupNetworkError
TeardownNetworkError
3)常见pod状态
Pending:
#正在创建Pod但是Pod中的容器还没有全部被创建完成,处于此状态的Pod应该检查Pod依赖的存储是否有权限挂载、镜像是否可以下载、调度是否正常等
Failed
#Pod中有容器启动失败而导致pod工作异常。检查事件
Unknown
#由于某种原因无法获得pod的当前状态,通常是由于与pod所在的node节点通信错误
Succeeded
#Pod中的所有容器都被成功终止即pod里所有的containers均已terminated。
Unschedulable:
#Pod不能被调度,kube-scheduler没有匹配到合适的node节点
PodScheduled
#pod正处于调度中,在kube-scheduler刚开始调度的时候,还没有将pod分配到指定的node,在筛选出合适的
节点后就会更新etcd数据,将pod分配到指定的node
Initialized
#所有pod中的初始化容器已经完成了
ImagePullBackOff:
#Pod所在的node节点下载镜像失败
Running
#Pod内部的容器已经被创建并且启动
Ready
#表示pod中的容器已经可以提供访问服务
complete
# 容器已创建完成
4)其它状态
Error: # pod 启动过程中发生错误
NodeLost: # Pod 所在节点失联
Unkown: # Pod 所在节点失联或其它未知异常
Waiting: # Pod 等待启动
Pending: # Pod 等待被调度
Terminating: # Pod 正在被销毁
CrashLoopBackOff: # pod 但是kubelet正在将它重启
InvalidImageName: # node节点无法解析镜像名称导致的镜像无法下载
ImageInspectError: # 无法校验镜像 镜像不完整导致
ErrImageNeverPull: # 策略禁止拉取镜像 镜像中心权限是私有等
ImagePullBackOff: # 镜像拉取失败 但是正在重新拉取
RegistryUnavailable: # 镜像服务器不可用 网络原因或harbor宕机
ErrImagePull: # 镜像拉取出错 超时或下载被强制终止
CreateContainerConfigError:# 不能创建kubelet使用的容器配置
CreateContainerError: # 创建容器失败
PreStartContainer:
执行preStart hook报错,Pod hook(钩子)是由 Kubernetes 管理的 kubelet 发
起的,当容器中的进程启动前或者容器中的进程终止之前运行,比如容器创建完成后里面的服务启动之前可以检查一下
依赖的其它服务是否启动,或者容器退出之前可以把容器中的服务先通过命令停止。
PostStartHookError: # 执行 postStart hook 报错
RunContainerError: # pod运行失败,容器中没有初始化PID为1的守护进程等
ContainersNotInitialized: # pod没有初始化完毕
ContainersNotReady: # pod没有准备完毕
ContainerCreating: # pod正在创建中
PodInitializing: # pod正在初始化中
DockerDaemonNotReady: # node节点docker服务没有启动
NetworkPluginNotReady: # 网络插件还没有完全启动
常见错误原因
ImagePullBackOff
镜像拉取错误(无效的镜像,指定了不存在标签,registry凭据)
CrashLoopBackOff
(应用程序中存在错误,容器配置错误,liveness探针失败)
kubectl logs podname --previous
(如果容器启动太快,打印前一个容器信息)
RunContainerError
(1.查看是否有不存在的卷,如configmap,secret 2.将只读挂在为读写) ---> kubectl describe pod <pod-name> 命令检查和分析这个错误
pending状态
(1.没有足够的资源调度失败 2.当前命名空间具有ResourceQuota 对象,创建 Pod 将使命名空间超过配额 3.绑定了一个处于pending状态的pvc)
kubectl get events --sort-by=.metadata.creationTimestamp # 如果ResouceQuota不足
pod处于未就绪状态(`就绪`探针失败时,则 Pod 未连接到服务,并且没有流量转发到该实例)
查看pod是否正常
kubectl get pods -n fronted
常见pod排查命令
kubectl logs <pod name> 有助于检索 Pod 中容器的日志
kubectl describe pod <pod name> 对检索与 Pod 相关的事件列表很有用
kubectl get pod <pod name> -o yaml 可提取 Kubernetes 中存储的 Pod 的 YAML 定义;
kubectl exec -ti <pod name> bash 可在 Pod 中的一个容器运行一个交互式命令
4.pod的状态为ContainerCreating状态的故障
一般原因是:后面node节点故障不能工作或网络ip已被注册、也可能是没有挂载到pv的存储卷。
诊断方法流程:
kubectl get pod -o wide |grep pod名 #查看pod在哪个节点
kubectl describe pod pod名 #查看pod的详细信息
kubectl logs pod pod名 [-c 容器名] #查看pod的日志或某个容器日志
systemctl status kubelet #查看pod所在节点的kubelet服务状态
journalctl -u kubelet #使用systemd运行kubelet,则需要使用journalctl 方法查看kubelet的日志
tailf /…/kubelet.xx.log #查看pod所在节点的kubelet服务日志
1)后面node节点故障不能工作的处理:
创建一个别的新的pod,看能否运行在该node1节点上,如果其他pod能创建在node1节点,说明可能只是无法创建的pod本身有问题,如果所有其他pod都无法在node1节点创建(所有在node节点创建的pod状态都是:ContainerCreating),说明node1节点有问题。
如果已经确定某个node节点有问题不能使用时,需要将node节点重置后重新加入集群:
步骤如下:
1) 先将该node节点上正在运行的pod驱逐到其他node节点
2) kubeadm reset 在故障node节点上重置k8s集群,执行完相当于这个节点所有东西都清空了(操作需要慎重,将pod全部驱逐后再操作)
3) systemctl stop kubelet
4) systemctl stop docker
5) rm -rf /var/lib/kubelet/*
6) rm -rf /etc/cni/
7) ifconfig cni0 down
8) ifconfig flannel.1 down (如果安装的是flannel网络)
9) ip link delete cni0
10) ip link delete flannel.1
11) systemctl start docker
12) systemctl start kubelet
13) kubeadmin join … 把node节点重新加入加入k8s集群
2)也可能是没有挂载到pv的存储卷的处理:
查看pv绑定的情况和需求。
步骤如下:
kubectl get pod -o wide |grep pod名 #查看pod所在node节点
kubectl describe pod pod名 #查看pod的详细信息
若后台存储是ceph相关报错,可能是没有安装相关程序
yum -y install ceph-common #再相应节点安装ceph相关程序
安装ceph-common程序后,删除pod: test-ceph后重新运行pod,再查看状态。
如后台存储是nfs或其他,则查看相关服务是否正常,是否能手动正常挂载。
部分节点无法启动Pod: ContainerCreating状态
排查故障总结:
kubectl get pods <pod name> # 查看日志pod状态
kubectl describe pods <pod name> # 查看pod详细信息
kubectl logs pods <pod name> # 查看log日志
systemctl status kubelet # 查看kubelet状态
查看日志时候也可以 -c 容器名
5.pod的状态为pending状态的故障
Pending状态:是挂起状态。表示创建的pod找不到可以运行它的物理节点,不能调度到相应的节点上运行。
1).从两个层面分析问题:
(1).物理节点层面分析:
查看节点资源使用情况: 如free -m查看内存、top查看cpu使用率、df -h查看磁盘使用情况,这样可以定位节点资源情况,判断是不是节点有问题。
查看节点污点:#kubectl describe node node节点名字 ,如果节点定义了污点,那么pod不能容忍污点,就会调度失败,可以在yaml文件里定义容忍度,则可以试下调度。
(2).pod本身分析:
在定义pod时,如果指定了nodeName或nodeSelector选择器是不存在的,那么也会调度失败。
在定义pod时,如果定义的资源请求比较大,导致物理节点资源不够也是不会调度的。
2).查看node节点是否有污点的方法:
kubectl describe node node名称 |grep Taints
Taints xxx (看有没有,没有就是空)
Pod状态异常排查问题集-pending状态排查思路
Pending是挂起状态: 表示创建的Pod找不到可以运行它的物理节点,不能调度到相应的节点上运行,那么这种情况如何去接查呢?我们可以从两个层面分析问题:
1)物理节点层面分析
1.查看节点资源使用情况:如free -m查看内存、top查看CPU使用率、df -h查看磁盘使用情况,这样就可以快速定位节点资源情况,判断是不是节点有问题
2.查看节点污点: kubectl deseribe nodes master1 (控制节点名字),如果节点定义了污点,那么Pod不能容忍污点,就会导致调度失败,如下:
3.Taints: node-role.kubernetes.io/master:NoSchedule
4.这个看到的是控制节点的污点,表示不允许Pod调度 (如果Pod定义容忍度,则可以实现调度)
2)Pod本身分析
1.在定又pod时,如果指定了nodeNamo是不存在的,那也会调度失败
2.在定义Pod时,如果定义的资源请求比较大,导致物理节点资源不够也是不会调度的
image.png
image.png
6.pod的状态为ImagePullBackOff状态的故障
1)ImagePullBackOff状态的原因:
(1).拉取镜像时间长导致超时.
(2).配置的镜像有错误:如镜像名字不存在等.
(3).配置的镜像无法访问:如网络限制无法访问hub上的镜像.
(4).配置的私有镜像仓库参数错误:如imagePullSecret没有配置或者配置错误.
(5).dockerfile打包的镜像不可用.
2)ImagePullBackOff状态的排查思路:
kubectl get pod -o wide 查看pod在哪个节点
kubectl describe pod pod名 查看pod的详细信息
查看到时镜像拉不下来问题时,可以手动拉一下看看
Pod状态异常排查问题集 ImagePulIBackOff状态
1)问题分析
拉取镜像时间长导致超时
配置的镜像有错误:如镜像名字不存在等
配置的镜像无法访问:如网络限制无法访问hub上的镜像
配置的私有镜像仓库参数错误: 如imagePullSecret没有配置或者配置错误
dockerfile打包的镜像不可用
Pod状态异常排查问题集 ImagePullBackOff状态排查思路
1)查看Pod
kubectl get pods -o wide
tomcat-pod 0/1 ImagePulIBackOff 0 105s
通过上面可以看到镜像拉取有问题,那可以进一步再将查错误
kubectl describe pods tomcat-pod
7.pod的状态为CrashLoopBackOff状态的故障
1)CrashLoopBackOff状态的原因:
pod里面的容器退出、多次重启或准备删除。
k8s中的pod正常运行,但是里面的容器可能退出或者多次重启或者准备删除,导致出现这个状态,这个状态具有偶发性,可能上一步还是running状态,但是突然就变成CrashLoopBackOff状态了。
2)CrashLoopBackOff状态的排查思路:
kubectl logs pod名 [-c 容器名] 查看pod日志,代码或环境变量
查看日志,查看构建镜像用的代码是否有问题,如果代码没问题,再看环境变量是否有问题。
kubectl describe pod pod名 查看pod的详细信息,limit资源限制
查看yaml文件里的limit资源限制,是否跟资源限制有关。
image.png
8.pod的状态为Error状态的故障
原因分析:
1)依赖的configmap、secret、pv、storageClass等不存在.
2)请求的资源超过了管理员设置的限制,比如超过了limits等.
3)无法操作集群内的资源,比如:开启rbac后,需要为serviceAccount配置权限.
排查思路:
kubectl describe pod pod名 #查看pod详细信息
kubectl logs pod pod名 [-c 容器名] #查看pod或容器日志
kubectl -f -u kubelet #查看kubelet服务日志
tail -f /var/log/messages #查看主机日志
9.pod的状态为Terminating或Unknown状态的故障
原因分析:
Terminating故障是因为容器里的应用挂了或node节点失联。
从k8s1.5开始,k8s不会因为node失联而删除其上正在运行的pod,而是将其标记为Terminating或Unknown状态。
相应删除这些状态的pod有4种方法:
1).手动删除node节点(确定节点不能用再删)
kubectl delete node node节点名称
2).恢复正常可选择性删除,若node节点恢复正常,kubelet会重新跟kube-apiserver通信确认这些pod的期待状态,进而再决定删除或者继续运行这些pod,如果删除可以通过
kubectl delete pod pod名 –grace-period=0 --force 强制删除
3).使用参数重建容器 (了解)
4).自动重建pod (了解)
注意:节点确实不能用了再删node节点。删除node节点前,先将部署的pod服务驱逐到其他node节点。
如果node节点已经删除了,但是使用命令kubectl get pod查看时该node节点上还显示有pod,呈现terminating状态,可以用命令: kubectl delete pod pod名 –grace-period --force 强制删除该pod。
解决思路:
1).systemctl status kubectl #查看kubectl状态
2).kubectl get node #查看节点状态和节点资源是否还充足,df -h free -m
3).kubectl get pod -n kube-system |grep apiserver #查看apiserver是否异常
4).查看kubelet日志,查看相应node节点的kubelet错误日志
从 v1.5 开始,Kubernetes 不会因为 Node 失联而删除其上正在运行的 Pod,而是将其标记为 Terminating 或 Unknown 状态。想要删除这些状态的 Pod 有三种方法:
1)从集群中删除该 Node。使用公有云时,kube-controller-manager 会在 VM 删除后自动删除对应的 Node
而在物理机部署的集群中,需要管理员手动删除 Node(如 kubectl delete node <node-name>)
2)Node 恢复正常
Kubelet 会重新跟 kube-apiserver 通信确认这些 Pod 的期待状态,进而再决定删除或者继续运行这些 Pod
3)用户强制删除
用户可以执行 kubectl delete pods <pod> --grace-period=0 --force 强制删除 Pod。
除非明确知道 Pod 的确处于停止状态(比如 Node 所在 VM 或物理机已经关机),否则不建议使用该方法
特别是 StatefulSet 管理的 Pod,强制删除容易导致脑裂或者数据丢失等问题
10.pod的健康检查(存活性探测和就绪性探测)
1).为什么需要探针?
如果没有探针,k8s无法知道应用是否还活着,只要pod还在运行,k8s则认为容器时健康的。但实际上,pod虽然运行了,但里面容器中的应用可能还没提供服务,那就需要做健康检查,健康检查就需要探针。
2).常见的探针有以下几种:
1)httpGet
对容器的ip地址(指定的端口和路径)执行http get请求,如果探测器收到响应,并且响应码是2xx,则认为探测成功。
如果服务器没有响应或者返回错误响应码则说明探测失败,容器将重启
2)tcpSocket
探针与容器指定端口建立tcp连接,如果连接建立则探测成功,否则探测失败容器重启
3)exec
在容器内执行任意命令,并检查命令退出状态码,
如果状态码为0,则探测成功,否则探测失败容器重启
3)健康检查的两种方式: livenessProbe和ReadinessProbe
1)LivenessProbe(存活探测):
探测pod里的容器是否启动成功,如果pod里的容器启动成功那pod的状态就是Running
2)ReadinessProbe(就绪探测):
Pod是Running的前提下,看pod里容器部署的应用是否就绪,是否可以对外提供服务,如果应用正常,可以接受客户端的请求,则ready是就绪的
4)LivenessProbe和ReadinessProbe区别:
LivenessProbe决定是否重启容器、ReadinessProbe主要来确定容器是否已经就绪,
只有当pod里的容器部署的应用都处于就绪状态,才会将请求转发给容器。
pod定义的存活性探测如下:
livenessProbe:
httpGet:
path: /
port: 8080
常见问题:
Killing container with id docker://xxxxx: Container failed probe.. Container wilIbe killed and reoreated.Iivenessพก
如果在pod启动时遇到这种情况,一般是没有设置initialDeIaySeconds导致的
设置初始化延迟initialDeIaySeconds
livenessProbe:
httpGet:
path: /
port: 8080
initialDeIaySeconds: 15s # pod启动过15s开始探测
容器启动后再探测,否认容器还没起来呢就探测,肯定是探测失败的。
11.token验证问题:(添加节点token过期)
token过期的处理
Kubeadm初始化k8s的时候生成的token有效期只有1天,当过期之后token就不可以用了,在node节点kubeadm join的时候在使用这个token就会报错,可用如下方法重新生成:
1.kubeadm token create
kubeadm token list 列出生成的token
2.生成一个永不过期的token
kubeadm token create --ttl 0
3.获取ca证书的hash值加入集群除了需要token外,还需要Master 节点的ca证书 sha256编码hash值,这个可以通过如下命令获取:
openssI x509 -pubkey -in /etc/kubernetes/pki/ca.crt | openssl rsa -pubin -outform der 2>/dev/null | openssl dgst -sha256 -hex | sed 's/^.* //'
4.把节点添加到集群:
kubeadm join master_IP:6443 --token XXXXXX --discovery-token-ca-cert-hash sha256:XXXX
12.kubectl执行异常,无权限连接到k8s问题定位
kubectl执行异常的排查
1.安装之后执行如下命令:
kubeotl get nodes
2.报错信息:
The connection to the server loca I host: 8080 was refused - did you specify the right host or port?
3.这是因为安装k8s之后,双认是没有权限操作k8s资源的,可用如下方法解决:
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
网友评论