Kevin
1413 words
7 minutes
kubernetes-service

1.NodePort#

img.png

  • 通过NodePort类型的Service,可以将Pod暴露到集群外部,通过Node的IP和NodePort访问Pod
  • 服务于多个Node的集群,可以通过任何Node的IP和NodePort访问Pod
  • NodePort端口范围:30000-32767
apiVersion: v1
kind: Service
metadata:
  name: my-service
spec:
  type: NodePort
  ports:
    - port: 80
      targetPort: 80 # default 与 port一致
      nodePort: 30080 # optional, 30000-32767
  selector: # link with pod definition metadata.labels
    app: my-app

2.ClusterIP#

img_1.png

  • ClusterIP类型的Service,只能在集群内部访问,通过ClusterIP访问Pod, eg.前后端交流, 数据库访问
  • ClusterIP类型的Service,可以通过其他Service访问
apiVersion: v1
kind: Service
metadata:
  name: my-service
spec:
  type: ClusterIP # default
  ports:
    - port: 80 # svc 暴露端口
      targetPort: 80 # 目标pod端口
  selector: # link with pod definition metadata.labels
    app: my-app

3.LoadBalancer#

  • LoadBalancer类型的Service,可以将Pod暴露到集群外部,通过外部负载均衡器访问Pod, 如果在不支持的环境创建,会被默认为NodePort类型的Service
apiVersion: v1
kind: Service
metadata:
  name: my-service
spec:
  type: LoadBalancer
  ports:
    - port: 80
      targetPort: 80
  selector: 
    app: my-app

1. Service 简介#

在 Kubernetes(K8s)中,Service(服务)用于提供稳定的网络访问,即使 Pod 副本数量变化,其访问入口(Service 的 Cluster IP 或外部 IP)仍然保持不变。

Service 的主要目标:

  • 提供稳定访问:Pod 可能会重启、扩缩容,但 Service 提供一个固定的网络入口。
  • 负载均衡:自动将流量分发到后端的多个 Pod。
  • 服务发现:通过 Kubernetes DNS 解析 Service 名称,使应用间通信更容易。

2. Service 工作原理#

Service 通过 Labels 选择后端 Pod,并使用 kube-proxy 进行流量转发。流量调度可基于 iptables 或 IPVS 规则实现。

Service 的基本工作流程如下:

  1. 创建 Service:定义一个 Service,指定选择的 Pod(通过 selector)。
  2. Kube-proxy 监听kube-proxy 监听 API Server 变化,更新 iptables/IPVS 规则。
  3. Pod 访问 Service:应用通过 Service 名称访问时,流量会被负载均衡到后端 Pod。

示意图:

+--------------------+      +--------------------+
|   Service (VIP)   | ---> |  Pod 1 (Backend)  |
|   10.96.0.1       |      |                   |
|   my-service      | ---> |  Pod 2 (Backend)  |
|   selector: app=X |      |                   |
+--------------------+      +--------------------+

3. Service 的核心组件#

  1. kube-proxy
    • 监听 Kubernetes API Server,维护 iptables/IPVS 规则,将 Service IP 映射到后端 Pod。
  2. Endpoints
    • Service 会自动创建 Endpoints 对象,存储可用 Pod 的 IP 和端口。
    • 可通过 kubectl get endpoints 查看。
  3. Kubernetes DNS
    • 通过 CoreDNS 解析 Service 名称,使 Pod 之间能通过 my-service.default.svc.cluster.local 访问。

4. Service 类型#

类型说明访问方式
ClusterIP(默认)仅在集群内部可访问curl http://<service-name>
NodePort通过集群节点 IP 和指定端口访问http://<NodeIP>:<NodePort>
LoadBalancer在云平台创建外部负载均衡http://<External-IP>
ExternalName代理请求到外部 DNShttp://<External-Domain>
Headless无 ClusterIP,直接解析到 Pod IPhttp://pod-ip:port

5. Service 配置示例#

(1)ClusterIP(默认类型,内部访问)#

  • 适用于集群内部 Pod 之间的通信: ![[Pasted image 20250309153854.png]]
apiVersion: v1
kind: Service
metadata:
  name: my-service
spec:
  selector:
    app: my-app
  ports:
    - protocol: TCP
      port: 80      # Service 端口
      targetPort: 8080  # Pod 端口
  • 验证 Service:

    kubectl get svc my-service
    kubectl get endpoints my-service
    

(2)NodePort(暴露到集群外部)#

