kubernetes核心概念 Service

零基础入门 Kubernetes Service:概念、YAML 配置示例与常见问题排查指南

一、Kubernetes Service 的核心概念

Kubernetes Service 是集群中一组 Pod 的逻辑抽象,通过静态 IP 地址和 DNS 名称提供稳定的网络访问入口。其核心价值在于:

  1. 解耦生命周期:Pod 可能因崩溃、扩容或缩容频繁重建,但 Service 的 IP 和 DNS 名称保持不变,避免客户端频繁更新访问地址。
  2. 负载均衡:自动将流量分发到后端 Pod,例如一个 Service 可关联 3 个 Nginx Pod,客户端请求会被均衡分配到不同实例。
  3. 服务发现 :通过 DNS 名称(如 my-service.default.svc.cluster.local)实现内部服务间的自动发现,无需硬编码 IP。

典型应用场景

  • 微服务架构:订单服务通过 Service 访问用户服务,无需关心用户服务的 Pod 数量或位置。
  • 数据库访问:应用通过 Service 连接 MySQL 集群,即使主从切换或扩容,访问地址不变。
  • 外部流量接入:通过 NodePort 或 LoadBalancer 类型 Service 将集群内服务暴露给外部用户。

二、Service 的 4 种类型及 YAML 配置示例

1. ClusterIP(默认类型)

用途 :仅在集群内部访问,适用于后端微服务间的通信。
配置示例:

yaml 复制代码
yaml
apiVersion: v1
kind: Service
metadata:
  name: backend-service
spec:
  selector:
    app: backend  # 匹配标签为 app=backend 的 Pod
  ports:
    - protocol: TCP
      port: 80      # Service 的端口
      targetPort: 8080  # Pod 的端口
  type: ClusterIP  # 可省略,默认值

验证命令:

csharp 复制代码
bash
kubectl get svc backend-service  # 查看 Service 的 ClusterIP(如 10.96.123.45)
kubectl describe svc backend-service  # 检查 Endpoints 是否包含 Pod IP

2. NodePort

用途 :通过集群节点的固定端口暴露服务,适用于开发测试或裸金属集群。
配置示例:

yaml 复制代码
yaml
apiVersion: v1
kind: Service
metadata:
  name: web-service
spec:
  selector:
    app: web
  ports:
    - protocol: TCP
      port: 80
      targetPort: 8080
      nodePort: 30080  # 默认范围 30000-32767,可省略自动分配
  type: NodePort

验证命令:

csharp 复制代码
bash
kubectl get svc web-service  # 查看 NodePort 端口(如 30080)
curl http://<任意节点IP>:30080  # 从集群外部访问

3. LoadBalancer

用途 :在云环境中自动创建外部负载均衡器(如 AWS ELB、GCP LB),适用于生产环境。
配置示例:

yaml 复制代码
yaml
apiVersion: v1
kind: Service
metadata:
  name: public-service
spec:
  selector:
    app: frontend
  ports:
    - protocol: TCP
      port: 80
      targetPort: 80
  type: LoadBalancer

验证命令:

arduino 复制代码
bash
kubectl get svc public-service  # 查看 EXTERNAL-IP(如 a1b2c3d4.us-west-2.elb.amazonaws.com)
curl http://<EXTERNAL-IP>  # 通过负载均衡器访问

4. ExternalName

用途 :将 Service 映射到外部 DNS 名称,适用于访问集群外部服务(如数据库)。
配置示例:

yaml 复制代码
yaml
apiVersion: v1
kind: Service
metadata:
  name: external-db
spec:
  type: ExternalName
  externalName: mysql.example.com  # 外部数据库的 DNS 名称

验证命令:

bash 复制代码
bash
kubectl exec -it <任意Pod> -- nslookup external-db  # 解析到 mysql.example.com

三、常见问题排查指南

问题 1:Service 无法访问

排查步骤:

  1. 检查 Service 状态:

    csharp 复制代码
    bash
    kubectl get svc <service-name> -o wide  # 确认 IP 和端口
    kubectl describe svc <service-name>  # 检查 Events 和 Endpoints
    • 若 Endpoints 为空,说明 Selector 未匹配到 Pod,需检查 Pod 标签是否与 Service 的 spec.selector 一致。
  2. 验证 Pod 状态:

    ini 复制代码
    bash
    kubectl get pods -l app=<label-value>  # 检查关联 Pod 是否存在
    kubectl logs <pod-name>  # 查看 Pod 日志是否有错误
  3. 测试网络连通性:

    ruby 复制代码
    bash
    kubectl run -it --rm debug --image=busybox --restart=Never -- sh
    # 在调试容器中执行
    ping <service-cluster-ip>  # 测试 ClusterIP 可达性
    wget <service-cluster-ip>:<port>  # 测试端口连通性

