文章目錄
-
- 1.問題說明
- 2.問題分析
- 3.問題排查
- 4.問題結論
- 5.問題解決
1.問題說明
今天早上發現,k8s其中有一個服務映射的 nodePort ,在k8s叢集外的同内網伺服器中,兩次連接配接該服務時,一次可連接配接,一次不能連接配接,即50%的幾率可以正常連接配接,使用telnet測試如下:
// 可正常連接配接
# telnet 192.168.21.202 30001
Trying 192.168.21.202...
Connected to 192.168.21.202.
Escape character is '^]'.
//不可連接配接
# telnet 192.168.21.202 30001
Trying 192.168.21.202...
telnet: connect to address 192.168.21.202: Connection refused
2.問題分析
可通過以下方式,将問題分層,縮小排查範圍:
- k8s叢集外部伺服器不可連接配接,k8s叢集内部伺服器可連接配接:此問題不屬于k8s叢集問題,應該是伺服器之間網絡連接配接問題,需要檢查防火牆及安全組問題
- k8s叢集内部伺服器不可連接配接,服務的pod容器内可連接配接:此問題可能為k8s叢集内問題,需要檢查各元件狀态是否健康,尤其是kube-proxy服務(此服務作用為将svc的請求轉發到pod容器内),同時還有iptables防火牆問題,同時也存在着服務問題,有可能此服務有兩個pod容器,其中一個服務存在問題
- 服務的pod容器内也不可連接配接:此問題應該是服務本身問題,可檢視服務啟動狀态是否啟動,檢視服務日志是否異常
3.問題排查
通過以上問題分析環節,可得出: k8s叢集内部伺服器不可連接配接,服務的pod容器内可連接配接,于是進行了以下排查步驟:
- 檢視存在問題的服務是否存在兩個pod容器及存活狀态
// 問題服務svc狀态
# kubectl get svc -o wide -n fabric-auto |grep fabric-auto-api
fabric-auto-api NodePort 10.1.102.29 <none> 8088:30001/TCP 3h10m app=fabric-auto,role=fabric-auto-api
// 問題服務pod狀态
# kubectl get pod -o wide -n fabric-auto |grep fabric-auto-api
fabric-auto-api-5955b9f9cc-x5mgz 1/1 Running 0 3h10m 10.2.3.175 192.168.21.202 <none> <none>
可通過以上指令檢視到pod容器的狀态,目前該服務僅一個pod容器,且正常啟動
- 檢視master節點各元件是否正常
以下結果表示無問題
# kubectl get cs
NAME STATUS MESSAGE ERROR
scheduler Healthy ok
controller-manager Healthy ok
etcd-1 Healthy {"health":"true"}
etcd-2 Healthy {"health":"true"}
etcd-0 Healthy {"health":"true"}
- 檢視node節點kubelet元件是否正常
可看到kubelet元件的服務狀态為running,服務無問題
//node節點中執行
# systemctl status kubelet
● kubelet.service - kubelet: The Kubernetes Node Agent
Loaded: loaded (/usr/lib/systemd/system/kubelet.service; enabled; vendor preset: disabled)
Drop-In: /usr/lib/systemd/system/kubelet.service.d
└─10-kubeadm.conf
Active: active (running) since Wed 2021-04-14 11:08:32 CST; 3h 10min ago
Docs: https://kubernetes.io/docs/
Main PID: 1208 (kubelet)
......
- 檢視node節點kube-proxy服務是否正常
因為此k8s叢集環境使用kubeadm安裝,是以kube-proxy使用容器啟動,檢視kube-proxy日志時,發現以下報警:
can’t set sysctl net/ipv4/vs/conn_reuse_mode, kernel version must be at least 4.1
//node節點中執行
# docker ps|grep kube-proxy
# docker logs -f k8s_kube-proxy_kube-proxy-qn8gg_kube-system_c189d6f0-b9ab-485b-b31e-bf3fd8f9f32d_0
......
E0203 12:34:19.189547 1 proxier.go:381] can't set sysctl net/ipv4/vs/conn_reuse_mode, kernel version must be at least 4.1
W0203 12:34:19.189665 1 proxier.go:434] IPVS scheduler not specified, use rr by default
......
去 Kubernetes Github 檢視相關 issues,發現有人遇見了相同的問題,經過 issue 中 Kubernetes 維護人員讨論,分析出原因可能為新版 Kubernetes 使用的 IPVS 子產品是比較新的,需要系統核心版本支援,本人使用的是 CentOS 系統,核心版本為 3.10,裡面的 IPVS 子產品比較老舊,缺少新版 Kubernetes IPVS 所需的依賴。
根據該 issue 讨論結果,解決該問題的辦法是,更新核心為新的版本。
centos7 伺服器更新核心版本方法使用此連結:https://blog.csdn.net/cljdsc/article/details/115698143
注意:因更新伺服器核心版本需要重新開機伺服器生效,此操作之前,應确定伺服器可暫時停機,重新開機前需要檢查伺服器啟動的服務項,重新開機後再進行檢查服務是否都已經啟動!!!
核心版本更新後,kube-proxy容器已經不再列印如上報警,但此時依然無法解決端口連接配接不通問題
再次對kube-proxy容器重新開機後,依然未能解決,看來最後的絕招,重新開機已經無法解決問題了。。。。。
- 觀察k8s叢集内端口轉發情況
指令:ipvsadm -Ln
作用:檢視目前ipvs子產品中記錄的連接配接(可用于觀察轉發情況)
# ipvsadm -ln
TCP 172.17.0.1:30001 rr
-> 10.2.3.161:8088 Masq 1 0 0
-> 10.2.3.172:8088 Masq 1 0 0
TCP 192.168.21.202:30336 rr
-> 10.2.3.161:3306 Masq 1 0 0
-> 10.2.3.172:3306 Masq 1 0 0
TCP 172.17.0.1:30303 rr
-> 10.2.3.163:8081 Masq 1 0 0
可以看到nodePort 端口:30001、30336轉發規則下有兩個pod容器,難道這兩個端口各自存在兩個服務嗎,可使用以下指令進行檢視:
//30001端口:僅一個pod容器
# kubectl get svc -o wide --all-namespaces |grep 30001
fabric-auto fabric-auto-api NodePort 10.1.102.29 <none> 8088:30001/TCP 3h19m app=fabric-auto,role=fabric-auto-api
# kubectl get pod -o wide --all-namespaces |grep fabric-auto-api
fabric-auto fabric-auto-api-5955b9f9cc-x5mgz 1/1 Running 0 3h19m 10.2.3.175 192.168.21.202 <none> <none>
//30336端口:僅一個pod容器
# kubectl get svc -o wide --all-namespaces |grep 30336
fabric-auto fabric-auto-mysql NodePort 10.1.76.55 <none> 3306:30336/TCP 3h23m app=fabric-auto,role=fabric-auto-mysql
# kubectl get pod -o wide --all-namespaces |grep fabric-auto-mysql
fabric-auto fabric-auto-mysql-7f7dc8b46b-jfsmt 1/1 Running 0 3h23m 10.2.3.174 192.168.21.202 <none> <none>
這兩個服務一定有問題!!!
- 檢視已有的Pod容器為YAML格式
# kubectl get svc -n fabric-auto fabric-auto-mysql -o yaml
# kubectl get deployment -n fabric-auto fabric-auto-mysql -o yaml
使用如上指令,檢視兩pod容器的deployment及svc的yaml檔案有一段是相同的:
labels:
app: fabric-auto
role: fabric-auto-control
labels 參數用來定義此目前服務的标簽,以便對pod容器進行管理
4.問題結論
由于兩個服務中的svc及pod的yaml檔案中标簽定義一緻,kube-proxy在進行流量分發時,發現有兩組同樣标簽的pod,于是都進行了轉發,是以出現:一次可連接配接,一次不可連接配接的情況。
5.問題解決
删除兩個服務的pod容器及svc
修改兩個服務的deployment及svc的yaml檔案中的labels标簽項,使其不一緻即可
重新建立服務的svc及pod,問題解決