天天看點

k8s叢集中nodePort端口不可連接配接問題排查

文章目錄

    • 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,問題解決

繼續閱讀