PrefacePod已经成功运行,但是有两个问题。一是集群外无法直接访问这些Pod,二是Pod故障自愈后,IP会发生变化。如何解决这两个问题,这里有一个很重要的概念:服务更新历史20200625-初稿-左成礼原文地址-https://blog.zuolinux.com/2020/06/25/about-service.html服务意义和特性为一组Pod(工作在TCP/UDP4层)提供负载均衡,防止Pod因IP更换而丢失,即服务发现通过标签选择器与PodService关联工作原理Service由kube-proxy实现组件加iptables/LVS。说白了就是通过kube-proxy生成一堆iptables规则,通过iptables规则转发数据。iptables转发:K8S默认转发设置。后端Pod的选择是随机的。当Pod没有响应时,连接就会失败,没有健康检查机制。需要pod就绪探测器以确保访问健康的pod。当集群规模达到数万个服务时,iptables的转发效率会明显降低。LVS转发:基于内核哈希表,性能强大,网络吞吐量更高。适用于pod大、转发规则多的大型集群。LVS支持更多的Pod负载均衡调度算法。LVS只负责负载均衡和代理功能。其余的包过滤、SNAT等操作仍然需要iptables处理,但是这些操作规则的数量不会因为Pod数量的增加而增加。也称为IPVS。Service默认工作方式创建Pod和默认Service来测试默认工作状态。首先创建3个Podcatsnginx.yamlapiVersion:apps/v1kind:Deploymentmetadata:name:nginx-deploymentspec:selector:matchLabels:app:nginxreplicas:3template:metadata:labels:app:nginxspec:containers:-name:nginximage:nginxports:-containerPort:80创建一个名为nginx-servicecatnginx-service.yamlapiVersion:v1kind:Servicemetadata:name:nginx-servicespec:selector:app:nginxports:-port:80targetPort:80protocol:TCPport:的默认服务类型80是集群内部的服务VIP端口。targetPort:80是Pod的端口。创建kubectlapply-fnginx.yamlkubectlapply-fnginx-service.yaml查看运行状态[root@master01~]#kubectlgetpod-owideNAMEREADYSTATUSRESTARTSAGEIPNODENOMINATEDNODEREADINESSGATESnginx-deployment-d46f5678b-cldf41/1运行021m192.10.137.153work03<无><无>nginx-部署-d46f5678b-lnxh91/1运行021m192.10.205.252work01<无><无>nginx-deployment-d46f5678b-th8xq1/1运行021m192.10.75.89work02<无><无>[root@master01~]#kubectgetserviceNAMETYPECLUSTER-IPEXTERNAL-IPPORT(S)AGEnginex-serviceClusterIP192.20.150.2680/TCP13m查看名为nginx-service的服务成功挂载的后端Pod[root@master01~]#kubectlgetendpointsnginx-serviceNAMEENDPOINTSAGEnginex-service192.10.137.153:80,192.10.205.252:80,192.10.75.89:8014m可以看到我们创建的名为nginx-service的服务在后端挂载了3个Pod,并写入3个Pod的内容,返回自己的访问Pod时的主机名kubectlexecnginx-deployment-d46f5678b-cldf4--sh-c'echo$(hostname)>/usr/share/nginx/html/index.html';kubectlexecnginx-deployment-d46f5678b-lnxh9--sh-c'echo$(主机名)>/usr/share/nginx/html/index.html';kubectlexecnginx-deployment-d46f5678b-th8xq--sh-c'echo$(hostname)>/usr/share/nginx/html/index.html';我们访问ServiceIP看看[root@master01~]#curl192.20.150.26nginx-deployment-d46f5678b-th8xq[root@master01~]#curl192.20.150.26nginx-deployment-d46f5678b-cldf4[root@master01~]#curl192.20.150.26nginx-d4hb96可以看出Service成功将请求代理到后端的一组Pod,并进行了流量分发。这是Service默认的工作类型,只能在集群所属节点上访问,离开集群后无法访问。这种类型的工作称为ClusterIP。Service对外提供服务的三种方式上一节可以看到,Service默认是不提供集群外服务的,那么如何在集群外访问它,有3种方案。ExternalIPs方式Service可以配置externalIPs,IP为集群中工作节点的主机IP。apiVersion:v1kind:服务。.....规格:......externalIPs:-192.168.10.16-192.168.10.17在192.168.10.16/17上执行ss-lntp以查看服务定义的公开端口。从集群外部访问192.168.10.16/17上Service暴露的端口。以NodePort方式修改nginx-service.yaml,添加一行:NodePortcatnginx-service.yamlapiVersion:v1kind:Servicemetadata:name:nginx-servicespec:type:NodePortselector:app:nginxports:-port:80targetPort:80protocol:TCPCreateservicekubectlapply-fnginx-service.yaml查看运行状态[root@master01~]#kubectlgetserviceNAMETYPECLUSTER-IPEXTERNAL-IPPORT(S)AGEnginex-serviceNodePort192.20.167.22180:30913/TCP13m参数PORT(S)80:30913/TCP,其中30913为集群对外访问的端口。可以访问任何物理主机的ip:30913来访问Pod。30913是K8S从固定范围30000-32767中选择的,固定端口也可以通过参数nodePort指定。可选范围可以通过kube-apiserver的--service-node-port-range参数修改。[root@master01~]#ss-nltp|grep30913LISTEN0128*:30913*:*可以看出主机上监听了30913端口。在没有运行K8S集群的机器上测试访问K8S主机[root@192-168-10-18~]#curl192.168.10.12:30913nginx-deployment-d46f5678b-2pmts[root@192-168-10-18~]#curl192.168.10.12:30913nginx-deployment-d46f5678b-zv8m4[root@192-168-10-18~]#curl192.168.10.12:30913nginx-deployment-d46f5678b-2pmts可以看到Pod可以访问成功来自群集内容之外,并且是随机分配的。原理kube-proxy在宿主机上创建iptables规则,访问宿主机IP:30913会转发到ServiceIP,然后Service会通过自己的iptables规则分发到PodLoadBalancer方式NodePort方式,如果要正式提供服务在外部,我们需要在集群外创建一个高可用的负载均衡器,将流量转发到宿主机开放的端口。如果宿主机开放端口发生变化,我们需要手动修改前端负载均衡器。LoadBalancerforPublicCloud自动执行此过程。LoadBalancer此方法适用于公有云。提交类型为LoadBalancer的创建服务申请后,公有云会帮我们创建一个负载均衡器,直接把请求分发给Pod。同时,当PodIP发生变化时,它会在负载均衡器上自动更新。其他:HeadlessService可以通过指定spec.clusterIP的值为“None”来创建HeadlessService。HeadlessService不会分配ClusterIP,kube-proxy不会处理,平台不会负载均衡和路由。定义了带有选择器的无头服务。Endpoint控制器会在API中创建Endpoints记录,并修改DNS配置以返回A记录。通过这个地址,请求可以直接到达Service的后端Pod。结束语Service为IP信息发生变化的Pod提供服务发现、负载均衡等管理功能,同时提供对外访问能力,使外部用户可以稳定地访问运行在集群内部的Pod提供的服务。上面提到的三种工作方式存在以下问题:ClusterIP方式默认工作在集群内部,可以通过参数externalIPs指定暴露哪个端口,但是无法进行7层URL跳转等控制NodePort方式,所有节点都会暴露这个端口,但是一个端口只能对应一个业务,适合业务比较少的环境或者测试环境。业务多时,无法有效管理。LoadBalance方式只适用于已有的公有云平台,不能用于自建集群。这些问题需要额外的成本,不能直接应用于生产环境。如果要提供给自建集群的生产环境,需要在Service前面添加一个IngressController。联系我微信公众号:zuolinux_com