Kubernetes中为一组Pod提供稳定访问入口与负载均衡的抽象资源
Service 是 Kubernetes 对一组 Pod 的抽象,它为这些 Pod 提供一个固定的虚拟 IP 与 DNS 名称,并在后端 Pod 之间做四层负载均衡。Pod 会被反复创建销毁,IP 随之变化,而 Service 的名字和地址保持不变,调用方因此不必关心后端实例的增减。
Service 本身不是进程,也不负责转发流量。真正干活的是每个节点上的 kube-proxy,它监听 Service 与 EndpointSlice 的变化,把转发规则写进 iptables 或 IPVS,由内核完成 DNAT。所以 Service 不通时,排查方向通常是 selector 匹配、Endpoints 列表和 kube-proxy 规则。
ClusterIP 默认类型,分配一个仅集群内可达的虚拟 IP,适合集群内部服务互调
NodePort 在 ClusterIP 基础上,于每个节点上开放一个静态端口(默认 30000-32767)
LoadBalancer 在 NodePort 基础上,向云厂商申请外部负载均衡器,生产环境对外暴露的标准做法
ExternalName 不做任何代理,把 Service 名称 CNAME 到集群外的域名,常用于引用外部数据库
此外还有一种特殊形态:Headless Service,即把 clusterIP 显式设为 None。它不分配虚拟 IP,不做负载均衡,DNS 查询会直接返回全部后端 Pod 的 IP 列表,供 StatefulSet 绑定固定网络标识或客户端自行选择。
kubectl get service [名称] [选项]
kubectl expose deployment [名称] --port=80 --target-port=8080
kubectl port-forward service/[名称] [本地端口]:[服务端口]
kubectl delete service [名称]
ClusterIP 是最常见的形态:
apiVersion: v1
kind: Service
metadata:
name: nginx-svc
namespace: default
spec:
type: ClusterIP
selector:
app: nginx
ports:
- name: http
protocol: TCP
port: 80 # Service 自身暴露的端口,集群内访问用的就是它
targetPort: 8080 # 容器实际监听的端口,不写则默认等于 port
NodePort,集群外可通过 <任意节点IP>:30080 访问:
apiVersion: v1
kind: Service
metadata:
name: nginx-nodeport
spec:
type: NodePort
selector:
app: nginx
ports:
- port: 80
targetPort: 8080
nodePort: 30080 # 省略则从 30000-32767 中随机分配
LoadBalancer,由云控制器向厂商申请 ELB/SLB:
apiVersion: v1
kind: Service
metadata:
name: nginx-lb
spec:
type: LoadBalancer
selector:
app: nginx
ports:
- port: 80
targetPort: 8080
externalTrafficPolicy: Local # 保留客户端真实 IP,但流量只发给本节点上的 Pod
Headless Service,配合 StatefulSet 使用:
apiVersion: v1
kind: Service
metadata:
name: mysql-headless
spec:
clusterIP: None # 关键:不分配虚拟 IP
selector:
app: mysql
ports:
- port: 3306
targetPort: 3306
不带 selector 的 Service,后端由手工维护的 EndpointSlice 提供,适合把外部中间件纳入集群管理:
apiVersion: v1
kind: Service
metadata:
name: legacy-api
spec:
ports:
- port: 8080
apiVersion: discovery.k8s.io/v1
kind: EndpointSlice
metadata:
name: legacy-api-1
labels:
kubernetes.io/service-name: legacy-api
addressType: IPv4
ports:
- port: 8080
endpoints:
- addresses:
- 192.168.1.100
- 192.168.1.101
# 查看所有 Service(含 ClusterIP)
kubectl get svc -A
kubectl get svc -A -o wide
# 查看详情,关注 Selector 与 Events
kubectl describe svc nginx-svc
# 快速用 Deployment 暴露一个 Service
kubectl expose deployment nginx --port=80 --target-port=8080 --type=NodePort
# 查看后端 Pod 列表(推荐 EndpointSlice)
kubectl get endpoints nginx-svc
kubectl get endpointslices -l kubernetes.io/service-name=nginx-svc
# 端口转发到本地调试
kubectl port-forward svc/nginx-svc 8080:80
# 删除 Service
kubectl delete svc nginx-svc
# 起一个临时 Pod,退出后自动删除
kubectl run test --rm -it --image=busybox:1.36 --restart=Never -- sh
wget -qO- http://nginx-svc # 同命名空间
wget -qO- http://nginx-svc.default # 跨命名空间
wget -qO- http://nginx-svc.default.svc.cluster.local # 全限定域名
nslookup nginx-svc.default.svc.cluster.local # 只解析不请求
# 1. ENDPOINTS 为 <none>:说明 selector 没匹配到任何 Ready 的 Pod
kubectl get svc nginx-svc -o wide
kubectl get endpoints nginx-svc
# 2. 对比 Pod 标签与 Service selector 是否一致
kubectl get pods --show-labels
kubectl get svc nginx-svc -o jsonpath='{.spec.selector}'
# 3. Pod 是否 Ready —— NotReady 的 Pod 会被从 Endpoints 摘除
kubectl get pods -o wide
# 4. kube-proxy 是否健康
kubectl -n kube-system get pods -l k8s-app=kube-proxy
kubectl -n kube-system logs -l k8s-app=kube-proxy --tail=50
# 5. 检查内核转发规则(iptables 模式)
sudo iptables -t nat -L KUBE-SERVICES -n | grep <ClusterIP>
port 与 targetPort 必须分清楚。port 是 Service 对外暴露的端口,targetPort 是容器实际监听的端口,后者必须与容器的 containerPort 一致。写反的典型症状是 Service 能解析但连接超时。metadata.labels 必须完全一致(大小写、拼写、层级),写错的 Service 不会报错,只是 Endpoints 永远为空。kubectl get pods 也看得见,但流量不会进来,排查时不能只看 Pod 状态。type: LoadBalancer 在自建集群里会一直 EXTERNAL-IP: <pending>。它依赖云厂商的 cloud-controller-manager,裸机环境需要额外部署 MetalLB 或改用 NodePort + Ingress。nodePort 时由系统从 30000-32767 分配,该范围可在 apiserver 的 --service-node-port-range 中调整;手动指定时要避开已占用端口,否则创建失败。serviceName 必须指向一个已存在的 Headless Service,否则域名解析不出来。externalTrafficPolicy: Local 会保留客户端源 IP,但只有运行着后端 Pod 的节点才会接收流量,节点数少于副本数时可能造成负载不均,同时健康检查失败会导致整体不可用。name 字段必填且互不相同,否则创建时会被校验拒绝。kubectl — Kubernetes集群管理工具kube-proxy — 实现Service转发规则的节点代理coredns — 为Service名称提供集群内DNS解析ingress — 在Service之上提供七层入口路由kubeadm — Kubernetes集群安装与生命周期管理工具