问题 2:NodePort 类型 Service 外部无法访问

排查步骤:

  1. 检查节点端口监听:

    perl 复制代码
    bash
    # 在集群节点上执行
    netstat -tulnp | grep <nodePort>  # 确认端口被 kube-proxy 监听
  2. 验证防火墙规则:

    • 云平台:检查安全组是否放行 NodePort 端口(如 30080)。
    • 裸金属集群:使用 iptables -L -n 检查是否有 DROP 规则。
  3. 测试从节点直接访问:

    bash 复制代码
    bash
    curl http://localhost:<nodePort>  # 从节点本地访问

问题 3:DNS 解析失败

排查步骤:

  1. 检查 CoreDNS 状态:

    ini 复制代码
    bash
    kubectl get pods -n kube-system -l k8s-app=kube-dns
    kubectl logs <coredns-pod-name> -n kube-system  # 查看日志是否有错误
  2. 测试 DNS 解析:

    ini 复制代码
    bash
    kubectl run -it --rm dns-test --image=busybox --restart=Never -- sh
    # 在调试容器中执行
    nslookup <service-name>.<namespace>.svc.cluster.local  # 完整 FQDN 解析
    nslookup <service-name>  # 同命名空间内可省略后缀

问题 4:负载均衡不均匀

排查步骤:

  1. 检查 Service 的 sessionAffinity:

    yaml 复制代码
    yaml
    spec:
      sessionAffinity: ClientIP  # 默认 None(轮询),可改为 ClientIP 固定 IP 到同一 Pod
  2. 验证 Pod 资源使用:

    ini 复制代码
    bash
    kubectl top pods -l app=<label-value>  # 检查 CPU/内存是否均衡
  3. 检查网络插件:

    • 若使用 Calico/Flannel,检查 kube-proxy 日志是否有 iptables 规则更新失败:

      perl 复制代码
      bash
      kubectl logs <kube-proxy-pod-name> -n kube-system | grep "error"

四、最佳实践

  1. 标签设计 :使用 app.kubernetes.io/name、app.kubernetes.io/version 等标准标签,避免随意命名。
  2. 端口命名 :在 Service 的 ports 中为端口添加名称(如 http、grpc),提高可读性。
  3. 健康检查 :为后端 Pod 配置 livenessProbe 和 readinessProbe,确保 Service 只路由到健康实例。
  4. 资源限制:为 Service 关联的 Pod 设置 CPU/内存请求和限制,防止单个 Pod 占用过多资源。

通过掌握 Service 的核心概念、配置方法和排查技巧,您可以高效管理 Kubernetes 集群中的服务通信,为后续部署复杂应用(如 Istio 服务网格、Knative 无服务器)打下坚实基础。

相关推荐
YYYing.2 小时前
【K8s系列 (一) 】Docker与容器(上篇)
docker·云原生·容器·kubernetes
weirong8 小时前
给 Operator 加 Admission Webhook 踩的 4 个坑(其中 3 个本可以不踩)
kubernetes
Goboy10 小时前
夯爆了,我被一个一句话接入的免费可观测平台策反了,那一刻我决定放弃用了3年的Prometheus
后端·docker·kubernetes
吴声子夜歌10 小时前
Kubernetes权威指南——深入掌握Service(一)
云原生·容器·kubernetes
weirong1 天前
图解 client-go Informer:手写一个 mini-Informer 才敢说懂
kubernetes
.冰块.1 天前
流量大了自动加 Pod!K8s HPA 扩缩容与 ResourceQuota/LimitRange 资源管控实战
linux·云原生·容器·kubernetes·hpa·quota·limitrange
无言听风雨丶2 天前
Linux 容器本质探秘:Cgroup 与 Namespace 深度解析与实战
linux·运维·服务器·kubernetes
无言听风雨丶2 天前
Kubernetes GitOps 持续交付实战:用 Argo CD 让 Git 成为集群事实源
git·elasticsearch·kubernetes
无言听风雨丶3 天前
Kubernetes 控制平面深度剖析:从 kubectl apply 到 etcd 写入的全链路
平面·kubernetes·etcd
openFuyao3 天前
openFuyao x 复旦大学软件工程实验室 Panel 回顾:Agentic时代,集群调度技术体系将如何演进?
kubernetes·openfuyao