Skip to content

第3章 Service 核心概念与 YAML 基础

本章学习 Service 的最基本定义、关键字段,以及 Service 与 Pod 的关联方式。


3.1 第一个 Service YAML

yaml
apiVersion: v1
kind: Service
metadata:
  name: web-service
  namespace: default
spec:
  type: ClusterIP          # Service 类型
  selector:
    app: web               # 通过标签选择后端 Pod
  ports:
    - port: 80             # Service 暴露的端口
      targetPort: 8080     # 后端 Pod 容器端口
      protocol: TCP        # 默认 TCP,可选 UDP/SCTP

把这段 YAML 保存为 web-service.yaml,然后执行:

bash
kubectl apply -f web-service.yaml
kubectl get svc web-service

输出类似:

text
NAME         TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)   AGE
web-service  ClusterIP   10.96.123.45   <none>        80/TCP    10s

3.2 关键字段说明

字段含义
spec.typeService 类型:ClusterIP / NodePort / LoadBalancer / ExternalName
spec.selector标签选择器,决定哪些 Pod 属于该 Service
spec.ports[].portService 自身暴露的端口,集群内调用方使用
spec.ports[].targetPort后端 Pod 上容器实际监听的端口
spec.ports[].nodePortNodePort 类型时节点上暴露的端口(默认 30000-32767)
spec.clusterIP自动分配的虚拟 IP,可手动指定 None 表示 Headless
spec.sessionAffinity会话保持策略,NoneClientIP
spec.externalTrafficPolicy外部流量策略,ClusterLocal
spec.internalTrafficPolicy内部流量策略,ClusterLocal

3.3 Service 如何找到 Pod

Service 通过 selector 匹配 Pod 的 Label:

yaml
# Service
selector:
  app: web
  tier: frontend
yaml
# Pod
metadata:
  labels:
    app: web
    tier: frontend

只有当 Pod 的 Label 全部满足 selector 中的条件时,才会被选中。

验证匹配关系

bash
# 查看 Service 的 selector
kubectl get svc web-service -o yaml

# 查看匹配的 Pod
kubectl get pods -l app=web,tier=frontend

3.4 Service 不是进程,而是一个抽象

很多初学者会以为 Service 是一个运行在集群某处的代理进程。其实不是。

  • Service 对象本身只保存配置和意图
  • ClusterIP 不是一个真实网卡上的 IP
  • 真正实现流量转发的是运行在每个节点上的 kube-proxy,它根据 Service 和 EndpointSlice 配置 iptables/ipvs 规则。

我们下下一章会详细讲 kube-proxy。


3.5 多端口 Service

一个 Service 可以暴露多个端口:

yaml
apiVersion: v1
kind: Service
metadata:
  name: web-service
spec:
  selector:
    app: web
  ports:
    - name: http
      port: 80
      targetPort: 8080
    - name: management
      port: 8081
      targetPort: 8081

建议:每个端口都命名,方便 Ingress、监控、日志区分。


3.6 无 Selector 的 Service

Service 也可以不写 selector,用于指向集群外部服务或自定义后端。此时需要手动创建 Endpoints/EndpointSlice(详见第6章)。

yaml
apiVersion: v1
kind: Service
metadata:
  name: external-db
spec:
  type: ClusterIP
  ports:
    - port: 3306

3.7 本章小结

  • Service 通过 YAML 声明,核心字段是 typeselectorports
  • selector 通过 Label 匹配 Pod,决定哪些 Pod 接收流量。
  • Service 本身不转发流量,真正转发的是 kube-proxy 配置的 iptables/ipvs 规则。
  • 多端口 Service 建议给每个端口命名。

本章练习

  1. 创建一个 Deployment(3 个副本,标签 app=my-app),再创建一个 ClusterIP Service 指向它。
  2. 从集群内的一个临时 Pod 访问 http://my-app,验证是否能访问到后端。
  3. 修改 Deployment 的副本数为 5,观察 Service 的 Endpoints 是否自动更新。