Service是Kubernetes的核心概念,經過建立Service,能夠爲一組具備相同功能的容器應用提供一個統一的入口地址,而且將請求負載分發到後端的各個容器應用上。html
Service從邏輯上表明瞭一組Pod,具體是哪組Pod則是由label來挑選的前端
在Kubernetes中Service的Cluster IP實現數據報文請求的轉發,都離不開node上部署的重要組件 kube-proxynode
kube-proxy做用nginx
apiVersion: v1 kind: Service metadata: name: nginx-svc labels: app: nginx spec: type: ClusterIP ports: - port: 80 targetPort: 80 selector: app: nginx
根據建立Service的type不一樣 能夠分爲如下幾種類型web
ClusterIP
默認方式,根據是否生成ClusterIP又能夠分爲普通Service和Headless Service兩類docker
此方式僅用於集羣內部之間實現通訊的後端
NodePortapi
NodePort模式除了使用cluster ip外,也將service的port映射到每一個node的一個指定內部port上,映射的每一個node的內部port都同樣。能夠經過訪問Node節點的IP實現外部通訊瀏覽器
LoadBalancer
要配合支持公有云負載均衡使用好比GCE、AWS。其實也是NodePort,只不過會把
ExternalName
外部IP;若是集羣外部須要有一個服務須要咱們進行訪問;那麼就須要在service中指定外部的IP讓service與外部的那個服務進行訪問;那麼接下的集羣內部到外部那個數據包走向即是:數據包先到service而後由service交給外部那個服務;回來的數據包是:交給node node交給service service交給Pod
下面說下生產經常使用的類型定義以及使用
定義一個web應用
apiVersion: apps/v1 kind: Deployment metadata: name: web-deploy namespace: default spec: replicas: 2 selector: matchLabels: app: myappnginx release: stable template: metadata: labels: app: myappnginx release: stable spec: containers: - name: nginxweb image: nginx:1.14-alpine imagePullPolicy: IfNotPresent
建立service資源基於ClusterIP類型
apiVersion: v1 kind: Service metadata: name: webservice #service名字;也就是後面驗證基於主機名訪問的名字 namespace: default #名稱空間要與剛纔建立的Pod的名稱空間一致,service資源也是基於namespace隔離的 spec: selector: #標籤選擇器很重要決定是要關聯某個符合標籤的Pod app: myappnginx #標籤要與剛纔定義Pod的標籤一致;由於service是經過標籤與Pod關聯的 release: stable type: ClusterIP #類型是ClusterIP ports: #暴露的端口設置 - port: 88 #service暴露的端口 targetPort: 80 #容器自己暴露的端口,和dockerfile中的expose意思同樣
查看service狀態
[root@master replicaset]# kubectl get svc -o wide NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 3d9h <none> webservice ClusterIP 10.102.99.133 <none> 88/TCP 13s app=myappnginx,release=stable [root@master replicaset]# kubectl describe svc webservice Name: webservice Namespace: default Labels: <none> Annotations: kubectl.kubernetes.io/last-applied-configuration: {"apiVersion":"v1","kind":"Service","metadata":{"annotations":{},"name":"webservice","namespace":"default"},"spec":{"ports":[{"port":88,"t... Selector: app=myappnginx,release=stable Type: ClusterIP IP: 10.102.99.133 Port: <unset> 88/TCP TargetPort: 80/TCP Endpoints: 10.244.1.27:80,10.244.2.27:80 Session Affinity: None Events: <none>
鏈接一個客戶端Pod進行測試
[root@master replicaset]# kubectl exec -it web-deploy-75bfb496f9-fm29g -- /bin/sh / # wget -O - webservice:88 #基於coredns進行解析的 Connecting to webservice:88 (10.102.99.133:88) <!DOCTYPE html> <html> <head> <title>Welcome to nginx!</title> <style>
無頭IP只能使用CluserIP類型就是沒有clusterip 而是將解析的IP 解析到後端的Pod之上
該服務不會分配Cluster IP,也不經過kube-proxy作反向代理和負載均衡。而是經過DNS提供穩定的網絡ID來訪問,DNS會將headless service的後端直接解析爲podIP列表。主要供StatefulSet使用
[root@master replicaset]# cat svc.yaml apiVersion: v1 kind: Service metadata: name: webservice namespace: default spec: selector: app: myappnginx release: stable clusterIP: None 定義cluserIP爲空 ports: - port: 88 targetPort: 80 [root@master replicaset]# kubectl get svc -o wide NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 3d10h <none> webservice ClusterIP None <none> 88/TCP 7s app=myappnginx,release=stable [root@master replicaset]# kubectl exec -it web-deploy-75bfb496f9-fm29g -- /bin/sh / # cat /etc/resolv.conf nameserver 10.96.0.10 search default.svc.cluster.local svc.cluster.local cluster.local options ndots:5 / # nslookup webservice nslookup: can't resolve '(null)': Name does not resolve Name: webservice Address 1: 10.244.2.27 10-244-2-27.webservice.default.svc.cluster.local Address 2: 10.244.1.27 web-deploy-75bfb496f9-fm29g / #
[root@k8s-master01 daem]# cat deploy.yaml apiVersion: apps/v1 kind: Deployment metadata: namespace: default name: nginxapp labels: app: nginx-deploy spec: replicas: 2 selector: matchLabels: app: mynginx template: metadata: labels: app: mynginx spec: containers: - name: nginxweb1 image: nginx:1.15-alpine 您在 /var/spool/mail/root 中有新郵件 [root@k8s-master01 daem]# cat svc.yaml apiVersion: v1 kind: Service metadata: name: nginx-svc labels: app: nginx-svc spec: ports: - name: http port: 80 #service暴露的端口,能夠基於內部集羣訪問 protocol: TCP nodePort: 30001 #node節點的映射端口 能夠經過外部訪問 targetPort: 80 selector: app: mynginx sessionAffinity: None type: NodePort
能夠基於內部集羣訪問
[root@k8s-master01 daem]# kubectl get svc NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 8d nginx-svc NodePort 10.99.184.91 <none> 80:30001/TCP 5s 您在 /var/spool/mail/root 中有新郵件 [root@k8s-master01 daem]# curl 10.99.184.91 <!DOCTYPE html> <html> <head> <title>Welcome to nginx!</title> <style> body { width: 35em; margin: 0 auto; font-family: Tahoma, Verdana, Arial, sans-serif; } </style> </head> <body> <h1>Welcome to nginx!</h1> <p>If you see this page, the nginx web server is successfully installed and working. Further configuration is required.</p> <p>For online documentation and support please refer to <a href="http://nginx.org/">nginx.org</a>.<br/> Commercial support is available at <a href="http://nginx.com/">nginx.com</a>.</p> <p><em>Thank you for using nginx.</em></p> </body> </html> [root@k8s-master01 daem]#
外部瀏覽器訪問
apiVersion: v1 kind: Service metadata: name: webservice namespace: default spec: selector: app: myappnginx release: stable sessionAffinity: ClientIP 未來自贊成客戶端的請求調度到後端的同一個Pod上 type: NodePort ports: - port: 88 nodePort: 30001 targetPort: 80
直接經過Pod的IP地址和端口號能夠訪問到容器應用內的服務,可是Pod的IP地址是不可靠的,例如當Pod所在的Node發生故障時,Pod將被Kubernetes從新調度到另外一個Node,Pod的IP地址將發生變化。更重要的是,若是容器應用自己是分佈式的部署方式,經過多個實例共同提供服務,就須要在這些實例的前端設置一個負載均衡器來實現請求的分發。Kubernetes中的Service就是用於解決這些問題的核心組件。