企业🤖AI智能体构建引擎,智能编排和调试,一键部署,支持知识库和私有化部署方案 广告
#### 根据 type 类型分为 4 种模式 **1.ClusterIP** `ClusterIP`:这是 kubernetes 的默认方式。这其中根据是否会生成 ClusterIP 又分为普通 Service 和 Headless Service。 -`普通 Service`:创建的 Service 会分配一个集群内部可访问的固定虚拟 IP,这是最常使用的方式。 -`Headless Service`:创建的 Service 不会分配固定的虚拟 IP,同样也不会通过 kube-proxy 做反向代理和负载均衡,主要通过 DNS 提供稳定的网络 ID 进行访问,通常用于 StatefulSet 中。 **2.NodePort** `NodePort`:使用 ClusterIP,并且将 Service 的 port 端口映射到集群中每个 Node 节点的相同端口 port,这样在集群外部访问服务可以直接使用 nodeIP:nodePort 进行访问。 **3.LoadBalancer** `LoadBalancer`:在 NodePort 的基础上(也就是拥有 ClusterIP 和 nodePort),还会向所处的公有云申请负载均衡器 LB(负载均衡器的后端直接映射到各 Node 节点的 nodePort 上),这样就实现了通过外部的负载均衡器访问服务。 **4.ExternalName** `ExternalName`:这是 Service 的一种特例形式。主要用于解决运行在集群外部的服务问题,这种方式下会返回外部服务的别名来为集群内部提供服务。上述提到的 3 种模式主要依赖于 kube-proxy,而这种模式依赖于`kube-dns`的层级。 这里可能理解起来比较抽象,举一个例子进行说明,请看下面的 YAML 文件: ~~~yaml kind: Service apiVersion: v1 metadata: name: my-service namespace: test spec: type: ExternalName externalName: www.shiyanlou.example.com ~~~ 当使用上面的 YAML 文件创建服务以后,DNS 服务会给`<service-name>.<namespace>.svc.cluster.local`(在这里就为`my-service.test.svc.cluster.local`)创建一个 CNAME 记录,并向其中写入`www.shiyanlou.example.com`。 当查询服务`my-service.test.svc.cluster.local`时,集群中的 DNS 服务就会返回映射的`www.shiyanlou.example.com`。 #### Service 涉及到的 3 种 Port Service 服务涉及到的 Port 概念比较多,我们这里做一个概念上的区分: * `port`:指 Service 暴露在 ClusterIP 上的端口 port,在 kubernetes 集群内部就是通过`ClusterIP:port`访问服务的。 * `nodePort`:指节点 Node 开放的端口,从 kubernetes 集群外部可以通过`nodeIP:nodePort`访问服务。nodePort 的范围是 30000-32767,设置端口时不能够与已经在使用的有冲突。 * `targetPort`:指 Pod 开放的端口,外部访问的请求经过 port 端口和 nodePort 端口,以及 kube-proxy 服务最终转发到后端 Pod 的 targetPort 端口,然后进入到 Pod 中的容器内进行处理。 #### 4 种 IP Service 服务涉及到的 IP 概念也比较多,我们这里同样做一个概念上的区分: * `ClusterIP`:这是一个虚拟地址(VIP),没有实际的网络设备承载这个地址,它的底层实现原理是依靠 kube-proxy 通过 iptables 规则重定向到 Node 节点的端口上,然后再负载均衡到后端 Pod。具体过程为:kube-proxy 发现新 Service,在 Node 节点上打开一个任意的 nodePort 端口,创建对应的 iptables 规则或是 IPVS 规则,重定向 Service 的`ClusterIP:port`到新建的 nodePort 端口上,然后开始处理关于新 Service 的连接访问。 * `NodeIP`:上面提到的`ClusterIP`由于是虚拟的,只能用于 kubernetes 集群内部的访问。当集群需要提供外部服务,这时就需要为服务提供公共 IP,通过定义 YAML 文件指定 Service 类型`spec.type=NodePort`,然后集群会在所有 Node 节点上开放一个指定的 nodePort,集群外部通过`nodeIP:nodePort`就可以访问服务了。 * `PodIP`:当每个新 Pod 创建时,集群都会先使用`gcr.io/google_containers/pause`镜像创建一个容器,然后再创建其它要求的容器。在 Pod 内部其它容器都使用`container`网络模式,并指定其值为 pause 容器的 ID(即:`network_mode: "container: pause 容器 ID"`),这样 Pod 内所有容器将共享 pause 容器的网络,所有其他容器在 Pod 内部都处于同一个网络模式下,可以彼此间直接通信,而与外部通信都会经过 pause 容器进行代理,因此 pause 容器 IP 才是真正实际意义上的 PodIP。 * `ExternalIP`:外部 IP,通过负载均衡(LB)方式发布服务的话,也就是 LoadBalancer Service 类型,公有云提供的负载均衡器的访问地址。 通过上面的梳理,我们更加清楚了 Service 的工作原理,下面的这张图片可以帮助理解: ![](https://img.kancloud.cn/b5/9c/b59c0a6c0bdbab4cbe9999c66f5248b3_649x503.png) #### Service 服务发现 Service 服务发现目前有两种类型:环境变量和 DNS。通常而言更加推荐使用后一种,也就是 DNS。 **1.环境变量** 当新创建 Pod 时,kubelet 会向该 Pod 中注册所有已经创建的与 Service 相关的环境变量。注意这里就存在一个问题,当某个特定的 Service 晚于 Pod 的创建,那么先创建的 Pod 就不会注册该 Service 的环境变量。因此我们更加推荐使用 DNS 来进行服务发现。 **2.DNS** 通过在集群中部署 CoreDNS 服务(在老版本的 kubernetes 集群中使用的是 KubeDNS)来实现集群内部 Pod 通过 DNS 方式进行通讯。 CoreDNS 是以插件方式集成到 kubernetes 集群中作为默认的 DNS 服务,这样可以更加灵活方便的进行拓展。