service
•防止Pod失聯
•定義一組Pod的訪問策略
•支持ClusterIP,NodePort以及LoadBalancer三種類型
•Service的底層實現主要有iptables和ipvs二種網絡模式
pod與service的關系:
•通過label-selector相關聯
•通過Service實現Pod的負載均衡(TCP/UDP 4層)
每個 Node 運行一個 kube-proxy
進程。kube-proxy
負責為 Service
實現了一種 VIP(虛擬 IP)的形式
kube-proxy 這個組件始終監視着apiserver中有關service的變動信息,獲取任何一個與service資源相關的變動狀態,通過watch監視,一旦有service資源相關的變動和創建,kube-proxy都要轉換為當前節點上的能夠實現資源調度規則(例如:iptables、ipvs)
service代理模式
iptables代理模式:
客戶端IP請求時,直接請求本地內核service ip,根據iptables的規則直接將請求轉發到到各pod上,因為使用iptable NAT來完成轉發,也存在不可忽視的性能損耗。另外,如果集群中存在上萬的Service/Endpoint,那么Node上的iptables rules將會非常龐大,性能還會再打折扣。
ipvs代理模式:
客戶端IP請求時到達內核空間時,根據ipvs的規則直接分發到各pod上。kube-proxy會監視Kubernetes Service
對象和Endpoints
,調用netlink
接口以相應地創建ipvs規則並定期與Kubernetes Service
對象和Endpoints
對象同步ipvs規則,以確保ipvs狀態與期望一致。訪問服務時,流量將被重定向到其中一個后端Pod。
service類型
ClusterIP
:通過集群的內部 IP 暴露服務,選擇該值,服務只能夠在集群內部可以訪問,這也是默認的ServiceType
。NodePort
:通過每個 Node 上的 IP 和靜態端口(NodePort
)暴露服務。NodePort
服務會路由到ClusterIP
服務,這個ClusterIP
服務會自動創建。通過請求<NodeIP>:<NodePort>
,可以從集群的外部訪問一個NodePort
服務。LoadBalancer
:使用雲提供商的負載均衡器,可以向外部暴露服務。外部的負載均衡器可以路由到NodePort
服務和ClusterIP
服務。
ClusterIP
[root@k8s-master1 nginx]# vim nginx-service.yaml apiVersion: v1 kind: Service metadata: name: nginx-service labels: app: nginx spec: type: ClusterIP ports: - port: 80 targetPort: 80 selector: app: nginx [root@k8s-master1 nginx]# kubectl apply -f nginx-service.yaml service/nginx-service created [root@k8s-master1 nginx]# kubectl get svc NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kubernetes ClusterIP 10.0.0.1 <none> 443/TCP 6d15h nginx-service ClusterIP 10.0.0.6 <none> 80/TCP 14s
service不會直接到pod,service是直接到endpoint資源,就是地址加端口,再由endpoint再關聯到pod。 [root@k8s-master1 nginx]# kubectl get pod -l app=nginx NAME READY STATUS RESTARTS AGE nginx-deployment-5fc86c987f-jdpkv 1/1 Running 0 21m nginx-deployment-5fc86c987f-scns6 1/1 Running 0 21m nginx-deployment-5fc86c987f-wwvlx 1/1 Running 0 21m [root@k8s-master1 nginx]# kubectl get ep NAME ENDPOINTS AGE kubernetes 192.168.0.123:6443,192.168.0.124:6443 6d15h nginx-service 172.17.32.3:80,172.17.73.3:80,172.17.73.4:80 76s
service只要創建完,就會在dns中添加一個資源記錄進行解析,添加完成即可進行解析。
[root@k8s-master1 nginx]# kubectl run -it --image=busybox:1.28.4 --rm --restart=Never sh
If you don't see a command prompt, try pressing enter.
/ # nslookup nginx-service Server: 10.0.0.2 Address 1: 10.0.0.2 kube-dns.kube-system.svc.cluster.local Name: nginx-service Address 1: 10.0.0.6 nginx-service.default.svc.cluster.local
NodePort
[root@k8s-master1 ~]# kubectl get pod --show-labels NAME READY STATUS RESTARTS AGE LABELS myapp-9b4987d5-hk5n9 1/1 Running 0 82s pod-template-hash=9b4987d5,run=myapp myapp-9b4987d5-ngvbk 1/1 Running 0 82s pod-template-hash=9b4987d5,run=myapp myapp-9b4987d5-r7q49 1/1 Running 0 82s pod-template-hash=9b4987d5,run=myapp [root@k8s-master1 ~]# vim myapp-service.yaml apiVersion: v1 kind: Service metadata: name: myapp namespace: default spec: selector: app: myapp release: canary type: NodePort ports: - port: 80 targetPort: 80 nodePort: 37695 [root@k8s-master1 ~]# kubectl create -f myapp-service.yaml service/myapp created [root@k8s-master1 ~]# kubectl get svc NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kubernetes ClusterIP 10.0.0.1 <none> 443/TCP 6d16h myapp NodePort 10.0.0.214 <none> 80:37695/TCP 8m14s
通過NodePort方式已經實現了從集群外部端口進行訪問 [root@k8s-master1 ~]# while true;do curl http://192.168.0.125:37695/hostname.html;sleep 1;done myapp-9b4987d5-ngvbk myapp-9b4987d5-hk5n9 myapp-9b4987d5-r7q49 myapp-9b4987d5-ngvbk myapp-9b4987d5-hk5n9 myapp-9b4987d5-r7q49 myapp-9b4987d5-ngvbk
會話保持
[root@k8s-master1 ~]# vim myapp-service.yaml apiVersion: v1 kind: Service metadata: name: myapp namespace: default spec: selector: app: myapp release: canary sessionAffinity: ClientIP type: NodePort ports: - port: 80 targetPort: 80 nodePort: 37695 [root@k8s-master1 ~]# kubectl create -f myapp-service.yaml service/myapp created [root@k8s-master1 ~]# while true;do curl http://192.168.0.125:37695/hostname.html;sleep 1;done myapp-9b4987d5-hk5n9 myapp-9b4987d5-hk5n9 myapp-9b4987d5-hk5n9
Headless Service
有時不需要或不想要負載均衡,以及單獨的 Service IP。 遇到這種情況,可以通過指定 Cluster IP(spec.clusterIP
)的值為 "None"
來創建 Headless
Service。
這個選項允許開發人員自由尋找他們自己的方式,從而降低與 Kubernetes 系統的耦合性。 應用仍然可以使用一種自注冊的模式和適配器,對其它需要發現機制的系統能夠很容易地基於這個 API 來構建。
對這類 Service
並不會分配 Cluster IP,kube-proxy 不會處理它們,而且平台也不會為它們進行負載均衡和路由。 DNS 如何實現自動配置,依賴於 Service
是否定義了 selector。
headless service做dns解析是直接解析到pod的,而servcie是解析到ClusterIP的
[root@k8s-master1 ~]# vim myapp.svc.yaml apiVersion: v1 kind: Service metadata: name: myapp namespace: default spec: selector: app: myapp release: canary clusterIP: "None" ports: - port: 80 targetPort: 80 [root@k8s-master1 ~]# kubectl apply -f myapp-svc.yaml service/myapp created [root@k8s-master1 ~]# kubectl get svc NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kubernetes ClusterIP 10.0.0.1 <none> 443/TCP 6d17h myapp ClusterIP None <none> 80/TCP 6m27s