Service 的四种类型到底各是什么关系?NodePort 只在有 Pod 的节点开端口吗?LoadBalancer 没有云厂商时是什么状态?ExternalName 有没有负载均衡?这篇在三节点 kind 集群里每种类型都实际访问一遍。
Service s-cip:type=ClusterIP;clusterIP=10.96.84.171(来自 Service CIDR 10.96.0.0/16);port 8080 → targetPort 80 从 Pod cli 访问 10.96.84.171:8080 → <title>Welcome to nginx!;用 Service DNS s-cip:8080 → <title>Welcome to nginx! 从节点 worker(有后端的节点)访问 → <title>Welcome to nginx!;从别的节点 control-plane 访问 → <title>Welcome to nginx!(kube-proxy 在每个节点上都写了规则) 从宿主机(Mac)直接访问 10.96.84.171:8080:不可达(超时) 直接访问 Pod IP 10.244.1.74:80 → <title>Welcome to nginx!(Pod IP 也通,但 Pod 重建后会变)
Service s-cip 的 clusterIP=10.96.84.171 来自 Service CIDR 10.96.0.0/16,port: 8080 转发到后端的 targetPort: 80。Pod 里用 IP:8080 或 DNS 名 s-cip:8080 都能访问到 nginx;在有后端的 worker 上、没有后端的 control-plane 上访问同样能通——kube-proxy 在每个节点上都写了规则。从宿主机(Mac)直接访问这个 IP 超时:它不在任何网卡上,只是被节点的转发规则识别。直接访问 Pod IP 也通,但 Pod 重建后会变,所以才需要 Service。
Service s-np:type=NodePort;自动分配 nodePort=32504(范围 30000-32767);同时也有 clusterIP=10.96.102.139(NodePort 是 ClusterIP 的超集) 从 Pod cli 访问节点 control-plane(172.18.0.3):32504 → <title>Welcome to nginx!(这个节点没有后端 Pod,也能通) 从 Pod cli 访问节点 worker(172.18.0.2):32504 → <title>Welcome to nginx!(这个节点有后端 Pod) 从 Pod cli 访问节点 worker2(172.18.0.4):32504 → <title>Welcome to nginx!(这个节点没有后端 Pod,也能通) 宿主机访问 localhost:32504(kind 没有映射这个端口):不可达 指定 nodePort: 80:退出码 1;The Service "s-bad" is invalid: spec.ports[0].nodePort: Invalid value: 80: provided port is not in the valid range. The range of valid ports is 30000-32767 指定 nodePort: 31234:退出码 0;实际 nodePort=31234 另一个 Service 也要 31234:退出码 1;The Service "s-pin2" is invalid: spec.ports[0].nodePort: Invalid value: 31234: provided port is already allocated
s-np 自动分配了 nodePort=32504(范围 30000-32767),同时也有 ClusterIP——NodePort 是 ClusterIP 的超集。Pod 访问三个节点的 IP:32504 全部成功,包括没有后端 Pod 的 control-plane 和 worker2:每个节点都会转发。指定 nodePort: 80 被拒(provided port is not in the valid range),指定 31234 成功,第二个 Service 再要 31234 则 provided port is already allocated。kind 没有把这些端口映射到宿主机,所以宿主机的 localhost:32504 不通。
Service s-lb:type=LoadBalancer;status.loadBalancer={};clusterIP=10.96.244.203;nodePort=31235
kubectl get svc:s-lb LoadBalancer 10.96.244.203 <pending> 8080:31235/TCP 8s
LoadBalancer 创建时同时分配了 nodePort 31235;用它访问 172.18.0.2:31235 → <title>Welcome to nginx!(云上的负载均衡器就是把流量转发到这些 NodePort)
allocateLoadBalancerNodePorts: false 的 s-lb2:nodePort=None
s-lb 的事件:(没有——没有云控制器来处理它)s-lb 的 status.loadBalancer 是空的,EXTERNAL-IP 是 <pending>,也没有任何事件——没有云控制器来处理它。但它同时被分配了 nodePort 31235,用节点 IP:31235 访问能通:云厂商的负载均衡器做的事就是把流量转给这些 NodePort。allocateLoadBalancerNodePorts: false 的 s-lb2 没有 nodePort(用于负载均衡器直连 Pod 的场景)。
Service s-ext:clusterIP=None;externalName=example.com 在 Pod 里 nslookup s-ext:['s-ext.k61.svc.cluster.local\tcanonical name = example.com'];最后解析到 5 个外部地址(不是 Service 的 IP) iptables 里有 s-ext 的规则吗:0 条(没有 kube-proxy 规则,不经过 Service 转发)
s-ext 的 clusterIP 是 None,只有 externalName: example.com。在 Pod 里 nslookup s-ext.k61.svc.cluster.local 得到 canonical name = example.com,再解析出外部地址;节点 iptables 里找不到任何 k61/s-ext 的规则(0 条)。它不经过 kube-proxy,不做端口映射也不做负载均衡。