現象說明
由於擴容需要,我把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也沒更新,咋就不行了呢? 奇怪。。。。。