由於Pod的IP是不固定的,因此Kubernetes須要Service,除此以外它還能夠在多個Pod間負載均衡
Service的訪問入口,實際上是宿主機的kube-proxy生成的iptables規則 ,及kube-dns生成的DNS記錄node
Service經過label標籤選中Pod,被選中的的Pod稱爲Service的Endpoints
示例以下nginx
# 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列表裏後端
咱們再查看servcieapi
# 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.3三、目的端口是80的IP包,都會跳轉到KUBE-SVC-NWV5X2332I4OT4T3的iptables鏈處理
KUBE-SVC-NWV5X2332I4OT4T3是一組集合,以下app
-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/三、1/2和1負載均衡
當訪問Service的VIP的IP包通過上述iptables處理後,就變成了訪問具體某一個後端Pod的IP包了,這些Endpoints對應的規則,是kube-proxy經過監聽Pod的變化事件,在宿主機上生成並的維護dom
示例yamltcp
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,只能由宿主機轉發
示例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地址代理給負載均衡後端
示例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
在一個 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
檢查這個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是否正常