Kubernetes Service 是为一组 Pod 提供稳定访问入口和服务发现能力的抽象对象。
Pod 通常具有以下特点:
如果客户端直接访问 Pod IP,服务会非常不稳定。
Service 解决的是:
客户端不直接依赖 Pod IP,
而是访问一个稳定的 Service。
Service 再把流量转发给后端 Pod。基本关系:
Service 通常通过 Label Selector 选择 Pod:
selector:
app: api只要 Pod 标签匹配,并且 Pod 处于可接收流量的状态,就可能成为 Service 的后端。
Service 可以拥有稳定的:
ClusterIPPod 重建后,Pod IP 可以变化,但 Service 的 ClusterIP 一般保持不变。
同一个 Namespace 内可以通过:
api访问 Service。
跨 Namespace 可以使用:
api.production完整 DNS 名称通常是:
api.production.svc.cluster.localService 可以将请求分发到多个后端 Pod:
Service
├── Pod A
├── Pod B
└── Pod CService 通常只会将流量发送给符合条件的 Endpoint,Readiness Probe 失败的 Pod 通常不会接收普通 Service 流量。
客户端不需要感知:
Service 可以用于:
各字段含义:
| 字段 | 含义 |
|---|---|
metadata.name | Service 名称 |
metadata.namespace | 所属 Namespace |
spec.selector | 选择后端 Pod |
ports[].name | 端口名称 |
|
port、targetPort 和 nodePort这是 Service 中最容易混淆的三个端口。
流量关系:
Service ClusterIP:80
|
v
Pod IP:8080如果是 NodePort 或 LoadBalancer:
NodeIP:30080
|
v
Service:80
portService 对外提供的端口:
port: 80集群内客户端访问:
api:80targetPort后端 Pod 实际监听的端口:
targetPort: 8080它可以是数字:
targetPort: 8080也可以是命名端口:
targetPort: httpPod:
ports:
- name: http
containerPort: 8080使用命名端口更适合多环境和端口调整:
nodePortNodePort 类型使用的节点端口:
nodePort: 30080客户端可以访问:
任意节点 IP:30080NodePort 范围通常由集群配置决定,常见默认范围是:
30000-32767严格来说,Service 的 spec.type 主要有四种:
ClusterIP
NodePort
LoadBalancer
ExternalName此外,还有两个经常被称为“Service 类型”的特殊模式:
Headless Service
Selectorless Service其中 Headless Service 实际是:
clusterIP: None并不是独立的 spec.type。
ClusterIP 是默认类型,用于集群内部访问。
也可以省略:
spec:
selector:
app: api默认就是 ClusterIP。
同 Namespace:
curl http://api跨 Namespace:
curl http://api.production完整 DNS:
curl http://api.production.svc.cluster.local集群内部服务一般优先使用 ClusterIP,不要为每个内部服务都创建 LoadBalancer。
典型架构:
NodePort 在每个节点上开放一个端口,并将请求转发到 Service 后端。
访问方式:
NodeIP:30080NodePort 直接暴露节点端口,存在以下问题:
生产环境通常不建议直接把 NodePort 作为普通 Web 服务的最终入口,更常见的是:
云 LoadBalancer
或 Ingress/GatewayLoadBalancer 通常通过云控制器或其他集成组件创建外部负载均衡器。
查看外部地址:
kubectl get svc api-public -n production可能看到:
NAME TYPE CLUSTER-IP EXTERNAL-IP
api-public LoadBalancer 10.96.10.20 203.0.113.10每个 LoadBalancer Service 可能产生:
如果几十个 HTTP 服务各自创建 LoadBalancer,成本和运维复杂度都会增加。
常见架构是:
一个或少量 LoadBalancer
|
云负载均衡器通常会检查后端节点或 Service 后端。需要确认:
常见原因:
排查:
ExternalName 不创建 ClusterIP,也不负责转发流量,而是通过 DNS CNAME 将 Service 映射到外部域名。
集群内访问:
external-db.production.svc.cluster.localDNS 会将其解析到:
db.example.comExternalName:
如果需要真正的外部后端代理、固定地址或健康检查,可以使用:
Headless Service 使用:
clusterIP: None示例:
它不提供普通的虚拟 ClusterIP 负载均衡,而是让 DNS 直接返回后端 Pod 地址。
普通 Service:
db.data.svc.cluster.local -> 一个 ClusterIPHeadless Service:
db.data.svc.cluster.local -> 多个 Pod IPStatefulSet 中通常可以进一步访问单个 Pod:
db-0.db.data.svc.cluster.local
db-1.db.data.svc.cluster.local
db-2.db.data.svc.cluster.localHeadless Service 不等于负载均衡器。
客户端可能需要自己处理:
Service 可以不配置 Selector:
然后通过 EndpointSlice 手工定义后端:
适合:
注意:
Service 通过 Selector 选择标签匹配的 Pod:
spec:
Pod:
metadata:
查看 Service:
kubectl get svc api -n production -o yaml查看匹配的 Pod:
kubectl get pods -n production \
-l app=api,environment=production查看 EndpointSlice:
kubectl get endpointslice \
-l kubernetes.io/service-name=api \
如果 Service 没有后端,常见原因:
EndpointSlice 是 Service 后端 Endpoint 的现代表示方式。
早期 Kubernetes 使用:
Endpoints大规模集群中,一个 Service 可能对应大量 Pod,单个 Endpoints 对象会变得很大。EndpointSlice 将后端拆分为多个切片,提高了扩展性。
查看:
kubectl get endpointslice -n productionEndpointSlice 中包含:
生产排障时,建议优先查看 EndpointSlice:
kubectl
Service 的转发通常由节点上的网络组件实现,例如:
基本过程:
查看 kube-proxy 模式需要结合集群配置,常见实现包括:
iptables
IPVS
nftables
eBPF业务通常不需要直接关心底层实现,但排障时要知道:
很多人认为 Service 一定按轮询分发请求,这不准确。
实际分发受到以下因素影响:
例如客户端一直复用一个 TCP 长连接,即使 Service 后端有 10 个 Pod,这个连接上的请求也可能一直落到同一个 Pod。
因此,要观察真实流量分布,不能只看 Pod 数量,应结合:
sessionAffinity默认情况下:
sessionAffinity: None可以配置基于客户端 IP 的会话粘性:
含义:
来自同一客户端 IP 的流量,尽量发送到同一个后端 Pod。适合:
不适合作为长期状态管理方案,因为:
更好的做法通常是:
Session 存储在 Redis、数据库或其他共享存储externalTrafficPolicyspec:
externalTrafficPolicy: Cluster默认常见行为是:
外部流量可以先到任意节点,
再转发到任意节点上的后端 Pod。优点:
缺点:
spec:
externalTrafficPolicy: Local只转发到当前节点上的本地 Pod。
优点:
缺点:
使用前要确认:
外部负载均衡器是否会把流量发到没有本地 Pod 的节点internalTrafficPolicy可以限制集群内部流量只访问本节点 Pod:
默认:
internalTrafficPolicy: Cluster适合 Local 的场景:
风险:
Service 可以利用 EndpointSlice 的拓扑信息,让流量优先访问同区域或同区域的后端。
一种配置方式:
不同 Kubernetes 版本和网络实现可能采用不同字段或能力。较新的集群还可能使用:
trafficDistribution: PreferClose这类能力适合:
但需要保证:
Service 通常只将流量发送给 Ready 的 Pod。
示例:
当 Readiness 失败:
Pod 仍然可能是 Running
但通常会从 Service Endpoint 中移除这允许应用:
需要避免:
把永久性故障隐藏成 Readiness 失败如果容器已经无法自行恢复,应结合 Liveness 或控制器重启机制。
Service 通常是四层或集群内部访问抽象,Ingress 主要负责 HTTP/HTTPS 路由。
典型架构:
Ingress 示例:
注意:
创建 Ingress 不会自动提供负载均衡能力。必须有 Ingress Controller 或其他实现。
Gateway API 是比传统 Ingress 更丰富的流量管理 API。
它可以表达:
典型结构:
Service 仍然通常作为后端服务抽象存在。
生产新建 HTTP 流量入口时,可以根据平台支持情况评估:
Ingress
或
Gateway API| 需求 | 推荐方式 |
|---|---|
| 集群内访问 Pod | ClusterIP |
| 暴露节点端口 | NodePort |
| 通过云 LB 暴露服务 | LoadBalancer |
| 通过 DNS 映射外部域名 | ExternalName |
| 外部固定 IP 作为后端 | Selectorless Service + EndpointSlice |
| StatefulSet 稳定身份 | Headless Service |
| 多个 HTTP 服务共享入口 | Ingress/Gateway + ClusterIP |
微服务之间通常使用:
ClusterIP + Service DNS不要直接使用:
Pod IP不要为每个服务都创建独立 LoadBalancer,除非:
建议使用:
api
order-api
payment
postgres避免把版本写进 Service 名称:
api-v1
api-v2除非确实需要通过多个 Service 并行暴露不同版本。
版本通常由:
管理。
避免多个控制器使用重叠 Selector。
推荐:
selector:
app.kubernetes.io/name: api
app.kubernetes.io/instance: production不要仅使用过于宽泛的标签:
selector:
app: api如果多个应用或版本都使用 app=api,可能误选 Pod。
明确写出:
port: 80
targetPort: 8080对于复杂服务,使用命名端口:
Service 是否有后端,通常受 Pod Readiness 影响。生产必须正确配置 Readiness Probe。
建立平台规范:
普通内部服务:ClusterIP
统一 Web 入口:Ingress/Gateway
特殊 TCP 服务:独立 LoadBalancer如果业务需要客户端真实 IP,评估:
externalTrafficPolicy: Local并确认:
sessionAffinity如果业务依赖会话,优先将 Session 外置,而不是依赖客户端 IP 粘性。
Service 提供访问路径,但不等于访问控制。
需要使用 NetworkPolicy 限制:
Deployment 的 Pod:
Service:
访问:
http://api.production.svc.cluster.localIngress:
适合:
某些外部系统需要访问数据库 TCP 端口:
生产注意:
StatefulSet Pod 可能拥有:
redis-0.redis.data.svc.cluster.local
redis-1.redis.data.svc.cluster.local
redis-2.redis.data.svc.cluster.local适合:
但应用必须自己处理:
应用使用:
legacy-db.production.svc.cluster.local迁移后只需要修改 Service 的目标域名,应用配置可以保持不变。
适合迁移过渡,但要确认客户端正确处理 CNAME 和 DNS。
Service:
EndpointSlice:
应用只访问:
https://external-payment.production.svc.cluster.local适合将外部老系统逐步纳入 Kubernetes 服务发现体系。
外部硬件负载均衡器配置:
节点 A:30080
节点 B:30080
节点 C:30080如果使用 externalTrafficPolicy: Local,外部负载均衡器最好能够感知:
哪些节点存在可用的本地 Pod否则可能把流量发送到没有后端的节点。
kubectl get svc -n production
检查:
kubectl get pods -n production --show-labels确认是否匹配:
kubectl get pods -n production \
-l app.kubernetes.io/name=apikubectl
如果没有 Endpoint,重点检查:
对比:
直接访问 Pod IP 正常
访问 Service 异常通常说明问题在:
应用如果只监听:
127.0.0.1:8080Service 访问 Pod IP 时可能失败。
容器内应用通常应监听:
0.0.0.0:8080检查:
kubectl exec -it <pod-name> -n production -- ssService 的 Selector 只能选择同 Namespace 内的 Pod。
下面这种访问不会跨 Namespace 自动选择 Pod:
production Service
选择 staging Pod跨 Namespace 访问应使用:
service-name.namespacetargetPort 写错Pod 实际监听:
8080Service 却配置:
targetPort: 80结果:
Service 存在
Endpoint 也存在
但连接失败Pod Running
Service 没有后端可能是 Readiness Probe 失败。
查看:
kubectl describe pod <pod-name> -n productioncontainerPort 当作自动暴露端口containerPort: 8080不会自动创建 Service,也不会自动暴露到集群外。
ClusterIP 通常稳定,但应用更推荐使用 DNS:
api.production.svc.cluster.local而不是硬编码:
10.96.20.10NodePort 只是暴露方式,不等于:
HTTP/HTTPS 生产入口通常需要 Ingress、Gateway 或云 LB。
Headless Service 返回多个后端地址,客户端必须具备相应的服务发现和故障处理能力。
Deployment/StatefulSet
|
v
StatefulSet
|
+--> Headless Service
Kubernetes Service 的核心定位是:
为一组会变化的 Pod 提供稳定的网络入口、服务发现和流量转发。几种主要模式:
生产环境最常见的组合是:
最核心的理解是:
Pod 是可替换的运行实例,
Service 是稳定的访问抽象。客户端应该依赖:
Service DNS而不是依赖:
Pod IP
容器 ID
节点 IP
临时 Pod 名称一个成熟的生产 Service 设计,还需要结合:
这样才能让 Service 在 Pod 重建、滚动发布、节点故障和副本扩缩时,仍然提供稳定可靠的服务访问能力。 还有。前面已经覆盖了 Service 的主要知识,下面补充一组更偏高级生产实践的内容,重点是流量语义、双栈、云负载均衡和安全边界。
Service 的底层通常以连接为单位选择后端。
例如客户端使用:
一个长期 TCP 连接那么这个连接上的多个请求可能一直访问同一个 Pod。
因此,即使 Service 后端有多个 Pod,也可能出现:
Pod A:连接数很多
Pod B:连接数很少
Pod C:几乎没有连接常见原因:
所以不能只根据 Pod 数量判断流量是否均衡,应监控:
每个 Pod 请求数
每个 Pod 连接数
每个 Pod 延迟
每个 Pod 错误率
每个客户端连接复用情况EndpointSlice 中常见的 Endpoint 条件包括:
可以粗略理解为:
| 条件 | 含义 |
|---|---|
ready | 是否处于可接收流量状态 |
serving | 是否仍能提供服务 |
terminating | 是否正在终止 |
在 Pod 优雅下线时,Endpoint 可能仍然存在,但状态已经表示:
正在终止,不应再接收新的普通流量排障时不要只看 Endpoint IP,还要查看它的状态条件:
kubectl
appProtocol可以声明应用层协议:
常见值:
http
https
grpc
kubernetes.io/h2cappProtocol 主要为:
提供协议提示。
它不会自动把 HTTP 服务变成 HTTPS,也不会自动启用 TLS。TLS、证书和协议终止仍需要由应用、Ingress、Gateway 或代理组件完成。
双栈 Service 示例:
常见配置:
ipFamilyPolicy | 含义 |
|---|---|
SingleStack | 单一 IP 协议族 |
PreferDualStack | 尽量使用双栈 |
RequireDualStack | 必须使用双栈 |
生产环境需要确认:
查看 Service 地址:
kubectl get svc dual-stack-api -o yaml关注:
spec:
clusterIPs:
ipFamilies:
ipFamilyPolicy一般让 Kubernetes 自动分配:
spec:
type: ClusterIP不要随意手工设置:
clusterIP: 10.96.10.20手工指定可能造成:
只有在确实需要兼容旧系统、固定白名单或特殊网络规划时,才考虑固定 ClusterIP,并且必须由平台统一分配和登记。
ClusterIP 通常只在集群网络范围内有效。
一般不能直接从集群外部访问:
Service ClusterIP除非外部网络经过特殊路由或代理配置。
外部访问应使用:
LoadBalancer
NodePort
Ingress
Gateway
端口转发测试时可以使用:
kubectl port-forward svc/api 8080:80 -n production然后访问:
http://127.0.0.1:8080port-forward 适合开发和排障,不适合生产流量入口。
allocateLoadBalancerNodePorts对于 LoadBalancer Service,某些实现会自动分配 NodePort:
spec:
type: LoadBalancer如果外部负载均衡器不需要通过 NodePort 转发,可以考虑:
spec:
type: LoadBalancer
allocateLoadBalancerNodePorts: false但只有在当前云控制器或负载均衡实现明确支持时才能这样做。
否则可能导致:
LoadBalancer 已创建
但后端没有可用转发端口使用前需要确认:
loadBalancerClass 用于选择不同 LB 实现如果集群中存在多个 LoadBalancer 实现,可以指定:
适合:
这通常属于平台层配置,业务团队不应随意填写任意 loadBalancerClass。
云环境中,LoadBalancer 可能默认创建公网入口,也可能创建内网入口。
通常通过云厂商 Annotation 指定,例如不同云平台的字段不完全相同:
metadata:
annotations:
example.com/load-balancer-scheme: internal生产环境必须明确:
这是公网服务还是内网服务?
是否需要公网 IP?
是否允许互联网访问?
是否需要跨 VPC?
是否有安全组限制?
是否需要私网 DNS?不要仅通过 Service 类型判断安全性:
type: LoadBalancer它本身不代表一定是内网或公网。
loadBalancerSourceRanges 不是完整安全控制可以配置来源网段:
它可以表达:
只允许指定 CIDR 的来源访问 LoadBalancer但实际是否生效,取决于:
生产环境应同时配置:
externalIPs 要谨慎使用Service 可以配置:
spec:
externalIPs:
- 192.0.2.20它表示允许通过指定外部 IP 访问 Service,但 Kubernetes 通常不会自动为你创建或管理这个 IP。
你需要自行保证:
因此,生产环境一般优先使用:
LoadBalancer
Ingress/Gateway而不是随意使用 externalIPs。
publishNotReadyAddresses 是服务发现选项,不是健康检查绕过示例:
它适合需要在启动阶段互相发现的集群成员。
但如果普通 Web 服务配置它,可能导致:
启动未完成的 Pod 也出现在 DNS 结果中
客户端连接到未 Ready 实例
请求失败率增加普通业务服务通常应保持默认行为,让 Readiness 控制流量进入。
无 Selector Service + EndpointSlice 很灵活,但后端地址是手工维护的。
如果 EndpointSlice 被错误修改,可能造成:
因此应限制谁可以修改:
services
endpointslices并使用:
同 Namespace:
http://api跨 Namespace:
http://api.production完整名称:
http://api.production.svc.cluster.local如果目标 Service 使用端口名称,还可以在应用配置中统一写:
api.production.svc.cluster.local:80注意:
Service 的 DNS 名称只保证服务发现,不保证网络一定被允许访问。跨 Namespace 访问还需要确认 NetworkPolicy 是否放行。
Pod 中的 /etc/resolv.conf 通常包含搜索域:
production.svc.cluster.local
svc.cluster.local
cluster.local因此:
api可能被解析为:
api.production.svc.cluster.local但在复杂场景下,短名称可能造成歧义。跨 Namespace 或跨团队调用时,建议至少使用:
service.namespace对关键基础服务,可以使用完整 FQDN:
service.namespace.svc.cluster.localService 只负责:
服务发现
基础流量转发它不自动提供:
这些需要由:
共同完成。
生产服务调用至少应配置:
连接超时
请求超时
有限次数重试
指数退避
熔断
幂等控制不要因为有 Service,就让客户端无限重试。
如果修改:
targetPortexternalTrafficPolicy可能影响正在建立和复用的连接。
例如切换 Selector:
旧版本 Pod -> 新版本 Pod需要验证:
对于长连接服务,Service 更新通常不能只观察 HTTP 短请求成功率。
Service
|
+--> 旧 Pod
+--> 新 Pod由 Deployment 控制滚动更新。
适合一般无状态服务。
api-blue Service -> blue Pods
api-green Service -> green Pods切换流量时修改 Ingress 或上层路由。
适合:
主 Service -> 稳定版本
Ingress/Gateway -> 少量流量到 canary Service适合:
Service 本身通常只能按 Selector 选择后端,复杂的按请求路由更适合由 Ingress、Gateway 或 Service Mesh 实现。
建议监控以下维度:
Service 本身通常不是业务性能的唯一来源,监控应从以下链路观察:
Service 的核心不是“一个虚拟 IP”,而是:
稳定名称
服务发现
后端实例选择
流量转发
健康状态传播
外部访问抽象生产环境可以按下面的方式选择:
需要特别记住:
Service 不保证应用健康
Service 不提供完整安全控制
Service 不替代应用重试和熔断
Service 不保证严格的请求级轮询
Service 不会自动创建 Ingress
Service 不会让 Pod IP 永久稳定一个成熟的生产 Service 方案应当是:
到这里,Service 从基本定义、类型、端口、服务发现、EndpointSlice、流量策略、云负载均衡、双栈、StatefulSet、外部服务接入、安全、发布和生产运维边界,已经基本覆盖完整。
Client
|
v
Service
|
v
EndpointSlice
|
v
Ready PodapiVersion: v1
kind: Service
metadata:
name: api
namespace: production
spec:
selector:
app: api
ports:
- name: http
protocol: TCP
port: 80
targetPort: 8080| TCP、UDP 或 SCTP |
ports[].port | Service 暴露的端口 |
ports[].targetPort | 后端 Pod 端口 |
spec.type | Service 类型 |
clusterIP | 集群内虚拟 IP |
externalTrafficPolicy | 外部流量策略 |
internalTrafficPolicy | 集群内部流量策略 |
sessionAffinity | 会话粘性 |
publishNotReadyAddresses | 是否发布未 Ready 的后端 |
ports:
- port: 80
targetPort: 8080
nodePort: 30080ports:
- name: http
port: 80
targetPort: httpapiVersion: v1
kind: Service
metadata:
name: api
namespace: production
spec:
type: ClusterIP
selector:
app: api
ports:
- name: http
port: 80
targetPort: 8080外部客户端
|
v
Ingress / Gateway
|
v
ClusterIP Service
|
v
PodapiVersion: v1
kind: Service
metadata:
name: api-nodeport
namespace: production
spec:
type: NodePort
selector:
app: api
ports:
- name: http
port: 80
targetPort: 8080
nodePort: 30080Client
|
v
NodeIP:30080
|
v
Service ClusterIP:80
|
v
PodIP:8080apiVersion: v1
kind: Service
metadata:
name: api-public
namespace: production
spec:
type: LoadBalancer
selector:
app: api
ports:
- name: http
port: 80
targetPort: 8080apiVersion: v1
kind: Service
metadata:
name: external-db
namespace: production
spec:
type: ExternalName
externalName: db.example.comapiVersion: v1
kind: Service
metadata:
name: db
namespace: data
spec:
clusterIP: None
selector:
app: db
ports:
- name: database
port: 5432
targetPort: 5432apiVersion: v1
kind: Service
metadata:
name: external-api
namespace: production
spec:
ports:
- name: https
port: 443
targetPort: 443apiVersion: discovery.k8s.io/v1
kind: EndpointSlice
metadata:
name: external-api-1
namespace: production
labels:
kubernetes.io/service-name: external-api
addressType: IPv4
ports:
- name: https
protocol: TCP
port: 443
endpoints:
- addresses:
- "192.0.2.10"
- addresses:
- "192.0.2.11"客户端访问 Service ClusterIP
|
v
节点网络规则匹配
|
v
选择后端 Endpoint
|
v
转发到 Pod IPapiVersion: v1
kind: Service
metadata:
name: legacy-app
spec:
selector:
app: legacy-app
sessionAffinity: ClientIP
sessionAffinityConfig:
clientIP:
timeoutSeconds: 3600
ports:
- port: 80
targetPort: 8080apiVersion: v1
kind: Service
metadata:
name: local-api
spec:
internalTrafficPolicy: Local
selector:
app: api
ports:
- port: 80
targetPort: 8080apiVersion: v1
kind: Service
metadata:
name: api
annotations:
service.kubernetes.io/topology-aware-routing: auto
spec:
selector:
app: api
ports:
- port: 80
targetPort: 8080readinessProbe:
httpGet:
path: /ready
port: 8080
periodSeconds: 5Internet
|
v
LoadBalancer Service
|
v
Ingress Controller
|
+--> api Service
|
+--> web Service
|
+--> admin ServiceapiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: web
namespace: production
spec:
ingressClassName: nginx
rules:
- host: api.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: api
port:
number: 80GatewayClass
|
v
Gateway
|
v
HTTPRoute
|
v
Service
|
v
Podports:
- name: http
port: 80
targetPort: httpapiVersion: apps/v1
kind: Deployment
metadata:
name: api
namespace: production
spec:
replicas: 3
selector:
matchLabels:
app.kubernetes.io/name: api
template:
metadata:
labels:
app.kubernetes.io/name: api
spec:
containers:
- name: api
image: registry.example.com/api:v1.2.0
ports:
- name: http
containerPort: 8080
readinessProbe:
httpGet:
path: /ready
port: httpapiVersion: v1
kind: Service
metadata:
name: api
namespace: production
spec:
type: ClusterIP
selector:
app.kubernetes.io/name: api
ports:
- name: http
port: 80
targetPort: http公网
|
v
LoadBalancer Service
|
v
Ingress Controller
|
+--> api Service
+--> web Service
+--> admin ServiceapiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: app-ingress
namespace: production
spec:
ingressClassName: nginx
rules:
- host: api.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: api
port:
number: 80
- host: www.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: web
port:
number: 80apiVersion: v1
kind: Service
metadata:
name: postgres-public
namespace: data
spec:
type: LoadBalancer
externalTrafficPolicy: Local
selector:
app: postgres
ports:
- name: postgres
protocol: TCP
port: 5432
targetPort: 5432apiVersion: v1
kind: Service
metadata:
name: redis
namespace: data
spec:
clusterIP: None
selector:
app: redis
ports:
- name: redis
port: 6379
targetPort: 6379apiVersion: v1
kind: Service
metadata:
name: legacy-db
namespace: production
spec:
type: ExternalName
externalName: legacy-db.example.comapiVersion: v1
kind: Service
metadata:
name: external-payment
namespace: production
spec:
ports:
- name: https
port: 443
targetPort: 443apiVersion: discovery.k8s.io/v1
kind: EndpointSlice
metadata:
name: external-payment
namespace: production
labels:
kubernetes.io/service-name: external-payment
addressType: IPv4
ports:
- name: https
protocol: TCP
port: 443
endpoints:
- addresses:
- "10.20.30.40"apiVersion: v1
kind: Service
metadata:
name: api-nodeport
namespace: production
spec:
type: NodePort
externalTrafficPolicy: Local
selector:
app: api
ports:
- name: http
port: 80
targetPort: 8080
nodePort: 30080kubectl run dns-test \
--rm -it \
--image=busybox:1.36 \
--restart=Never \
-- nslookup api.production.svc.cluster.localkubectl run curl-test \
--rm -it \
--image=curlimages/curl \
--restart=Never \
-- curl -v http://api.production.svc.cluster.localkubectl run curl-test \
--rm -it \
--image=curlimages/curl \
--restart=Never \
-- curl -v http://<pod-ip>:8080公网
|
v
LoadBalancer Service
|
v
Ingress Controller / Gateway
|
v
ClusterIP Service
|
v
Pod应用
|
v
Selectorless Service
|
v
EndpointSlice
|
v
集群外服务[ ] Service 是否选择了正确 Namespace 中的 Pod
[ ] Selector 是否唯一且稳定
[ ] Pod 标签是否匹配
[ ] Pod 是否通过 Readiness Probe
[ ] port 是否正确
[ ] targetPort 是否正确
[ ] 是否使用命名端口
[ ] 是否需要 ClusterIP、NodePort 或 LoadBalancer
[ ] 是否需要 Headless Service
[ ] 是否需要 ExternalName
[ ] 是否需要 EndpointSlice
[ ] 是否需要保留源 IP
[ ] 是否需要 internalTrafficPolicy
[ ] 是否需要 topology-aware routing
[ ] 是否需要 sessionAffinity
[ ] 是否配置 NetworkPolicy
[ ] 是否配置 DNS
[ ] 是否需要 TLS、认证和限流
[ ] LoadBalancer 数量和成本是否可控
[ ] 外部健康检查是否正常
[ ] 是否监控 EndpointSlice 和 Service 延迟
[ ] 是否有发布和下线验证ClusterIP:
集群内部访问,默认类型
NodePort:
通过每个节点的固定端口访问
LoadBalancer:
通过外部或云负载均衡器访问
ExternalName:
通过 DNS CNAME 映射外部域名
Headless Service:
不提供虚拟 IP,直接返回后端 Pod 地址
Selectorless Service:
不自动选择 Pod,通过 EndpointSlice 手工指定后端内部服务:
ClusterIP + Service DNS
公网 HTTP:
LoadBalancer + Ingress/Gateway + ClusterIP
有状态集群:
StatefulSet + Headless Service + PVC
外部老系统:
ClusterIP Service + EndpointSlice
或 ExternalNameReadiness Probe
EndpointSlice
Ingress/Gateway
NetworkPolicy
externalTrafficPolicy
拓扑路由
DNS
健康检查
源 IP 保留
负载均衡成本
监控和故障排查apiVersion: v1
kind: Service
metadata:
name: grpc-api
spec:
selector:
app: grpc-api
ports:
- name: grpc
port: 9090
targetPort: 9090
appProtocol: grpcapiVersion: v1
kind: Service
metadata:
name: dual-stack-api
spec:
ipFamilyPolicy: PreferDualStack
ipFamilies:
- IPv4
- IPv6
selector:
app: api
ports:
- name: http
port: 80
targetPort: 8080apiVersion: v1
kind: Service
metadata:
name: private-api
spec:
type: LoadBalancer
loadBalancerClass: example.com/private-lb
selector:
app: api
ports:
- port: 443
targetPort: 8443apiVersion: v1
kind: Service
metadata:
name: restricted-api
spec:
type: LoadBalancer
loadBalancerSourceRanges:
- "10.0.0.0/8"
- "192.168.0.0/16"
selector:
app: api
ports:
- port: 443
targetPort: 8443apiVersion: v1
kind: Service
metadata:
name: cluster-members
spec:
clusterIP: None
publishNotReadyAddresses: true
selector:
app: cluster-member
ports:
- name: peer
port: 7000
targetPort: 7000Service 后端 Endpoint 数量
Ready Endpoint 数量
NotReady Endpoint 数量
每个 Pod 请求数
每个 Pod 连接数
请求成功率
4xx/5xx
P50/P95/P99 延迟
连接建立失败
DNS 解析失败
跨节点流量
跨可用区流量
LoadBalancer 健康检查
NodePort 错误
NetworkPolicy 拒绝数客户端
-> DNS
-> LoadBalancer/Ingress
-> Service
-> EndpointSlice
-> Pod
-> 应用
-> 下游依赖[ ] Service 类型是否符合访问边界
[ ] 是否误将内部服务暴露到公网
[ ] Selector 是否唯一
[ ] EndpointSlice 是否正常
[ ] Ready 状态是否正确
[ ] targetPort 是否匹配应用监听端口
[ ] 是否需要保留源 IP
[ ] externalTrafficPolicy 是否正确
[ ] 是否需要 internalTrafficPolicy
[ ] 是否需要 Headless Service
[ ] 是否需要 publishNotReadyAddresses
[ ] 是否需要双栈
[ ] 是否使用命名端口
[ ] 是否需要 appProtocol
[ ] 是否需要 Ingress/Gateway
[ ] 是否需要独立 LoadBalancer
[ ] 是否控制 LoadBalancer 成本
[ ] 是否配置安全组和来源网段
[ ] 是否配置 NetworkPolicy
[ ] 是否限制 EndpointSlice 修改权限
[ ] 是否考虑长连接和连接复用
[ ] 是否配置客户端超时、重试和熔断
[ ] 是否有版本发布和回滚方案
[ ] 是否监控 Endpoint、延迟和错误率集群内服务:
ClusterIP
统一 HTTP/HTTPS 入口:
LoadBalancer + Ingress/Gateway + ClusterIP
独立四层公网或私网服务:
LoadBalancer
裸机或外部硬件 LB:
NodePort
StatefulSet 节点发现:
Headless Service
外部域名映射:
ExternalName
外部固定 IP 后端:
Selectorless Service + EndpointSliceService
+ EndpointSlice
+ Readiness Probe
+ Ingress/Gateway
+ NetworkPolicy
+ DNS
+ LB/防火墙
+ 超时重试熔断
+ 监控审计
+ 灰度发布和回滚