Z.S.K.'s Records

Kubernetes学习(Kubernetes踩坑记)

记录在使用Kubernetes中遇到的各种问题及解决方案, 好记性不如烂笔头

不定期更新

CoreDNS提示Loop (127.0.0.1:38827 -> :53) detected for zone “.”

原因: CoreDNS所在的宿主机上/etc/resolv.conf中存在有127.0.xx的nameserver,这样会造成解析死循环.

解决: 修改宿主机/etc/resolv.conf或者将CoreDNS的configmap中的forward修改为一个可用的地址, 如8.8.8.8

hostPath volumes are not allowed to be used

原因: 集群中存在psp禁止pod直接挂载hostpath.

解决: 通过添加psp来允许或者删除存在的psp都可

container has runAsNonRoot and image has non-numeric user (grafana), cannot verify user is non-root

原因: 这是由于在deploy中设置了securityContext: runAsNonRoot: true, 在这种情况下,当pod启动时,使用的默认用户比如上面的grafana,k8s无法确定他是不是root用户,因此需要再指定securityContext:runAsUser: 1000`, 随便一个数据即可, 只要不是0(指定0时指的是root)即可

参考

OCI runtime create failed

原因: /var/lib/kubelet/pod下的数据目录已经损坏.

ImageInspectError

原因: 这种情况下一般都是镜像损坏了

解决: 把相关的镜像删除后重新拉取

node not found

原因: 这个报错只是中间过程,真正的原因在于apiserver没有启动成功,导致会一直出现这个错误

OCI runtime create failed

原因: 在path中没有nvidia-container-runtime-hook这个二进制文件,可能跟本人删除nvidia显卡驱动有关.

Nginx Ingress Empty address

1
2
3
# kubectl get ingress
NAME HOSTS ADDRESS PORTS AGE
prometheus prometheus.1box.com 80 31d

会发现address中的ip是空的,而查看生产环境时却是有ip列表的.

原因: 这个其实不是一个错误,也不影响使用,原因在于测试环境中是不存在LoadBalance类型的svc, 如果需要address中显示ip的话需要在,需要做些额外的设置

解决:

  1. 在nginx controller的容器中指定启动参数-report-ingress-status
  2. 在nginx controller引用的configmap中添加external-status-address: "10.164.15.220"

这样的话,在address中变会显示10.164.15.220

参考:

https://github.com/nginxinc/kubernetes-ingress/issues/587

https://docs.nginx.com/nginx-ingress-controller/configuration/global-configuration/reporting-resources-status/

but volume paths are still present on disk

原因: 这种pod已经被删除了,但是volume还存在于disk中

解决: /var/lib/kubelet/pods/3cd73...

参考

PLEG is not healthy

原因: PLEG(Pod Lifecycle Event Generator),宿主机上面跑的容器太多,导致pod无法在3m钟内完成生命周期检查

参考

metrics-server: 10255 connection refused

1
unable to fully collect metrics: [unable to fully scrape metrics from source kubelet_summary:k8s-node-49: unable to fetch metrics from Kubelet k8s-node-49 (xxx.xxx.xxx.49): Get http://xxx.xxx.xxx.49:10255/stats/summary?only_cpu_and_memory=true: dial tcp xxx.xxx.xxx.49:10255: connect: connection refused

解决: 将- --kubelet-port=10255注释

metrics-server: no such host

1
unable to fetch metrics from Kubelet k8s-node-234 (k8s-node-234): Get https://k8s-node-234:10250/stats/summary?only_cpu_and_memory=true: dial tcp: lookup k8s-node-234 on 10.96.0.10:53: no such host

解决: 使用kubelet-preferred-address-types=InternalIP,Hostname,InternalDNS,ExternalDNS,ExternalIP参数

daemonset tolerations

集群中新增了几台机器用于部署clickhouse用于做大数据分析,为了不让这类占用大量资源的POD影响其它POD,因此选择给机器打taint的形式控制该类POD的调度, 创建POD后发现这些POD都会出现DNS解析异常, 这时就需要注意容器网络,比如flannel是否容忍了这些机器的taint,不然的话,flannel是无法被调度到这些机器的,因此容器间的通信会出现问题,可以将类似flannel这些的基础POD容忍所有的NoScheule与NoExecute

1
2
3
4
5
tolerations:
- effect: NoSchedule
operator: Exists
- effect: NoExecute
operator: Exists

Are you tring to mount a directory on to a file

原因:

Yaml文件中使用了subPath, 但是mountPath指向了一个目录

解决:

mountPath需要加上文件名

Kubernetes启动后提示slice: no such file ro directory

原因:

yum安装的kubelet默认的是cgroupfs,而docker一般默认的是systemd。但是kubernetes安装的时候建议使用systemd, kubelet跟docker的不一致, 要么修改kubelet的启动参数 , 要么修改dokcer启动参数

解决:

docker的启动参数文件为: /etc/docker/daemon.json: "exec-opts": ["native.cgroupdriver=systemd”]

kubelet的启动参数文件为: /var/lib/kubelet/config.yaml: cgroupDriver: systemd

“cni0” already has an IP address different from

原因:

使用kubeadm reset 重复操作过, reset之后,之前flannel创建的bridge device cni0和网口设备flannel.1依然健在

解决:

添加之前需要清除下网络

1
2
3
4
5
6
7
8
9
10
11
12
13
kubeadm reset
systemctl stop kubelet
systemctl stop docker
rm -rf /var/lib/cni/
rm -rf /var/lib/kubelet/*
rm -rf /etc/cni/
ifconfig cni0 down
ifconfig flannel.1 down
ifconfig docker0 down
ip link delete cni0
ip link delete flannel.1
systemctl start docker
systemctl start kubelet

kubeadm初始化时提示 CPU小于2

1
2
3
4
[preflight] Running pre-flight checks
error execution phase preflight: [preflight] Some fatal errors occurred:
[ERROR NumCPU]: the number of available CPUs 1 is less than the required 2
[preflight] If you know what you are doing, you can make a check non-fatal with `--ignore-preflight-errors=...`

原因:

kubeadm对资源一定的要求,如果是测试环境无所谓的话,可忽略

解决:

1
使用 --ignore-preflight-errors 忽略

Unable to update cni config: no network found

原因:

还未部署网络插件容器,导致在/etc/cni下还没有文件

解决:

根据实际情况部署网络插件

while reading ‘google-dockercfg’ metadata

原因:

无法访问上述url出现 404

解决:

由于是在RKE上部署k8s, 所以可能会去访问google相关的url, 不影响业务,可以忽略

no providers available to validate pod request

原因:

在api-server的启动参数enable-admission中设置了PodSecrityPolicy, 但是集群中又没有任何的podsecritypolicy,因此导致整个集群都无法新建出pod

解决:

删除相应的podsecritypolicy即可

unable to upgrade connection: Unauthorized

原因:

kubelet的启动参数少了x509认证方式配置证书的路径, 加上重启kubelet即可

解决:

kubectl get cs 提示\<unknown>

原因:

是个bug, 版本的问题,kubernetes有意废除get cs命令

解决:

目前对集群的运行无影响, 可通过加-oyaml 查看状态

安装kubeadm时提示Depends错误

原因:

跟kubeadm没多大关系, 系统安装的有问题

解决:

执行以下命令修复

1
2
apt --fix-broken install 
apt-get update

访问service时提示Connection refused

现象: 从另一环境中把yaml文件导入到新环境后有些service访问不通

1
2
3
telnet mongodb-mst.external 27017
Trying 10.97.135.242...
telnet: Unable to connect to remote host: Connection refused

首先排除了域名、端口的配置问题。

会发现提示连接拒绝.可以确定的是集群内的DNS是正常的.

那么就是通过clusterIP无法到达realserver. 查看iptables规则

发现提示default has no endpoints --reject-with icmp-port-unreachable

很奇怪, 提示没有endpoints, 但是使用kubectl get ep又能看到ep存在且配置没有问题

而且这个default是怎么来的.

为了方便部署, 很多配置是从别的环境导出的配置, 有些service访问是没问题的, 只有少部分connection refused

结比一下发现一个很有趣的问题,先来看下不正常的yaml文件:

由于服务在集群外部署的, 因此这里使用了subset方式, 开始怀疑问题在这里, 但是后来知道这个不是重点

乍一看这个配置没什么问题, 部署也很正常, 但是对比正常的yaml文件,发现一个区别:

如果在services中的端口指定了名字, 那么在subsets中的端口也要带名字, 没有带名字的就会出现connection refused,这个确实之前从来没有关注过, 一个端口的情况下也不会指定名字

而且这面iptalbes中提示的default刚好就是这里的port name,虽然不敢相信,但是也只能试一试这个方法: 在subsets中也加了port name

重新部署一个,再次查看iptalbes规则

iptables-save|grep mongodb-mst

OMG, 居然可行, 再看下telnet的结果:

1
2
3
Trying 10.105.116.92...
Connected to mongodb-mst.external.svc.cluster.local.
Escape character is '^]'.

访问也是没问题, 那么原因就在于:

在service中指定了port name时, 也需要在ep中指定port name

error converting fieldPath: field label not supported

今天遇到一个部署deployment出错的问题, yaml文件如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
apiVersion: apps/v1
kind: Deployment
metadata:
name: demo-deployment
namespace: 4test
labels:
app: config-demo-app
spec:
replicas: 1
selector:
matchLabels:
app: config-demo-app
template:
metadata:
labels:
app: config-demo-app
annotations:
# The field we'll use to couple our ConfigMap and Deployment
configHash: 4431f6d28fdf60c8140d28c42cde331a76269ac7a0e6af01d0de0fa8392c1145
spec:
containers:
- name: config-demo-app
image: gcr.io/optimum-rock-145719/config-demo-app
ports:
- containerPort: 80
envFrom:
# The ConfigMap we want to use
- configMapRef:
name: demo-config
# Extra-curricular: We can make the hash of our ConfigMap available at a
# (e.g.) debug endpoint via a fieldRef
env:
- name: CONFIG_HASH
#value: "4431f6d28fdf60c8140d28c42cde331a76269ac7a0e6af01d0de0fa8392c1145"
valueFrom:
fieldRef:
fieldPath: spec.template.metadata.annotations.configHash

提示以下错误:

会提示Unsupported value:spec.template.metadata.annotations.configHash

目的很简单: container中的环境变量中引用configHash变量, 这个值是当configmap变更时比对两个不同的sha值以此达到重启pod的目的, 但fieldPath显然不支持spec.template.metadata.annotations.configHash

从报错提示来看, 支持列表有metadata.name, metadata.namespace, metadata.uid, spec.nodeName,spec.serviceAccountName, status.hostIp, status.PodIP, status.PodIPs

这些值用于容器中需要以下信息时可以不从k8s的apiserver中获取而是可以很方便地从这些变量直接获得

参考

参考文章:

转载请注明出处https://izsk.me

Z.S.K. wechat
Scan Me To Read on Phone
I know you won't do this,but what if you did?