Kubernetes的Service運行原理


一、為什么Servcie能定位到Pod

因為Pod的IP是不固定的,所以Kubernetes需要Service,除此之外它還可以在多個Pod間負載均衡
Service的訪問入口,其實是宿主機的kube-proxy生成的iptables規則 ,及kube-dns生成的DNS記錄

Service通過label標簽選中Pod,被選中的的Pod稱為Service的Endpoints
示例如下

# kubectl get ep hostnames
NAME ENDPOINTS AGE
hostnames 10.244.0.241:9376,10.244.0.242:9376,10.244.0.243:9376 20m

可以看到,當我們訪問hostnames這個service時,會被定位到10.244.0.241:9376,10.244.0.242:9376,10.244.0.243:9376
注意:只有處於Running狀態,且readlinessProbe檢查通過的Pod,才會出現在Endpoints列表里

我們再查看servcie

# kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
hostnames ClusterIP 10.111.15.33 <none> 80/TCP 23m

service列表的VIP(ClusterIP),是設置了一個固定的入口地址,並沒有真正的網絡設備,ping是沒有響應的
通過訪問10.111.15.33,就可以訪問到它所代理的Pod了
Service的實現原理是由kube-proxy組件,加上iptables來共同實現的,當提交service后,會創建這樣一條iptables規則

-A KUBE-SERVICES -d 10.111.15.33/32 -p tcp -m comment --comment "default/hostnames: cluster IP" -m tcp --dport 80 -j KUBE-SVC-NWV5X2332I4OT4T3

iptables規則 的含義是:凡是上的地址是10.111.15.33、目的端口是80的IP包,都會跳轉到KUBE-SVC-NWV5X2332I4OT4T3的iptables鏈處理
KUBE-SVC-NWV5X2332I4OT4T3是一組集合,如下

-A KUBE-SVC-NWV5X2332I4OT4T3 -m comment --comment "default/hostnames:" -m statistic --mode random --probability 0.33332999982 -j KUBE-SEP-WNBA2IHDGP2BOBGZ
-A KUBE-SVC-NWV5X2332I4OT4T3 -m comment --comment "default/hostnames:" -m statistic --mode random --probability 0.50000000000 -j KUBE-SEP-X3P2623AGDH6CDF3
-A KUBE-SVC-NWV5X2332I4OT4T3 -m comment --comment "default/hostnames:" -j KUBE-SEP-57KPRZ3JQVENLNBR

這是一組隨機模式的iptables鏈,這三條鏈是DNAT規則,三條鏈指向的最終目的地是Service代理的三個Pod
iptables規則的匹配是從上到下逐條進行的,為了讓每條概率都相同,probability分別被設置成了1/3、1/2和1

當訪問Service的VIP的IP包經過上述iptables處理后,就變成了訪問具體某一個后端Pod的IP包了,這些Endpoints對應的規則,是kube-proxy通過監聽Pod的變化事件,在宿主機上生成並的維護

二、Servcie在外部訪問的三種方式

1. nodePort模式

示例yaml

apiVersion: v1
kind: Service
metadata:
  name: my-nginx
  labels:
    run: my-nginx
spec:
  type: NodePort
  ports:
  - nodePort: 8080
    targetPort: 80
    protocol: TCP
    name: http
  - nodePort: 443
    protocol: TCP
    name: https
  selector:
    run: my-nginx

訪問方式:<任何一台宿主機的IP地址>:8080

宿主機上沒有任何一個代理的Pod存在,不能直接訪問通過IP訪問Pod,只能由宿主機轉發

2.LoadBalancer

示例yaml

kind: Service
apiVersion: v1
metadata:
  name: example-service
spec:
  ports:
  - port: 8765
    targetPort: 9376
  selector:
    app: example
  type: LoadBalancer

K8S使用了一個CloudProvier轉接層,跟公有雲api對拉,當LoadBalancer的Service被提交后,
K8S會在公有雲創建一個負載均衡服務,把代理的Pod地址代理給負載均衡后端

3.ExternalName

示例yaml

kind: Service
apiVersion: v1
metadata:
  name: my-service
spec:
  type: ExternalName
  externalName: my.database.example.com

不需要label選擇,相當於在kube-dns里添加了一條CNAME記錄
訪問my-servcie.default.svc.cluster.locl和訪問my.database.example.com一樣

另外,還允許配置公有IP地址

kind: Service
apiVersion: v1
metadata:
  name: my-service
spec:
  selector:
    app: MyApp
  ports:
  - name: http
    protocol: TCP
    port: 80
    targetPort: 9376
  externalIPs:
  - 80.11.12.10

三、解決問題思路

1.DNS無法訪問Service

在一個 Pod 里執行nslookup排查

$ nslookup kubernetes.default
Server:    10.0.0.10
Address 1: 10.0.0.10 kube-dns.kube-system.svc.cluster.local

Name:      kubernetes.default
Address 1: 10.0.0.1 kubernetes.default.svc.cluster.local

2. Service無法通過ClusterIP訪問時

檢查這個Service的Endpoints

kubectl get endpoints hostnames
NAME        ENDPOINTS
hostnames   10.244.0.5:9376,10.244.0.6:9376,10.244.0.7:9376

如果Pod的readniessProbe沒通過,不會出現在Endpoints列表
如果Endpoints正常,再確認kube-proxy和宿主機的iptables是否正常


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM