结合文档内容,从核心作用、底层组件、三类IP、四大Service类型、Endpoints、CoreDNS、企业实战逐层拆解,搭配完整实验、流程、坑点,零基础也能看懂。


一、先搞懂:为什么必须用 Service?

1. Pod 的三大天生缺陷(痛点)

  1. Pod IP 不固定
    Pod 重建、漂移到其他节点后,IP 会随机变化。如果业务直接写死 Pod IP,服务就会失联。
  2. 无法统一入口
    一个应用通常多副本(多个Pod),客户端没法逐个记所有 Pod IP,需要统一访问入口。
  3. 集群外默认无法访问 Pod
    Pod 网络是集群内部私有网段,外网/集群外主机不能直接连通。

2. Service 核心定位

Service 是 K8s 四层负载均衡 + 固定访问入口,工作在 TCP/UDP 四层(不解析HTTP协议内容)。
核心能力:

  • 提供固定虚拟IP(ClusterIP),永不变化;
  • 自动关联一组 Pod,实现负载均衡
  • 实时感知 Pod 上下线,自动更新后端地址;
  • 配合 kube-proxy 实现流量转发;
  • 结合 CoreDNS 实现服务发现(域名访问)。

3. 核心协作组件(必须理解)

(1)kube-proxy

每个 K8s 节点默认常驻进程,核心职责:

  1. 通过 watch 监听 apiserver,实时感知 Service、Pod 变化;
  2. 在当前节点生成 iptables / IPVS 转发规则
  3. 接收访问 Service 的流量,转发到后端正常 Pod。

前文讲过:kube-proxy 支持 iptables(默认)和 IPVS 两种模式,大规模集群推荐 IPVS。

(2)Endpoints(端点)

Service 不会直接绑定 Pod,而是通过 Endpoints 记录后端所有正常 Pod 的 IP+端口

  • 由 Service 的 selector 标签选择器自动维护;
  • Pod 新增/删除/就绪状态变化,Endpoints 会自动同步;
  • 查看命令:kubectl get ep / kubectl describe ep
(3)CoreDNS

集群内置 DNS 服务,实现服务域名解析
集群内所有 Service 都会自动生成域名,无需记 IP。
标准域名格式:

<服务名>.<命名空间>.svc.cluster.local

二、K8s 集群三类网络 IP(重点区分)

集群内存在三套独立网络,互不冲突:

网络类型名称特点作用范围
节点网络Node IP物理/虚拟机网卡真实IP,永久固定集群内外均可访问,用于节点通信、NodePort/LoadBalancer
Pod 网络Pod IPPod 内部IP,动态变化仅集群内部节点/Pod 互通
服务网络ClusterIPService 虚拟IP,集群内部虚拟地址,不绑定物理网卡仅集群内部访问

示例:

  • NodeIP:192.168.1.63(宿主机网卡地址)
  • PodIP:10.244.187.76(Calico/Flannel 分配)
  • ClusterIP:10.96.0.1(系统默认 kubernetes 服务)

关键:ClusterIP 是纯内核虚拟IPip addr 在节点上看不到网卡绑定,只存在于转发规则中。


三、Service 资源清单核心字段详解

执行 kubectl explain service 查看原生字段,挑生产常用字段逐一解释:

1. 基础字段

apiVersion: v1       # Service 属于 core/v1 核心资源
kind: Service       # 资源类型
metadata:
  name: my-svc      # Service 名称
  namespace: default# 命名空间

2. spec 核心字段

1)selector 标签选择器

用来匹配后端 Pod,规则和 Deployment/ReplicaSet 完全一致:

  • 匹配 labels 相符的 Pod;
  • 匹配成功后,自动把 Pod IP 写入 Endpoints;
  • 不写 selector 时,需要手动创建 Endpoints(对接外部服务场景)。
2)ports 端口配置(三层端口必记)
ports:
- port: 80        # ① Service 内部端口(ClusterIP 监听端口,集群内访问用)
  targetPort: 80  # ② 后端 Pod/容器的端口(流量最终转发到这里)
  nodePort: 30380 # ③ 节点端口(NodePort 类型专用,集群外访问)
  protocol: TCP   # 协议:TCP/UDP,默认TCP

三者流转关系:
客户端 → NodeIP:nodePort → ClusterIP:port → PodIP:targetPort

3)type Service 类型(四大核心类型)
type: ClusterIP / NodePort / LoadBalancer / ExternalName

