Kubernetes Serivce 是一组具有相同 label Pod 集合的抽象(可以简单的理解为集群内的 LB),集群内外的各个服务可以通过 Service 进行互相通信。
Service 和 kube-proxy 在 kubernetes 集群中的工作原理
上图流程:
1:运行在每个 Node 节点的 kube-proxy 会实时的 watch Services 和 Endpoints 对象。
当用户在 kubernetes 集群中创建了含有 label 的 Service 之后,同时会在集群中创建出一个同名的 Endpoints 对象,用于存储该 Service 下的 Pod IP. 它们的关系如下图所示:
2、每个运行在 Node 节点的 kube-proxy 感知到 Services 和 Endpoints 的变化之后,会在各自的 Node 节点设置相关的 iptables 或 IPVS 规则,用于之后用户通过 Service 的 ClusterIP 去访问该 Service 下的服务。
3、当 kube-proxy 把需要的规则设置完成之后,用户便可以在集群内的 Node 或客户端 Pod 上通过 ClusterIP 经过 iptables 或 IPVS 设置的规则进行路由和转发,最终将客户端请求发送到真实的后端 Pod。
Service 类型
ClusterIP
ClusterIP 类型的 Service 是 Kubernetes 集群默认的 Service, 它只能用于集群内部通信。不能用于外部通信。
ClusterIP Service 类型的结构如下图所示:
NodePort
如果你想要在集群外访问集群内部的服务,你可以使用这种类型的 Service。NodePort 类型的 Service 会在集群内部的所有 Node 节点打开一个指定的端口。之后所有的流量直接发送到这个端口之后,就会转发的 Service 去对真实的服务进行访问。
NodePort Service 类型的结构如下图所示:
LoadBalancer
如果我们希望有一个单独的 IP 地址,将请求分配给所有的外部节点IP(比如使用 round robin),我们就可以使用 LoadBalancer 服务,所以它是建立在 NodePort 服务之上的。
LoadBalancer Service 类型的结构如下图所示:
ExternalName
类型为 ExternalName 的service将服务映射到 DNS 名称,而不是使用选择器,例如my-service
或者cassandra
。 您可以使用spec.externalName
参数指定这些服务。
创建 ExternalName 类型的服务的 yaml 如下:
kind: Service apiVersion: v1 metadata: name: service-python spec: ports: - port: 3000 protocol: TCP targetPort: 443 type: ExternalName externalName: remote.server.url.com
Headless
在某些场景中,开发人员可能不想使用Service提供的负载均衡功能,而希望自己来控制负载均衡策略,针对这种情况,kubernetes提供了HeadLiness Service,这类Service不会分配Cluster IP,如果想要访问service,只能通过service的域名进行查询。
创建service-headliness.yaml
apiVersion: v1 kind: Service metadata: name: service-headliness namespace: dev spec: selector: app: nginx-pod clusterIP: None # 将clusterIP设置为None,即可创建headliness Service type: ClusterIP ports: - port: 80 targetPort: 80 # 创建service [root@master ~]# kubectl create -f service-headliness.yaml service/service-headliness created # 获取service, 发现CLUSTER-IP未分配 [root@master ~]# kubectl get svc service-headliness -n dev -o wide NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR service-headliness ClusterIP None <none> 80/TCP 11s app=nginx-pod # 查看service详情 [root@master ~]# kubectl describe svc service-headliness -n dev Name: service-headliness Namespace: dev Labels: <none> Annotations: <none> Selector: app=nginx-pod Type: ClusterIP IP: None Port: <unset> 80/TCP TargetPort: 80/TCP Endpoints: 10.244.1.39:80,10.244.1.40:80,10.244.2.33:80 Session Affinity: None Events: <none> # 查看域名的解析情况 [root@master ~]# kubectl exec -it pc-deployment-66cb59b984-8p84h -n dev /bin/sh / # cat /etc/resolv.conf nameserver 10.96.0.10 search dev.svc.cluster.local svc.cluster.local cluster.local [root@master ~]# dig @10.96.0.10 service-headliness.dev.svc.cluster.local service-headliness.dev.svc.cluster.local. 30 IN A 10.244.1.40 service-headliness.dev.svc.cluster.local. 30 IN A 10.244.1.39 service-headliness.dev.svc.cluster.local. 30 IN A 10.244.2.33