跳转到内容

Kubernetes服务

来自代码酷

Kubernetes服务[编辑 | 编辑源代码]

介绍[编辑 | 编辑源代码]

Kubernetes服务(Service)是Kubernetes中的核心概念之一,用于为一组功能相同的Pod提供稳定的网络访问入口。由于Pod是临时性的(可能会被调度、重启或替换),直接通过Pod IP访问是不可靠的。服务通过抽象的方式,为Pod提供固定的虚拟IP(ClusterIP)、DNS名称或外部可访问的端点(NodePort/LoadBalancer),从而确保应用程序的可靠访问。

服务的主要功能包括:

  • 负载均衡:将流量均匀分配到后端Pod。
  • 服务发现:通过DNS或环境变量让其他服务发现当前服务。
  • 解耦:客户端无需关心后端Pod的具体位置或状态变化。

服务类型[编辑 | 编辑源代码]

Kubernetes支持以下服务类型:

类型 描述 适用场景
ClusterIP 默认类型,分配集群内部IP,仅集群内可访问 内部服务通信
NodePort 在每个节点上开放静态端口(30000-32767),外部可通过节点IP:端口访问 开发测试或简单外部访问
LoadBalancer 通过云提供商的负载均衡器分配外部IP 生产环境外部访问
ExternalName 将服务映射到外部DNS名称(如数据库服务) 集成外部服务

服务工作原理[编辑 | 编辑源代码]

服务通过标签选择器(Label Selector)关联一组Pod。当创建服务时,Kubernetes会创建对应的Endpoints对象,动态更新后端Pod的IP列表。

graph LR Client -->|请求| Service[Service: my-svc] Service -->|负载均衡| Pod1[Pod A] Service -->|负载均衡| Pod2[Pod B] Service -->|负载均衡| Pod3[Pod C]

流量路由流程[编辑 | 编辑源代码]

1. 客户端向服务的虚拟IP(ClusterIP)发送请求。 2. kube-proxy组件通过iptables/ipvs规则将流量转发到后端Pod。 3. 如果使用NodePort或LoadBalancer,流量会先到达节点或外部负载均衡器。

YAML配置示例[编辑 | 编辑源代码]

以下是一个ClusterIP服务的定义示例:

apiVersion: v1
kind: Service
metadata:
  name: my-web-service
spec:
  type: ClusterIP  # 可省略,默认为ClusterIP
  selector:
    app: nginx     # 选择标签为app=nginx的Pod
  ports:
    - protocol: TCP
      port: 80     # 服务端口
      targetPort: 80  # Pod上的端口

创建后,集群内其他组件可通过以下方式访问该服务:

  • DNS名称:my-web-service.default.svc.cluster.local
  • 环境变量:MY_WEB_SERVICE_SERVICE_HOST

实际案例[编辑 | 编辑源代码]

案例1:部署Web应用[编辑 | 编辑源代码]

假设有一个三副本的Nginx Deployment:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:alpine
        ports:
        - containerPort: 80

为其创建NodePort服务以允许外部访问:

apiVersion: v1
kind: Service
metadata:
  name: nginx-service
spec:
  type: NodePort
  selector:
    app: nginx
  ports:
    - protocol: TCP
      port: 80
      targetPort: 80
      nodePort: 30080  # 手动指定(可选)

此时可通过任意节点IP的30080端口访问Nginx。

案例2:数据库服务抽象[编辑 | 编辑源代码]

对于需要连接外部数据库的场景,可以使用ExternalName:

apiVersion: v1
kind: Service
metadata:
  name: mysql-service
spec:
  type: ExternalName
  externalName: mysql.prod.example.com  # 实际数据库地址

应用程序只需连接mysql-service即可,无需关心实际数据库位置变化。

高级主题[编辑 | 编辑源代码]

会话保持(Session Affinity)[编辑 | 编辑源代码]

通过设置sessionAffinity: ClientIP,可将同一客户端的请求始终路由到同一个Pod:

spec:
  sessionAffinity: ClientIP
  sessionAffinityConfig:
    clientIP:
      timeoutSeconds: 3600

Headless服务[编辑 | 编辑源代码]

当不需要负载均衡时(如StatefulSet),可创建无ClusterIP的服务:

spec:
  clusterIP: None  # 标记为Headless

客户端将直接获取所有后端Pod的IP列表。

服务拓扑路由[编辑 | 编辑源代码]

Kubernetes 1.17+支持基于节点拓扑的路由:

spec:
  topologyKeys:
    - "kubernetes.io/hostname"
    - "topology.kubernetes.io/zone"

数学原理[编辑 | 编辑源代码]

服务的负载均衡可建模为流量分配问题。设:

  • n个后端Pod
  • i个Pod的权重为wi(默认为1)

则请求分配到Podi的概率为:

Pi=wij=1nwj

常见问题[编辑 | 编辑源代码]

Q:服务与Ingress有什么区别? A:服务是L4(TCP/UDP)抽象,而Ingress是L7(HTTP/HTTPS)路由规则,通常需要配合Ingress Controller使用。

Q:如何调试服务无法访问的问题? 1. 检查Endpoints是否包含预期Pod:kubectl get endpoints <service-name> 2. 检查kube-proxy是否正常运行 3. 验证网络策略(NetworkPolicy)是否允许流量

总结[编辑 | 编辑源代码]

Kubernetes服务是微服务架构中的关键组件,它:

  • 提供稳定的访问端点
  • 实现自动负载均衡
  • 支持多种暴露方式
  • 与服务发现机制深度集成

通过合理使用服务,开发者可以构建高可用、松耦合的分布式系统。