Home

K8S Service 原理

在 Kubernetes 中,Service 的创建过程涉及多个组件的协作,包括 API Server、kube-proxy、Endpoint Controller 等。以下是 Service 创建的详细流程,从 YAML 提交到最终生效的完整过程:


1. 用户提交 Service 定义(YAML/JSON)

用户通过 kubectl apply -f service.yaml 提交一个 Service 定义,例如:

apiVersion: v1
kind: Service
metadata:
  name: nginx-service
spec:
  selector:
    app: nginx  # 选择标签为 app: nginx 的 Pod
  ports:
    - protocol: TCP
      port: 80       # Service 暴露的端口
      targetPort: 80 # Pod 监听的端口
  type: ClusterIP    # 默认类型

2. API Server 接收并存储 Service 定义

  • API Server 是 Kubernetes 的“大脑”,负责接收所有资源创建/更新请求。
  • Service 的定义会被持久化存储到 etcd(Kubernetes 的分布式键值数据库)。

3. Endpoint Controller 监听 Service 和 Pod 变化

  • Endpoint Controller(运行在 Controller Manager 中)会监听两类资源:
    1. Service 的创建/更新/删除事件。
    2. Pod 的变动(如新建、删除、标签变更)。
  • 关键动作
    • 根据 Service 的 selector(如 app: nginx)筛选匹配的 Pod。
    • 生成 Endpoints 对象(或更新现有的),记录当前匹配 Pod 的 IP 和端口列表。
kubectl get endpoints nginx-service

输出示例:

NAME            ENDPOINTS                         AGE
nginx-service   10.244.1.2:80,10.244.2.3:80      5s
- 如果没有任何 Pod 匹配 `selector`,Endpoints 列表为空(但 Service 仍存在)。

4. kube-proxy 监听 Service 和 Endpoints 变化

  • kube-proxy 运行在每个节点上,负责实现 Service 的流量转发逻辑。
  • 它通过监听 API Server 获取以下信息:
    1. Service 的虚拟 IP(ClusterIP)和端口
    2. Endpoints 中 Pod 的 IP
      列表
  • 根据模式(iptables/IPVS)更新节点网络规则

(1)iptables 模式(默认)

  • kube-proxy 会在节点的 iptables 中插入规则:
    • 当访问 ClusterIP:Port 时,DNAT(目标地址转换)到某个 Pod IP
    • 使用 randomprobability 算法实现负载均衡。
  • 查看规则示例:
iptables-save | grep nginx-service

(2)IPVS 模式(高性能)

  • kube-proxy 直接调用 Linux 内核的 IPVS 模块:
    • 创建虚拟服务器(VIP = ClusterIP)。
    • 添加多个真实服务器(Real Server = Pod IP
      )。
  • 查看规则示例:
ipvsadm -Ln

5. DNS Controller 更新 Service 的 DNS 记录

  • CoreDNS(或 kube-dns)会监听 Service 的创建:
    • 为 Service 分配一个 DNS 名称,格式为 <service-name>.<namespace>.svc.cluster.local
    • 例如,nginx-service.default.svc.cluster.local 解析到 ClusterIP。
  • 集群内的 Pod 可以通过 DNS 名称访问 Service,无需硬编码 IP。

6. 完整流程示例

假设创建一个 ClusterIP 类型的 Service:

  1. 用户提交 YAML
kubectl apply -f nginx-service.yaml
  1. API Server 存储到 etcd
  2. Endpoint Controller 发现 Service 和匹配的 Pod,生成 Endpoints。
  3. kube-proxy 在各节点更新 iptables/IPVS 规则
  4. CoreDNS 添加 Service 的 DNS 记录
  5. 其他 Pod 可通过以下方式访问 Service
    • DNS 名称:nginx-service.default.svc.cluster.local
    • ClusterIP:10.96.123.456:80
    • 流量会被自动转发到后端的 Pod(如 10.244.1.2:80)。

7. 关键组件交互图

+---------+       +------------+       +---------------+       +-----------+
| kubectl | ----> | API Server | ----> | Endpoint Ctrl | ----> | Endpoints |
+---------+       +------------+       +---------------+       +-----------+
                                                                    |
                                                                    v
+------------+       +---------------+       +----------------+     +-----+
| kube-proxy | <---- | Service Watch | <---- | Endpoints Watch | <-- | Pods |
+------------+       +---------------+       +----------------+     +-----+
    |
    v
+------------------+
| iptables/IPVS规则 |
+------------------+

8. 验证 Service 创建是否成功

  • 检查 Service 和 Endpoints:
kubectl get svc nginx-service
kubectl get endpoints nginx-service
  • 检查 DNS 解析(在 Pod 内执行):
nslookup nginx-service.default.svc.cluster.local
  • 检查节点上的 iptables/IPVS 规则:
iptables-save | grep nginx-service  # iptables 模式
ipvsadm -Ln | grep 10.96.123.456    # IPVS 模式

9. 高级场景

(1)Headless Service(无头服务)

  • 设置 clusterIP: None,不分配 ClusterIP。
  • DNS 直接返回 Pod IP 列表(适用于 StatefulSet)。

(2)Session Affinity(会话保持)

  • 通过 sessionAffinity: ClientIP 让同一客户端的请求固定到同一个 Pod。

(3)ExternalName Service

  • 将 Service 映射到外部 DNS(如数据库服务):
kind: Service
spec:
  type: ExternalName
  externalName: mysql.example.com

总结

步骤关键组件动作
1. 提交 YAMLkubectl/API Server接收并存储 Service 定义到 etcd
2. 匹配 PodEndpoint Controller根据 selector 生成 Endpoints 对象
3. 配置转发规则kube-proxy更新 iptables/IPVS 规则
4. 注册 DNSCoreDNS添加 Service 的 DNS 记录
5. 流量代理kube-proxy将请求转发到后端 Pod

Service 的创建过程体现了 Kubernetes 的 声明式 API控制器模式,通过多个组件的协作,最终实现“一组 Pod 的访问抽象”。

Linux Kubernetes 网络 存储 AI