Pod 的 IP 是临时的——每次重建 Pod 都会分配新的 IP。如果前端应用直接写死后端 Pod 的 IP,一旦 Pod 重建,连接就会断开。Kubernetes 通过 Service 解决这个问题:Service 为一组 Pod 提供稳定的虚拟 IP 和 DNS 名称,无论后端 Pod 如何变化,客户端始终通过 Service 访问。
本章从 Service 的四种类型出发,逐步深入 Endpoints、Ingress、DNS、kube-proxy 和 NetworkPolicy,构建完整的 Kubernetes 网络知识体系。
一、Service:Pod 的稳定访问入口
Service 的核心机制是标签选择器(Label Selector)——它通过 Selector 筛选匹配的 Pod,将流量转发到这些 Pod 上。Pod 增减、重建、IP 变化,Service 自动更新后端列表,客户端无感知。
1.1 Service 的工作原理
- Service 根据
selector找到匹配的 Pod - 将 Pod 的 IP +
targetPort写入 Endpoints 对象 - kube-proxy 监听 Endpoints 变化,在节点上配置转发规则
- 访问 Service IP 的流量被转发到后端 Pod
1.2 四种 Service 类型
ClusterIP(默认)
分配一个集群内部可达的虚拟 IP,只能在集群内部访问。
apiVersion: v1kind: Servicemetadata: name: nginx-svcspec: type: ClusterIP # 默认类型 selector: app: nginx ports: - port: 80 # Service 端口 targetPort: 8080 # Pod 容器端口# 集群内访问curl http://nginx-svc:80curl http://10.96.0.100:80NodePort
在 ClusterIP 基础上,在每个 Node 上开放一个端口(默认范围 30000-32767),外部可以通过 NodeIP:NodePort 访问。
spec: type: NodePort ports: - port: 80 targetPort: 8080 nodePort: 30080 # 指定 NodePort(可选,不指定则自动分配)NodePort 的端口范围有限(30000-32767),不适合直接对外暴露服务。生产环境通常在 NodePort 前面再加一层 LoadBalancer 或 Ingress。
LoadBalancer
在 NodePort 基础上,向云厂商请求一个外部负载均衡器(如 AWS ELB、GCP Load Balancer),将外部流量导入集群。
spec: type: LoadBalancer ports: - port: 80 targetPort: 8080# 查看外部 IPkubectl get svc nginx-svc# NAME TYPE EXTERNAL-IP PORT(S)# nginx-svc LoadBalancer 203.0.113.100 80:30080/TCPLoadBalancer 类型依赖云厂商的 Cloud Controller Manager。在本地集群(如 minikube、kind)中,外部 IP 通常显示为 <pending>。
ExternalName
将 Service 映射到外部 DNS 名称,不创建 Endpoints,不代理流量,仅在集群 DNS 中创建 CNAME 记录。
spec: type: ExternalName externalName: my.database.aws.com# 集群内访问 my-db.default.svc.cluster.local# DNS 返回 CNAME -> my.database.aws.com1.3 Service 类型选择
| 场景 | 推荐类型 | 原因 |
|---|---|---|
| 集群内部通信 | ClusterIP | 安全,不暴露到外部 |
| 开发/测试环境外部访问 | NodePort | 简单直接 |
| 生产环境对外暴露 | LoadBalancer + Ingress | 云厂商负载均衡 + 路由管理 |
| 访问集群外部服务 | ExternalName | 统一 DNS 命名 |
二、Endpoints 与 EndpointSlice
2.1 Endpoints
每个 Service 自动创建一个同名的 Endpoints 对象,存储匹配 Pod 的 IP 和端口:
apiVersion: v1kind: Endpointsmetadata: name: nginx-svc # 与 Service 同名subsets: - addresses: - ip: 10.244.1.5 - ip: 10.244.2.3 - ip: 10.244.3.7 ports: - port: 8080当 Pod 的 Readiness Probe 失败时,该 Pod 的 IP 会从 Endpoints 中移除,Service 不再将流量转发给它——这就是 Readiness Probe 与 Service 的协作机制。
2.2 EndpointSlice
当 Service 后端 Pod 数量很大时(数千个),单个 Endpoints 对象会变得非常大,每次变更都需要全量同步。EndpointSlice 将后端 Pod 拆分为多个切片,每个切片最多 100 个端点:
apiVersion: discovery.k8s.io/v1kind: EndpointSlicemetadata: name: nginx-svc-abc123 labels: kubernetes.io/service-name: nginx-svcaddressType: IPv4endpoints: - addresses: - 10.244.1.5 conditions: ready: true - addresses: - 10.244.2.3 conditions: ready: trueports: - port: 8080Kubernetes 1.21 起 EndpointSlice 成为默认特性。对于大规模集群(1000+ Pod/Service),EndpointSlice 显著降低了 API Server 和 kube-proxy 的负载。
三、Ingress 与 Ingress Controller
Service 的 LoadBalancer 类型有一个问题:每个 Service 需要一个外部负载均衡器,成本高且 IP 资源浪费。Ingress 提供了更优雅的方案——一个入口点,基于域名和路径路由到不同 Service。
3.1 Ingress 工作模型
3.2 Ingress 配置示例
apiVersion: networking.k8s.io/v1kind: Ingressmetadata: name: my-ingress annotations: nginx.ingress.kubernetes.io/ssl-redirect: "true"spec: ingressClassName: nginx # 指定 Ingress Controller tls: - hosts: - api.example.com - web.example.com secretName: tls-secret rules: - host: api.example.com http: paths: - path: / pathType: Prefix backend: service: name: api-svc port: number: 80 - host: web.example.com http: paths: - path: / pathType: Prefix backend: service: name: web-svc port: number: 80 - path: /api pathType: Prefix backend: service: name: api-svc port: number: 803.3 Ingress Controller 选型
| Controller | 特点 | 适用场景 |
|---|---|---|
| NGINX Ingress | 最成熟,社区最大,配置丰富 | 通用场景 |
| Traefik | 自动服务发现,原生支持 CRD | 云原生、动态配置 |
| Kong | 插件生态丰富,API 网关能力 | API 管理、限流认证 |
| Envoy (Contour/Gloo) | 高性能,xDS 动态配置 | 大规模、服务网格 |
Ingress 只是 API 对象(定义路由规则),Ingress Controller 才是实际执行转发的组件。集群必须部署至少一个 Ingress Controller,Ingress 规则才会生效。
四、集群 DNS 服务发现
Kubernetes 集群内置 DNS 服务(CoreDNS),为每个 Service 自动创建 DNS 记录。
4.1 DNS 记录规则
| 对象 | DNS 名称 | 解析结果 |
|---|---|---|
| Service(ClusterIP) | my-svc.my-ns.svc.cluster.local | Service ClusterIP |
| Service(Headless) | my-svc.my-ns.svc.cluster.local | 所有 Pod IP(轮询) |
| Pod(StatefulSet) | pod-0.my-svc.my-ns.svc.cluster.local | Pod IP |
| Pod(普通) | 10-244-1-5.my-ns.pod.cluster.local | Pod IP |
# 在集群内查询 Service DNSnslookup nginx-svc# Server: 10.96.0.10# Name: nginx-svc.default.svc.cluster.local# Address: 10.96.0.100
# 同 Namespace 下可以简写curl http://nginx-svc:80
# 跨 Namespace 需要全限定名curl http://nginx-svc.production.svc:804.2 CoreDNS 配置
CoreDNS 通过 ConfigMap 配置,支持自定义 DNS 转发和解析:
apiVersion: v1kind: ConfigMapmetadata: name: coredns namespace: kube-systemdata: Corefile: | .:53 { errors health { lameduck 5s } ready kubernetes cluster.local in-addr.arpa ip6.arpa { pods insecure fallthrough in-addr.arpa ip6.arpa ttl 30 } prometheus :9153 forward . /etc/resolv.conf { max_concurrent 1000 } cache 30 loop reload loadbalance }五、kube-proxy:Service 背后的流量转发
kube-proxy 运行在每个 Node 上,负责实现 Service 的负载均衡。它监听 API Server 的 Service 和 Endpoints 变化,在节点上配置转发规则。
5.1 iptables 模式(默认)
iptables 模式使用 Linux netfilter 规则实现流量转发:
# kube-proxy 创建的 iptables 规则(简化)-A KUBE-SERVICES -d 10.96.0.100/32 -j KUBE-SVC-NGINX-A KUBE-SVC-NGINX -m statistic --mode random --probability 0.333 -j KUBE-SEP-POD1-A KUBE-SVC-NGINX -m statistic --mode random --probability 0.500 -j KUBE-SEP-POD2-A KUBE-SVC-NGINX -j KUBE-SEP-POD3-A KUBE-SEP-POD1 -s 10.244.1.5/32 -j MARK --set-xmark 0x4000/0x4000-A KUBE-SEP-POD1 -p tcp -m tcp -j DNAT --to-destination 10.244.1.5:8080iptables 模式的特点:
- 随机概率实现负载均衡(
--probability参数) - 规则链式匹配,Service 数量多时性能下降(O(n) 复杂度)
- 无法平滑切换后端 Pod(规则更新是原子替换)
5.2 IPVS 模式
IPVS(IP Virtual Server)是 Linux 内核的 L4 负载均衡器,专为大规模负载均衡设计:
# kube-proxy 创建的 IPVS 规则ipvsadm -Ln# TCP 10.96.0.100:80 rr# -> 10.244.1.5:8080 Masq 1 0 0# -> 10.244.2.3:8080 Masq 1 0 0# -> 10.244.3.7:8080 Masq 1 0 0IPVS 模式的优势:
| 维度 | iptables | IPVS |
|---|---|---|
| 负载均衡算法 | 随机概率 | rr/wrr/lc/wlc/sh/dh/sed/nq 等 |
| 规则查找 | O(n) 线性 | O(1) 哈希 |
| 大规模性能 | 1000+ Service 时延迟明显 | 万级 Service 仍稳定 |
| 会话保持 | 支持 | 支持(sessionAffinity) |
生产环境建议使用 IPVS 模式。需要在所有 Node 上加载 IPVS 内核模块:ip_vs, ip_vs_rr, ip_vs_wrr, ip_vs_sh, nf_conntrack。
5.3 模式切换
# 查看 kube-proxy 当前模式kubectl get configmap kube-proxy -n kube-system -o yaml | grep mode
# 切换到 IPVS 模式kubectl edit configmap kube-proxy -n kube-system# 将 mode: "" 改为 mode: "ipvs"
# 重启 kube-proxykubectl rollout restart daemonset kube-proxy -n kube-system六、NetworkPolicy:网络隔离
默认情况下,Kubernetes 集群中所有 Pod 可以互相通信。NetworkPolicy 提供基于 Label 的网络访问控制。
6.1 NetworkPolicy 示例
apiVersion: networking.k8s.io/v1kind: NetworkPolicymetadata: name: api-policy namespace: productionspec: podSelector: matchLabels: app: api # 策略应用到 app=api 的 Pod policyTypes: - Ingress - Egress ingress: - from: - podSelector: # 允许来自 app=web 的 Pod matchLabels: app: web ports: - port: 8080 - port: 443 - from: - namespaceSelector: # 允许来自 monitoring Namespace matchLabels: name: monitoring ports: - port: 9090 # 监控端口 egress: - to: - podSelector: # 允许访问 app=mysql 的 Pod matchLabels: app: mysql ports: - port: 3306 - to: # 允许 DNS 解析 - namespaceSelector: {} ports: - port: 53 protocol: UDP6.2 NetworkPolicy 的关键规则
| 规则 | 说明 |
|---|---|
podSelector | 策略应用到哪些 Pod(空表示 Namespace 内所有 Pod) |
policyTypes | 指定 Ingress/Egress 方向(未指定方向默认全部允许) |
ingress.from | 允许的入站来源(podSelector + namespaceSelector 是 AND 关系,同一 from 列表项内;不同列表项是 OR 关系) |
egress.to | 允许的出站目标 |
NetworkPolicy 由 CNI 插件实现,不是 kube-proxy。如果 CNI 不支持 NetworkPolicy(如 Flannel),配置了也不会生效。支持 NetworkPolicy 的 CNI:Calico、Cilium、Weave Net。
总结
| 概念 | 核心要点 |
|---|---|
| Service ClusterIP | 集群内部虚拟 IP,默认类型 |
| Service NodePort | 在 Node 上开放端口,外部可访问 |
| Service LoadBalancer | 云厂商负载均衡器,生产环境首选 |
| Service ExternalName | DNS CNAME 映射,访问外部服务 |
| Endpoints/EndpointSlice | Service 后端 Pod 列表 |
| Ingress | 基于域名/路径的 HTTP 路由,统一入口 |
| CoreDNS | 集群内 DNS 服务发现 |
| kube-proxy iptables | 默认模式,规则链匹配,小规模够用 |
| kube-proxy IPVS | 哈希查找,多算法,大规模首选 |
| NetworkPolicy | 基于 Label 的网络隔离,CNI 实现 |
下一章将深入 Kubernetes 的应用管理——Helm 包管理与 Operator 模式。
支持与分享
如果这篇文章对你有帮助,欢迎支持作者或分享给更多人
部分信息可能已经过时






