问题描述:查看pod日志报错,Normal Killing 39s (x735 over 15h) kubelet, 10.179.80.31 Killing container with id docker://apigateway:Need to kill Pod,可能是磁盘满了,无法创建和删除 pod
解决方案:登录node节点,查看docker存储目录,检查docker磁盘空间,清理容器日志输出和可写层文件。
# docker info | grep Root //查看 docker存储目录
Docker Root Dir: /var/lib/docker
# df -h //检查磁盘空间 Filesystem 1K-blocks Used Available Use% Mounted on ... /dev/vda1 51474044 4619112 44233548 10% / ... /dev/vdb 20511356 20511356 0 100% /var/lib/docker
# cd /var/lib/docker/containers
# du -sh * // 找到比较大的目录
# cd dda02c9a7491fa797ab730c1568ba06cba74cecd4e4a82e9d90d00fa11de743c
# cat /dev/null > dda02c9a7491fa797ab730c1568ba06cba74cecd4e4a82e9d90d00fa11de743c-json.log.9 //删除log文件,使用 cat /dev/null >
方式删除而不用 rm
,因为用 rm 删除的文件,docker 进程可能不会释放文件,空间也就不会释放;log 的后缀数字越大表示越久远,先删除旧日志。
# kubectl drain 10.179.80.31 //将该 node 标记不可调度,并将其已有的 pod 驱逐到其它节点
# systemctl restart dockerd //重启 dockerd
# kubectl uncordon 10.179.80.31 //取消不可调度的标记
总结:
# for i in `docker info | grep Root| awk '{print $4}'` ; do du -sh $i/containers/* | sort ; done //找出日志输出量大的pod
# for i in `docker info | grep Root| awk '{print $4}'` ; do du -sh $i/aufs/diff | sort ; done //找出可写层数据量大的pod
# grep 834d97500892f56b24c6e63ffd4e520fc29c6c0d809a3472055116f59fb1d2be /var/lib/docker/image/aufs/layerdb/mounts/*/mount-id //通过可写层目录(diff
的子目录)反查容器id
# docker images //找出体积大的镜像
问题描述:查看pod日志报错,Warning FailedSync 3m (x408 over 1h) kubelet, 10.179.80.31 error determining status: rpc error: code = DeadlineExceeded desc = context deadline exceeded,怀疑是17版本dockerd的BUG。可通过 kubectl -n cn-staging delete pod apigateway-6dc48bf8b6-clcwk --force --grace-period=0
强制删除pod,但 docker ps
仍看得到这个容器
解决方案:
问题描述:k8s 资源的 metadata 里如果存在 finalizers
,那么该资源一般是由某程序创建的,并且在其创建的资源的 metadata 里的 finalizers
加了一个它的标识,这意味着这个资源被删除时需要由创建资源的程序来做删除前的清理,清理完了它需要将标识从该资源的 finalizers
中移除,然后才会最终彻底删除资源。比如 Rancher 创建的一些资源就会写入 finalizers
标识。
解决方案:kubectl edit
手动编辑资源定义,删掉 finalizers
,这时再看下资源,就会发现已经删掉了
问题描述:查看pod日志报错,(combined from similar events): Failed create pod sandbox: rpc error: code = Unknown desc = failed to create a sandbox for pod "apigateway-6dc48bf8b6-l8xrw": Error response from daemon: mkdir /var/lib/docker/aufs/mnt/1f09d6c1c9f24e8daaea5bf33a4230de7dbc758e3b22785e8ee21e3e3d921214-init: no space left on device,node上磁盘满了,无法创建和删除 pod
解决方案:参考问题一的解决方案
问题描述:查看pod日志报错,Error syncing pod,可能是节点的内存碎片化严重,导致无法创建pod
解决方案:
周期性地或者在发现大块内存不足时,先进行drop_cache操作:
echo 3 > /proc/sys/vm/drop_caches
必要时候进行内存整理,开销会比较大,会造成业务卡住一段时间(慎用):
echo 1 > /proc/sys/vm/compact_memory
问题描述:查看pod日志报错,signal: killed,memory limit 单位写错,误将memory的limit单位像request一样设置为小 m
,这个单位在memory不适用,应该用Mi
或M
,会被k8s识别成byte,所以pause容器一起来就会被 cgroup-oom kill 掉,导致pod状态一直处于ContainerCreating
解决方案:修改yaml摸板中的内存单位。
问题描述:查看 master 上 kube-controller-manager 状态,异常的话尝试重启
解决方案:重启 kube-controller-manager服务
问题描述:创建pod,资源不足。
解决方案:将Allocatable和“Allocated resources”相减,可得出剩余可申请的资源。如果这个值小于 pod 的 request,就不满足 pod 的资源要求,也就不会调度上去。
# kubectl describe node | grep -A 5 Allocatable //Allocatable
表示此节点 k8s 能够申请的资源总和
# kubectl describe node | grep -A 5 'Allocated resources' //Allocated resources
表示此节点已分配的资源
问题描述:资源够用,但是未被调度。node 不满足 pod 的 nodeSelector 或 affinity。
解决方案:检查 pod 是否有 nodeSelector 或 affinity(亲和性)的配置,如果有,可能是 node 不满足要求导致无法被调度。
问题描述:旧 pod 无法解挂 cbs 云盘。可能是 pod 之前在另一个节点,但之前节点或kubelet挂了,现在漂移到新的节点上,但是之前pod挂载了cbs云盘,而由于之前节点或kubelet挂了导致无法对磁盘进行解挂,pod 漂移到新的节点时需要挂载之前的cbs云盘,但由于磁盘未被之前的节点解挂,所以新的节点无法进行挂载导致pod一直pending。
解决方案:在腾讯云控制台找到对应的云主机或磁盘,手动对磁盘进行卸载,然后pod自动重启时就可以成功挂载了(也可以delete pod让它立即重新调度)
问题描述:镜像无法下载。
解决方案:看下 pod 的 event,看下是否是因为网络原因无法下载镜像或者下载私有镜像给的 secret 不对。
问题描述:低版本 kube-scheduler 的 bug。
解决方案:可能是低版本 kube-scheduler
的 bug, 可以升级下调度器版本。
问题描述:Service 无法解析,低检查 dns 服务是否正常(kube-dns或CoreDNS)
解决方案:
# ps -ef | grep kubelet //查找dns 服务的 cluster ip
...--cluster-dns=172.16.255.81...
# kubectl get svc -n kube-system | grep 172.16.255.81 //查找dns 的 service
kube-dns ClusterIP 172.16.255.81 <none> 53/TCP,53/UDP 7d23h
# kubectl -n kube-system describe svc kube-dns | grep -i endpoints //查找endpoint
Endpoints: 172.16.1.2:53,172.16.1.4:53
Endpoints: 172.16.1.2:53,172.16.1.4:53
# kubectl -n kube-system get pod -o wide | grep 172.16.1.2 //查找endpoint 的 对应 pod 是否正常
coredns-85c958d7d-qnnjv 1/1 Running 1 3d22h 172.16.1.2 192.168.79.15 <none>
一键查询汇总:
# for i in `ps -ef | grep kubelet | grep -v color | awk -F 'cluster-dns' '{print $2}'| awk -F '=' '{print $2}'| awk '{print $1}'`; \
do \
echo -e "\033[34m dns服务的cluster ip:\033[0m"$i; \
echo -e "\033[34m dns的service:\033[0m";\
kubectl get svc -n kube-system | grep $i; \
echo -e "\033[34m 看是否存在endpoint:\033[0m"; \
kubectl -n kube-system describe svc kube-dns | grep -i endpoints; \
echo -e "\033[34m 检查endpoint的对应pod是否正常\033[0m:"; \
test=`kubectl -n kube-system describe svc kube-dns | grep -i endpoints| awk '{print $2}' | awk -F ':' '{print $1}'|uniq`; \
kubectl -n kube-system get pod -o wide | grep $test; \
done
问题描述:dns 服务正常,pod 与 dns 服务之间网络不通
解决方案:检查 dns 服务运行正常,再检查下 pod 是否连不上 dns 服务,可以在 pod 里 telnet 一下 dns 的 53 端口
# telnet 172.16.1.2 53 //连 dns service 的 cluster ip
如果检查到是网络不通,就需要排查下网络设置
问题描述:Service 定义中的 targetPort 对应容器的端口,如果容器监听的是 8080,而 targetPort 写的 80,那么会不通,所以确保 targetPort 与容器监听的端口要一致。
解决方案:检查和修改yaml文件。
问题描述:节点安全组没放开 NodePort 区间,由于 TKE 的 LoadBalancer Service 基于 NodePort 实现,所以 LB 会绑定节点的 NodePort 端口(Service中的nodePort字段),也就是 LB 会将请求直接发到节点的 NodePort 端口上,然后 k8s 内部再通过 kube-proxy 将数据包路由到对应的 pod 中。
解决方案:通常节点安全组都对内网放开访问的,所以如果是内网LB一般不会这样,如果LB是公网类型,它对绑定的节点进行健康检查探测的源ip就是这个公网ip,而nodePort区间是30000-32768,所以节点安全组应该对 0.0.0.0/0
的 TCP 和 UDP 设为允许。
问题描述:容器集群内无法访问外网
解决方案:
1.检查node节点是否可以访问外网(确保 node 能上外网,如果在node上都不能访问外网,则集群内也无法访问)
2.TKE 1.10 以上的集群在 kube-system
下有 ip-masq-agent
的 Deamonset,作用是将出公网的请求的源 ip snat 成 node 的 ip,这样数据包才能出公网,确保 node 上有 ip-masq-agent
的 pod:
# kubectl get pod -n kube-system -o wide
3.发现完全没有,请提工单;
如果发现有,但部分没有,检查下节点是否设置了污点(taint),导致 Deamonset 的 pod 无法被调度上来;
如果发现都有,还是无法访问公网,检查下 ip-masq-agent 的 配置:
# kubectl -n kube-system get cm ip-masq-agent-config -o yaml
问题描述:购买了 mysql, redis 等外部服务,或者在集群外自己搭建了一些服务(如自建dns、暂未容器化的服务等),集群内的pod访问不通这些服务
解决方案:通常是安全组问题,容器网络是在 vpc 层面实现的,pod ip 在整个 vpc 内都可以路由,如果容器访问 vpc 内但在集群外的服务,需要这个服务对应机器的安全组放开这个容器网段,因为服务收到容器的数据报文的源IP就是pod ip
问题描述:kubectl无法执行exec 和 logs,无法进入pod
解决方案:通常是 apiserver --> kubelet:10250 之间的网络不通,10250 是 kubelet 提供接口的端口,kubectl exec
和kubectl logs
的原理就是 apiserver 调 kubelet,kubelet 再调 dockerd 来实现的,所以要保证 kubelet 10250 端口对 apiserver 放通。
kubectl exec
和kubectl logs
)问题描述:本质上是脏数据问题,Running+Succeed != 期望Completions 数量,低版本 kubectl 不容忍,delete job 的时候打开debug(加-v=8),会看到kubectl不断在重试,直到达到timeout时间。新版kubectl会容忍这些,删除job时会删除关联的pod。可能是 k8s 的一个bug: https://github.com/kubernetes/kubernetes/issues/43168
解决方案:
1.升级 kubectl 版本,1.12 以上
2.低版本 kubectl 删除 job 时带 --cascade=false
参数(如果job关联的pod没删完,加这个参数不会删除关联的pod)
kubectl delete job --cascade=false <job name>
问题描述:node上直接访问pod能通,访问 service 和 nodePort 不行,service 的 targetPort 与容器实际监听端口不一致。
解决方案:更正 service 的 targetPort
问题描述:node上直接访问pod能通,访问 service 不行且集群开启了 ipvs、集群版本小于1.11、node上有pod使用了与service同端口号的hostPort
解决方案:是 k8s 对 ipvs 支持的 bug,1.11 版本修复,使用不与 service 端口号冲突的 hostPort 或升级集群版本
问题描述:node的安全组需要放通容器网段,因为访问 service 时,数据包可能从一个node转发到另一个node,源IP网段是容器网段,如果node安全组没放通转发就会失败
解决方案:修改安全组,放通容器网段。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。