四大类型用途、访问范围、使用场景下文逐个实验讲解。

4)sessionAffinity 会话亲和

默认 None:轮询负载均衡;
设置 ClientIP会话保持,同一客户端IP请求始终转发到同一个Pod。
适用场景:需要会话留存的业务(传统Web会话)。


四、四大 Service 类型 完整实验 + 原理

环境统一前置:
集群:1 Master + 多个 Worker,Calico 网络,镜像已导入;
所有实验基于 Nginx Deployment 多副本演示。


类型一:ClusterIP(默认类型)

1. 作用

仅集群内部访问,分配一个固定 ClusterIP 虚拟地址。

  • 只能在集群节点、Pod 内部访问;
  • 集群外部(办公电脑、外网)无法直接访问;
  • 纯四层负载均衡,是集群内部服务互通标准方案

2. 实验步骤

步骤1:创建 Nginx Deployment(多副本)

# pod_test.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-nginx
spec:
  replicas: 2
  selector:
    matchLabels:
      run: my-nginx
  template:
    metadata:
      labels:
        run: my-nginx
    spec:
      containers:
      - name: my-nginx
        image: nginx
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 80
        # 健康探测(保证就绪Pod才接入Endpoints)
        startupProbe:
          httpGet: {path: /, port: 80}
          initialDelaySeconds: 60
          periodSeconds: 5
          timeoutSeconds: 10
        livenessProbe:
          httpGet: {path: /, port: 80}
          initialDelaySeconds: 60
          periodSeconds: 5
          timeoutSeconds: 10
        readinessProbe:
          httpGet: {path: /, port: 80}
          initialDelaySeconds: 60
          periodSeconds: 5
          timeoutSeconds: 10

执行创建:

kubectl apply -f pod_test.yaml
# 查看Pod及IP
kubectl get pods -o wide -l run=my-nginx

步骤2:创建 ClusterIP 类型 Service

# service_test.yaml
apiVersion: v1
kind: Service
metadata:
  name: my-nginx
  labels:
    run: my-nginx
spec:
  type: ClusterIP  # 默认类型,可省略
  selector:
    run: my-nginx  # 匹配Pod标签
  ports:
  - port: 80        # Service内部端口
    targetPort: 80  # 容器端口
    protocol: TCP
kubectl apply -f service_test.yaml
# 查看Service
kubectl get svc

输出示例:

NAME       TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)   AGE
my-nginx   ClusterIP   10.99.198.177   <none>        80/TCP    5m

步骤3:查看 Endpoints(核心验证)

kubectl get ep my-nginx
kubectl describe svc my-nginx

Endpoints 会列出两个 Pod 的 IP:80,证明 Service 已自动关联后端。

步骤4:访问测试

  1. 集群节点内访问(Master/Worker 主机)
curl 10.99.198.177:80

正常返回 Nginx 页面。

  1. Pod 内部跨Pod访问
    进入任意 Pod,用 Service IP / 域名访问:
kubectl exec -it <pod-name> -- /bin/bash
curl my-nginx.default.svc.cluster.local

域名解析成功,证明 CoreDNS 正常工作。

3. 关键特性验证:Pod 重建后 IP 变化

# 删除一个Pod,Deployment自动重建新Pod
kubectl delete pod <旧pod名>
kubectl get pods -o wide -l run=my-nginx

👉 现象:新Pod IP 改变,但 ClusterIP 完全不变,访问依旧正常。
这就是 Service 解决 Pod IP 漂移的核心价值。

4. 访问范围总结

✅ 集群节点、Pod 可访问
❌ 集群外物理机/浏览器 无法访问


类型二:NodePort(节点端口)

1. 作用

ClusterIP 基础上,在所有节点上开放一个固定端口,实现集群外部访问

  • 端口范围:默认 30000 ~ 32767(系统预留);
  • 流量路径:外网客户端 → 任意节点IP:NodePort → ClusterIP → 后端Pod
  • 缺点:端口有限、节点IP暴露,适合测试/小型业务,不适合生产高并发

2. 实验步骤

步骤1:编写 NodePort 类型 Service

# service_nodeport.yaml
apiVersion: v1
kind: Service
metadata:
  name: my-nginx-nodeport
spec:
  type: NodePort
  selector:
    run: my-nginx-nodeport
  ports:
  - port: 80          # Service内部端口
    targetPort: 80    # 容器端口
    nodePort: 30380   # 手动指定节点端口(可选,不写则自动随机分配)
    protocol: TCP

