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就是用于解决这些问题的核心组件。