Services

Service #

官方文档: kubernetes.io/docs/concepts/services-networking/service/


1. 概述 #

Service 是一种抽象,定义了一组逻辑上的 Pod 端点以及如何访问它们的策略。

为什么需要 Service

  • Pod 是短暂的(IP 会变化)
  • Service 提供稳定的 IP 和 DNS 名
  • 自动通过 selector 跟踪后端 Pod

云原生服务发现 #

客户端 → Service(稳定 IP)→ kube-proxy → Pod(动态 IP)
                              ↑
                        EndpointSlice(自动跟踪 Pod)

2. 定义 Service #

2.1 基本 Service #

apiVersion: v1
kind: Service
metadata:
  name: my-service
spec:
  selector:
    app.kubernetes.io/name: proxy      # 选择后端 Pod
  ports:
  - protocol: TCP
    port: 80                           # Service 端口
    targetPort: 8080                   # Pod 端口(默认等于 port)

2.2 端口定义 #

字段说明
portService 暴露的端口号
targetPort后端 Pod 的端口(默认等于 port
nodePortNodePort 类型的节点端口(可选)
protocolTCP(默认)/ UDP / SCTP
appProtocol应用层协议提示(httphttps 等)

2.3 无 Selector 的 Service #

Service 可以不设 selector,用于对接非 Pod 后端:

apiVersion: v1
kind: Service
metadata:
  name: my-service
spec:
  ports:
  - protocol: TCP
    port: 80
    targetPort: 9376
  # 无 selector
---
apiVersion: discovery.k8s.io/v1
kind: EndpointSlice
metadata:
  name: my-service-abc      # 名称须以 Service 名为前缀
  labels:
    kubernetes.io/service-name: my-service
addressType: IPv4
ports:
  - name: http
    port: 9376
endpoints:
  - addresses:
    - 192.0.2.246

典型场景:对接外部数据库、路由到其他 Service。


3. Service 类型 #

类型说明端口范围特点
ClusterIP(默认)集群内部虚拟 IP任意仅集群内可访问
NodePort在每个节点暴露端口30000-32767可从集群外访问,自建 LB
LoadBalancer云厂商自动创建 LB任意外部 LB + NodePort 基础
ExternalName映射外部 DNS 名N/ADNS 级别 CNAME 重定向

3.1 ClusterIP #

  • 默认类型
  • 分配集群内部 IP(10.x.x.x
  • .spec.clusterIP 可手动指定,设为 "None" 则为 Headless Service
  • kube-proxy 在各节点配置 iptables/IPVS/eBPF 规则

3.2 NodePort #

spec:
  type: NodePort
  ports:
  - port: 80
    targetPort: 8080
    nodePort: 30007    # 可选,手动指定

端口分配策略

默认范围自动分配段手动分配段
30000-3276730000-3099931000-32767

自定义网卡--nodeport-addresses=127.0.0.0/8 可限制 kube-proxy 监听特定网卡。默认监听所有网卡。

访问方式:<NodeIP>:<nodePort><ClusterIP>:<port>

3.3 LoadBalancer #

spec:
  type: LoadBalancer
  clusterIP: 10.0.171.239
  loadBalancer:
    class: example.com/lb-implementation   # 指定 LB 实现

构建过程:先创建 NodePort → cloud-controller-manager 配置外部 LB → LB 流量转发到 NodePort。

字段说明版本
spec.loadBalancerIP指定 LB IP(已弃用)v1.24 deprecated
spec.loadBalancerClass指定 LB 实现类v1.24 stable
spec.allocateLoadBalancerNodePorts禁用 NodePort 分配v1.24 stable
status.loadBalancer.ingress.ipModeVIP(默认)或 Proxyv1.x

ipMode 说明

ipMode流量路径
VIPLB → NodeIP:NodePort → Pod(DNAT)
ProxyLB → Pod IP:Port(直接路由)

内部 LB 注解(云厂商特定):

metadata:
  annotations:
    service.beta.kubernetes.io/alibaba-cloud-loadbalancer-address-type: "intranet"
    service.kubernetes.io/qcloud-loadbalancer-internal-subnetid: subnet-xxxxx

3.4 ExternalName #

spec:
  type: ExternalName
  externalName: my.database.example.com
  • 无 selector,无 ClusterIP
  • 通过 DNS CNAME 重定向到外部域名
  • 重定向在 DNS 层面,不走 proxy
  • 陷阱:HTTP/HTTPS 中 Host header 与 ExternalName 不一致

4. Headless Service #

设置 .spec.clusterIP: "None" 创建无 ClusterIP 的 Service。

特征说明
无 ClusterIP不分配虚拟 IP
不走 kube-proxy无负载均衡、无代理
DNS 返回 Pod IP客户端直接连接 Pod

DNS 行为 #

有 selector无 selector
自动创建 EndpointSlice不创建 EndpointSlice
DNS 返回所有 Pod IP(A/AAAA)DNS 返回手动配置的端点 IP

典型用途:StatefulSet、自定义服务发现、gRPC 直连 Pod。


5. 服务发现 #

5.1 环境变量 #

kubelet 在创建 Pod 时自动注入环境变量:

# Service "redis-master" 的环境变量
REDIS_MASTER_SERVICE_HOST=10.0.0.11
REDIS_MASTER_SERVICE_PORT=6379
REDIS_MASTER_PORT=tcp://10.0.0.11:6379

注意:必须先创建 Service,后创建 Pod,环境变量才会注入。

5.2 DNS #

Service 类型DNS 记录解析结果
普通 ServiceA/AAAAClusterIP
Headless ServiceA/AAAA所有 Pod IP
ExternalNameCNAME外部域名

DNS 域名格式:<service-name>.<namespace>.svc.cluster.local


6. 虚拟 IP 寻址机制 #

kube-proxy 的三种模式:

模式原理优点缺点
iptables(默认)在每个节点设置 iptables 规则内核态、零依赖规则多时性能下降
IPVS基于内核 IPVS 模块支持 LC/RR/DH 等算法需内核模块支持
eBPF内核可编程字节码性能最优、无 Sidecar需较新内核版本

流量路径 #

客户端 Pod → ClusterIP:Port
     ↓
  iptables/IPVS/eBPF 规则(kube-proxy 配置)
     ↓
  DNAT → 后端 Pod IP:targetPort

7. 流量策略 #

7.1 流量策略(Traffic Policy) #

字段选项说明
externalTrafficPolicyCluster(默认)外部流量跨节点负载均衡,源 IP 丢失(SNAT)
Local仅路由到本节点 Pod,保留源 IP
internalTrafficPolicyCluster(默认)内部流量可路由到任意节点 Pod
Local仅路由到本节点 Pod

7.2 流量分布(Traffic Distribution) #

.spec.trafficDistribution 表达拓扑偏好(非强制约束):

说明
PreferSameZone偏好同可用区端点
PreferSameNode偏好同节点端点

7.3 会话亲和性 #

spec:
  sessionAffinity: ClientIP      # 或 None(默认)
  sessionAffinityConfig:
    clientIP:
      timeoutSeconds: 10800      # 默认 3 小时
说明
None(默认)无亲和性,随机负载均衡
ClientIP相同客户端 IP 路由到同一 Pod

8. External IPs(已弃用) #

Kubernetes v1.36 [deprecated] — 建议迁移

spec:
  externalIPs:
  - 198.51.100.32
  ports:
  - port: 80
  • 允许 Service 绑定到非 cluster IP 的外部 IP
  • 流量到达节点后被路由到 Service 端点
  • Kubernetes 不管理 externalIPs 的分配(运维负责)

9. Service 类型选型指南 #

内部服务间通信?
├─ 是 → ClusterIP
│         ├─ 需要直连 Pod?→ Headless Service (clusterIP: None)
│         └─ 需要稳定的虚拟 IP?→ 普通 ClusterIP
└─ 否 → 需要外部访问?
          ├─ 云环境 + 生产?→ LoadBalancer
          ├─ 简单外部访问?→ NodePort
          └─ 对接外部域名?→ ExternalName

10. 关键对比 #

维度ClusterIPNodePortLoadBalancerExternalNameHeadless
集群内访问✗(DNS)✓(DNS)
集群外访问✗(DNS)
有 ClusterIP
有 selector可选
kube-proxy
保留源 IPLocalLocalN/AN/A
生产推荐测试对接外部StatefulSet

参考 #