搭配对应 Deployment(前文已有),执行创建:

kubectl apply -f pod_nodeport.yaml
kubectl apply -f service_nodeport.yaml

步骤2:查看 Service

kubectl get svc

输出:

my-nginx-nodeport   NodePort   10.100.156.7   <none>   80:30380/TCP

格式 80:30380port:nodePort

步骤3 多场景访问测试

  1. 集群内部:依旧可以用 ClusterIP 访问
curl 10.100.156.7
  1. 集群外部(办公电脑/浏览器)
    使用任意节点公网/内网IP + 30380 端口访问:
# 节点IP:30380
curl 192.168.40.180:30380

浏览器直接打开 http://节点IP:30380 也可正常访问。

3. 流量转发原理(结合 kube-proxy)

节点上查看 IPVS/iptables 规则:

ipvsadm -Ln

可以看到 NodePort 端口对应的转发规则,流量被均衡分发到多个 Pod IP。

4. 优缺点 & 生产建议

✅ 优点:配置简单,快速对外暴露服务
❌ 缺点:

  1. 端口区间固定,大规模服务容易端口耗尽;
  2. 依赖节点IP,节点故障则对应入口不可用;
  3. 四层转发,无七层能力。
    👉 生产:测试环境首选,生产前端业务优先用 Ingress

类型三:ExternalName(外部名称服务)

1. 作用

集群内域名别名,不创建 ClusterIP、不做负载均衡。
核心场景:

  1. 跨命名空间访问服务
  2. 对接集群外部域名/第三方服务。

原理:
把当前 Service 直接映射为另一个完整域名,集群内访问该 Service 等同于访问目标域名。

2. 实验:跨 Namespace 访问

步骤1:创建两个命名空间

kubectl create ns nginx-ns

步骤2:在 nginx-ns 下创建 Nginx Deployment + ClusterIP Service

# server_nginx.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx
  namespace: nginx-ns
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx
        imagePullPolicy: IfNotPresent
# nginx_svc.yaml
apiVersion: v1
kind: Service
metadata:
  name: nginx-svc
  namespace: nginx-ns
spec:
  type: ClusterIP
  selector:
    app: nginx
  ports:
  - port: 80
    targetPort: 80

创建并验证:

kubectl apply -f server_nginx.yaml -n nginx-ns
kubectl apply -f nginx_svc.yaml -n nginx-ns
kubectl get svc -n nginx-ns

该服务完整域名:nginx-svc.nginx-ns.svc.cluster.local

步骤3:在 default 命名空间创建 ExternalName 服务

# client_svc.yaml
apiVersion: v1
kind: Service
metadata:
  name: client-svc
spec:
  type: ExternalName
  externalName: nginx-svc.nginx-ns.svc.cluster.local  # 目标完整域名
  ports:
  - port: 80
kubectl apply -f client_svc.yaml

步骤4:测试访问

在 default 命名空间启动 busybox Pod 测试:

kubectl exec -it <busybox-pod> -- sh
# 访问当前Service,等价于跨命名空间访问nginx-svc
wget -q -O - client-svc
# 直接访问原域名对比
wget -q -O - nginx-svc.nginx-ns.svc.cluster.local

两者返回结果完全一致。

3. 补充场景:对接外网域名

举例:集群内统一用 Service 别名访问 baidu.com

apiVersion: v1
kind: Service
metadata:
  name: baidu
spec:
  type: ExternalName
  externalName: www.baidu.com
  ports:
  - port: 80

集群内直接 curl baidu 即可。


类型四:LoadBalancer(负载均衡器)

1. 作用

在 NodePort 基础上,对接云厂商公有负载均衡(阿里云/腾讯云/AWS 等)。

  • 云平台会分配独立公网IP;
  • 外部流量 → 云LB → 集群节点 → Pod;
  • 仅限公有云 K8s 使用,自建物理集群(无云LB)无法使用。

2. 简要说明

  1. 自建机房/裸金属 K8s:不支持 LoadBalancer
  2. 公有云创建该类型 Service 后,云平台自动分配外网IP;
  3. 访问方式:外网IP + 服务端口;
  4. 生产公有云业务常用,结合云LB的健康检查、防火墙能力。

五、高阶实战:手动 Service + Endpoint 对接集群外部服务

