前言
Kubesphere 是国内青云公司开源的 Kubernetes 发行版,有比较方便的集群管理界面,我们团队使用 Kubesphere 来作为开发平台。
本文记录了一次 kubesphere 环境下的 网络故障解决过程。
现象
开发同学反馈我们自己搭建的 harbor 仓库总是出问题,有时候可以 pull 镜像成功,有时候报 net/http: TLS handshake timeout
, 通过 curl 的方式访问 harbor.xxxx.cn,也会随机频繁挂起。但是 ping 的反馈一切正常。
原因分析
接到错误报障后,经过了多轮分析,才最终定位到原因,应该时安装 kubesphere 时,制定了使用最新版的 kubernetes 1.23.1 。
虽然使用 ./kk version --show-supported-k8s
可以看到 kubesphere 3.2.1 可以支持 kubernetes 1.23.1 ,但实际上只是试验性支持,有大坑。
基本上分析过程如下:
出现 harbor registry 访问问题,下意识以为是 harbor 部署有问题,但是在检查 harbor core 的日志的时候,没有看到异常时有错误日志信息,甚至 info 级别的日志信息都没有。
又把目标放在 harbor portal , 查看访问日志,一样没有发现异常信息.
根据访问链,继续追查 kubesphere-router-kubesphere-system , 即 kubesphere 版的 nginx ingress controller ,同样没有发现异常日志。
尝试在其他 pod 里访问 harbor 的集群内 svc 地址,发现不会出现访问超时问题。初步判断是 kubesphere 自带的 ingress 的问题。
把 kubesphere 自带的 ingress controller 关闭,安装 kubernetes 官方推荐的 ingress-nginx-controller 版本, 故障依旧,而且 pod 日志里也没有发现异常信息。 绝望了。。。。
综合上面的过程分析,问题应该出现在客户端到 ingress controller 之间,我的 ingress controller 时通过 nodeport 方式暴露到集群外面,因此,测试其他通过 nodePort 暴露到集群外的 svc,发现是一样的故障,至此完全可以排除 harbor 部署问题了,基本确定是客户端到 ingress controller 的问题。
外部客户端通过 nodePort 访问 ingress controller 时,会通过 kube-proxy 组件,分析 kube-proxy 的日志,发现告警信息
$$
can’t set sysctl net/ipv4/vs/conn_reuse_mode, kernel version must be at least 4.1
$$
这个告警信息是因为 我的 centos 7.6 的内核版本过低,与 kubernetes 新版的 ipvs 兼容。
可以通过升级 操作系统的 kernel 把版本可以解决。
- 升级完 kernel 后,calico 启动不了,报以下错误信息
$$
ipset v7.1: kernel and userspace incompatible: settype hash:ip,port with revision 6 not supported by userspace.
$$
原因是 安装 kubesphere 时默认 calico 版本是 v3.20.0 , 这个版本不支持我的最新版 linux kernel ,需要升级到 v3.23.0 以上版本。
- 升级完 calico 版本后,calico 继续报错
$$
user “system:serviceaccount:kube-system:calico-node” cannot list resource “caliconodestatuses” in api group “crd.projectcalico.org”
$$
还有另外一个错误信息,都是因为 clusterrole calico-node 的权限不足,可以通过修改权限来解决问题。
- 至此,该莫名其妙的网络问题解决了。
解决过程
根据上面的分析,主要解决方案如下:
升级操作系统内核
- 使用阿里云的 yum 源
$$
wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo
yum clean all && yum -y update
$$
- 启用elrepo仓库
$$
rpm –import https://www.elrepo.org/RPM-GPG-KEY-elrepo.org
rpm -Uvh http://www.elrepo.org/elrepo-release-7.0-3.el7.elrepo.noarch.rpm
$$
- 安装最新版本内核
$$
yum –enablerepo=elrepo-kernel install kernel-ml
$$
- 查看系统上的所有可用内核
$$
awk -F\‘ ’$1==“menuentry ” {print i++ “ : ” $2}' /etc/grub2.cfg
$$
- 设置新的内核为grub2的默认版本
查看第4步返回的系统可用内核列表,不出意外第1个应该是最新安装的内核。
$$
grub2-set-default 0
$$
- 生成 grub 配置文件并重启
$$
grub2-mkconfig -o /boot/grub2/grub.cfg reboot now
$$
- 验证
$$
uname -r
$$
升级 calico
kubernetes 上的 calico 一般是使用 daemonset 方式部署,我的集群里,calico 的 daemonset 名字是 calico-node。
直接输出位 yaml 文件,编辑文件里的 image 版本号为最新版本 v3.23.1 。重新创建 daemonset。
clusterrole
还需要修改 名为 calico-node 的 clusterrole ,否则 calico pod 会一直报权限错。
总结
这次奇怪的网络故障,最终原因还是因为 kubesphere 的版本 与 kubernetes 的版本不匹配。所以在生产环境还是要稳字为先,不要冒进使用最新的版本。否则会耽搁很多时间来解决莫名其妙的问题。