现象说明
由于扩容需要,我把k8s的一台服务器重启了。然后跑在k8s上的项目访问不了了。
我做了如下的一些尝试:
1. 确认k8s集群是正常的。
判断节点状态
kubectl get nodes -o wide
发现有的node 显示 not ready。通过重启节点上的kubelet服务等方式,使得节点状态转换为ready
# 不正常的node 上重启服务 systemctl restart docker systemctl restart kubelet
查看kubelet日志,看有无错误
# 各个node上, 查看状态 systemctl status kubelet # 查看日志 journalctl -u kubelet -f
如果有日志错误,就查询相应的解决方法
2. 判断服务状态
# 查看pod状态 kubectl get pods -n <namespace_name> # 查看pod描述 kubectl describe pod -n <namespace_name> <pod_name> # 查看pod日志 kubectl logs -n <namespace_name> <pod_name>
确定所有的pod都启动正常,没有报错
3. 确定是否是请求转发的问题
由于istio不好定位问题,因为一方面我对它不熟,另一方面多了好多流量转发的过程,不好定位问题所在。我直接把系统的端口通过k8s暴露出来。
暴露服务的配置文件expose.yml 如下:
apiVersion: v1 kind: Service metadata: name: myapp # 这里修改你自己的命名空间 namespace: my_namespace spec: selector: # 这里修改为你自己的选择器,选择需要暴露的服务 app: xxx type: NodePort ports: - name: http # 这里修改为你自己的服务端口和对外暴露的端口 port: 80 targetPort: 80 protocol: TCP nodePort: 8080
执行命令,部署到k8s上
# 修改下面命令中的文件名为你自己的文件 kubectl apply -f expose.yml
然后可以在外部访问 8080端口,发现是能够访问该服务的。 那就确认了是istio的问题。
4. 确认 istio的服务正常。
istio 正常情况下也是需要部署一些pod、service、crd等,到k8s上的。最可能出问题的就是pod和service
确认istio 的pod正常启动 这里都在istio-system命名空间中
# 查看pod状态 kubectl get pods -n istio-system # 查看pod描述 kubectl describe pod -n istio-system <pod_name> # 查看pod日志 kubectl logs -n istio-system <pod_name>
我这里有两个pod istio-ingressgatewway是负责进入的流量转发的, istiod是控制平面的服务
开始的时候,我这两个pod都启动不了,一直是creating的状态。描述中的报错是
MountVolume.SetUp failed for volume "istio-token" : failed to fetch token: the server could not find the requested resource
找了好久,没有好的解决方法。有的人说是和第一方和第三方认证啥的相关。感觉不是很靠谱的样子,毕竟istio官网,也没说这个事情。
后来灵光一闪,是不是istio版本的问题?
找到的问题1: istio版本问题
突然想到我之前有两个版本的istio安装过。经过确认是istio版本和k8s版本不匹配的问题。我卸载了istio,然后安装了正确的版本,istio的两个pod启动起来了。
为什么会这样?
我就重启了一下服务器,没有重新安装istio,为什么之前可以,现在istio启动不了?
我印象中我用过 1.4 和1.5两个版本的istio。
最开始安装的1.4版本是正确的,正常启动的。
然后为了项目能够一键启动,项目的启动文件里,配置了istio的安装脚本,这里配置了1.5的版本
后来也根据安装脚本使用kubectl apply -f xxx.yaml 更新过项目,istio 也更新了,没事
服务器重启了,istio启动失败
我认为这可能是k8s的一个bug,就是1.4 版本安装好之后,
kubectl apply -f install-1.4.yml
再安装1.5
kubectl apply -f install-1.5.yml
并不会杀掉旧版本istio的pod,istio正常提供转发服务。服务器重新启动后,会根据install-1.5.yml启动1.5 版本的istio,版本不匹配这个时候就出错了。
之前也遇到过类似的事情。
给我的启发是,k8s中的服务yml配置有更新的时候,最好kubectl delete 之后,再 kubectl apply -f xxx
找到的问题2:
istio的pod都启动了,但是还是无法访问我们的项目。 我又重新确认了一下istio的gateway、 virtual service、service的配置情况,没有问题。
之前是使用脚本批量执行kubectl apply 的。为了好定位问题,我手动一条一条执行,发现gateway.yml部署的时候,报错,
Error from server: error when creating "gateway.yaml": admission webhook "validation.istio.io" denied the request: configuration is invalid: port name must be set: number:80 protocol:"HTTP" Error from server: error when creating "gateway.yaml": admission webhook "validation.istio.io" denied the request: configuration is invalid: port name must be set: number:8080 protocol:"HTTP"
这个报错信息很明确了,就是配置文件错了,少了一个name没有配置。其实这个name无所谓,随便写个名字就行。
修改保存,然后执行
kubectl apply -f gateway.yml
部署成功。
这个问题,我就没想明白是怎么回事了,之前的配置文件都是正常部署的,istio也没更新,k8s也没更新,咋就不行了呢? 奇怪。。。。。