场景:K8s 集群内应用访问集群外独立 MySQL(物理机/虚拟机)
核心:Service 不配置 selector手动创建 Endpoints 指向外部IP。

步骤1:集群外安装 MySQL(示例节点IP:192.168.40.182)

略(安装 mariadb / mysql)。

步骤2:创建无 selector 的 Service

# mysql_service.yaml
apiVersion: v1
kind: Service
metadata:
  name: mysql
spec:
  type: ClusterIP
  ports:
  - port: 3306
    targetPort: 3306
kubectl apply -f mysql_service.yaml
# 此时 Endpoints 为空
kubectl describe svc mysql

步骤3:手动创建 Endpoints 指向外部MySQL

# mysql_endpoint.yaml
apiVersion: v1
kind: Endpoints
metadata:
  name: mysql  # 名称必须和 Service 完全一致
subsets:
- addresses:
  - ip: 192.168.40.182  # 外部MySQL真实IP
  ports:
  - port: 3306
kubectl apply -f mysql_endpoint.yaml

步骤4 验证

kubectl describe svc mysql
# Endpoints 已变为 192.168.40.182:3306

集群内 Pod/节点 访问 mysql:3306 即可连通外部数据库。

核心规则:

  1. Service 和 Endpoints 名称必须完全相同
  2. 不写 selector 则不会自动管理 Pod,由人工维护 Endpoints;
  3. 常用于对接遗留物理服务、外部中间件。

六、CoreDNS 服务发现 完整验证

1. CoreDNS 作用

集群内置 DNS 组件,所有 Service 自动解析为域名,格式:

<服务名>.<命名空间>.svc.cluster.local

同命名空间可简写服务名,跨命名空间写完整域名。

2. 验证实验

  1. 查看集群 CoreDNS Pod
kubectl get pods -n kube-system | grep coredns
  1. 启动测试 dig Pod(DNS解析工具)
# dig.yaml
apiVersion: v1
kind: Pod
metadata:
  name: dig
spec:
  containers:
  - name: dig
    image: xianchao/dig
    command: ["sleep","3600"]
    imagePullPolicy: IfNotPresent
  restartPolicy: Always
kubectl apply -f dig.yaml
  1. 进入 Pod 解析 Service 域名
kubectl exec -it dig -- nslookup my-nginx
# 完整域名解析
nslookup my-nginx.default.svc.cluster.local

解析结果会返回 Service 的 ClusterIP,证明 DNS 服务正常。


七、四大 Service 类型 对比总结

类型访问范围核心用途适用场景限制
ClusterIP仅集群内部内部服务互通、四层负载微服务内部调用外网无法访问
NodePort集群内外均可节点端口暴露服务测试环境、临时对外端口30000-32767,节点单点故障
LoadBalancer全网(公网IP)云厂商负载均衡公有云生产业务仅云K8s支持
ExternalName集群内部域名别名、跨命名/外网对接跨NS访问、对接外部域名无负载均衡,仅域名转发

八、生产最佳实践 & 常见坑点

1. 最佳实践

  1. 内部微服务:统一使用 ClusterIP + 域名访问;
  2. 测试对外访问:临时用 NodePort,用完及时关闭;
  3. 公有云生产对外:优先 LoadBalancer + 云厂商能力;
  4. 自建机房生产对外:不使用 NodePort,统一搭配 Ingress(七层网关)
  5. 对接外部中间件:使用「无selector Service + 手动Endpoints」;
  6. 跨命名空间调用:优先 ExternalName 或直接使用完整域名。

2. 常见故障排查

  1. 能通 ClusterIP,无法访问 Pod
    排查:Pod 就绪探针、防火墙、容器端口是否匹配 targetPort
  2. NodePort 外网访问超时
    排查:节点防火墙/安全组是否放行 30000-32767 端口。
  3. Service 正常但 Endpoints 为空
    排查:selector 标签和 Pod labels 不匹配。
  4. 域名解析失败
    排查:CoreDNS Pod 是否正常、集群DNS配置。

3. 补充:Service 与 前文知识关联

  1. Service 依赖 kube-proxy(iptables/IPVS)做转发;
  2. Service 依赖 Pod 就绪探针,只有 Ready 的Pod才会加入 Endpoints;
  3. 配合 Deployment 实现:Pod 漂移/重建后,服务入口始终稳定。当前文件内容过长,豆包只阅读了前 34%。
Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