![[Pasted image 20250309153814.png]]

  • 适用于集群外部访问,Kubernetes 自动分配 30000-32767 端口:
apiVersion: v1
kind: Service
metadata:
  name: my-service
spec:
  type: NodePort
  selector:
    app: my-app
  ports:
    - protocol: TCP
      port: 80
      targetPort: 8080
      nodePort: 30080  # 可手动指定端口(可选)
  • 访问方式:

    curl http://<NodeIP>:30080
    

(3)LoadBalancer(云平台自动创建外部负载均衡)#

  • 适用于 AWS、GCP、Azure 等云环境:
apiVersion: v1
kind: Service
metadata:
  name: my-service
spec:
  type: LoadBalancer
  selector:
    app: my-app
  ports:
    - protocol: TCP
      port: 80
      targetPort: 8080
  • 访问方式:

    curl http://<External-IP>
    

(4)ExternalName(代理外部服务)#

  • 适用于 Kubernetes 内部访问外部服务,如 example.com
apiVersion: v1
kind: Service
metadata:
  name: my-external-service
spec:
  type: ExternalName
  externalName: example.com
  • 访问方式:

    curl http://my-external-service
    

(5)Headless Service(无 ClusterIP,直接访问 Pod)#

被创建后并不会被分配一个 VIP,而是会以 DNS 记录的方式暴露出它所代理的 Pod: <pod-name>.<svc-name>.<namespace>.svc.cluster.local

  • 适用于 StatefulSet 或 DNS 直接解析:
apiVersion: v1
kind: Service
metadata:
  name: headless-service
spec:
  clusterIP: None
  selector:
    app: my-app
  ports:
    - port: 80
      targetPort: 8080
  • 访问方式:

    nslookup headless-service
    

6. Service 关键参数#

参数说明
selector选择匹配的 Pod
ports.portService 监听的端口
ports.targetPortPod 的应用端口
typeService 类型(ClusterIP、NodePort、LoadBalancer、ExternalName)
sessionAffinityClientIP 方式保持会话

7. Service 进阶#

  1. Session Affinity(会话保持)

    • 默认情况下,Service 负载均衡到不同 Pod,可以开启 基于 IP 的粘性会话
    • 将同一客户端的请求始终路由到同一个 Pod
    • 工作原理: Kubernetes Service 会记录客户端 IP 与后端 Pod 的对应关系,并将来自同一 IP 的请求始终路由到该 Pod。
    spec:
      sessionAffinity: ClientIP
    
  2. Health Check(健康检查)

    • 通过 readinessProbe 确保 Service 仅发送流量到健康 Pod:
    • readinessProbe 用于检测 Pod 是否准备好接收流量。只有通过 readinessProbe 检查的 Pod 才会被添加到 Service 的后端 Endpoint 列表中。
    • 重要性: 确保 Service 只将流量发送到运行正常的 Pod,避免将流量发送到尚未启动或运行异常的 Pod。
    readinessProbe: #service会定期的通过HTTP的GET方法,去访问POD的8080端口的/health路径,如果返回的状态码是200,则表明这个POD是健康的
      httpGet:
        path: /health
        port: 8080
    
  3. 与 Ingress 结合

    • 用于管理外部流量到集群内部 Service 的路由
    • 关系:
      • Ingress 通过 Service 将外部流量路由到后端的 Pod。
      • Service 负责在 Pod 之间进行负载均衡,而 Ingress 负责根据主机名、路径等信息将流量路由到不同的 Service。
    • Ingress 通过 Service 将外部流量路由到内部 Pod:
    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
      name: my-ingress
    spec:
      rules:
        - host: my-app.example.com #定义了当请求路径以 / 开头时,将流量转发到名为 my-service 的 Service 的 80 端口。
          http:
            paths:
              - path: /
                pathType: Prefix
                backend:
                  service:
                    name: my-service
                    port:
                      number: 80
    

8. Service Debug & 排查#

  1. 检查 Service 是否创建成功

    kubectl get svc my-service
    
  2. 查看 Service 对应的 Endpoints

    kubectl get endpoints my-service
    
  3. 查看 Pod 是否能访问 Service

    kubectl exec -it <pod-name> -- curl http://my-service:80
    
  4. 检查 kube-proxy 规则

    iptables -t nat -L -n | grep my-service
    
kubernetes-service
https://fuwari.vercel.app/posts/kubernetes-service/kubernetes-service/
Author
Kevin
Published at
2024-12-17