零基础入门 Kubernetes Service:概念、YAML 配置示例与常见问题排查指南
一、Kubernetes Service 的核心概念
Kubernetes Service 是集群中一组 Pod 的逻辑抽象,通过静态 IP 地址和 DNS 名称提供稳定的网络访问入口。其核心价值在于:
- 解耦生命周期:Pod 可能因崩溃、扩容或缩容频繁重建,但 Service 的 IP 和 DNS 名称保持不变,避免客户端频繁更新访问地址。
- 负载均衡:自动将流量分发到后端 Pod,例如一个 Service 可关联 3 个 Nginx Pod,客户端请求会被均衡分配到不同实例。
- 服务发现 :通过 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 无法访问
排查步骤:
-
检查 Service 状态:
csharpbash kubectl get svc <service-name> -o wide # 确认 IP 和端口 kubectl describe svc <service-name> # 检查 Events 和 Endpoints
- 若
Endpoints
为空,说明 Selector 未匹配到 Pod,需检查 Pod 标签是否与 Service 的spec.selector
一致。
- 若
-
验证 Pod 状态:
inibash kubectl get pods -l app=<label-value> # 检查关联 Pod 是否存在 kubectl logs <pod-name> # 查看 Pod 日志是否有错误
-
测试网络连通性:
rubybash kubectl run -it --rm debug --image=busybox --restart=Never -- sh # 在调试容器中执行 ping <service-cluster-ip> # 测试 ClusterIP 可达性 wget <service-cluster-ip>:<port> # 测试端口连通性
问题 2:NodePort 类型 Service 外部无法访问
排查步骤:
-
检查节点端口监听:
perlbash # 在集群节点上执行 netstat -tulnp | grep <nodePort> # 确认端口被 kube-proxy 监听
-
验证防火墙规则:
- 云平台:检查安全组是否放行 NodePort 端口(如 30080)。
- 裸金属集群:使用
iptables -L -n
检查是否有 DROP 规则。
-
测试从节点直接访问:
bashbash curl http://localhost:<nodePort> # 从节点本地访问
问题 3:DNS 解析失败
排查步骤:
-
检查 CoreDNS 状态:
inibash kubectl get pods -n kube-system -l k8s-app=kube-dns kubectl logs <coredns-pod-name> -n kube-system # 查看日志是否有错误
-
测试 DNS 解析:
inibash kubectl run -it --rm dns-test --image=busybox --restart=Never -- sh # 在调试容器中执行 nslookup <service-name>.<namespace>.svc.cluster.local # 完整 FQDN 解析 nslookup <service-name> # 同命名空间内可省略后缀
问题 4:负载均衡不均匀
排查步骤:
-
检查 Service 的
sessionAffinity
:yamlyaml spec: sessionAffinity: ClientIP # 默认 None(轮询),可改为 ClientIP 固定 IP 到同一 Pod
-
验证 Pod 资源使用:
inibash kubectl top pods -l app=<label-value> # 检查 CPU/内存是否均衡
-
检查网络插件:
-
若使用 Calico/Flannel,检查
kube-proxy
日志是否有 iptables 规则更新失败:perlbash kubectl logs <kube-proxy-pod-name> -n kube-system | grep "error"
-
四、最佳实践
- 标签设计 :使用
app.kubernetes.io/name
、app.kubernetes.io/version
等标准标签,避免随意命名。 - 端口命名 :在 Service 的
ports
中为端口添加名称(如http
、grpc
),提高可读性。 - 健康检查 :为后端 Pod 配置
livenessProbe
和readinessProbe
,确保 Service 只路由到健康实例。 - 资源限制:为 Service 关联的 Pod 设置 CPU/内存请求和限制,防止单个 Pod 占用过多资源。
通过掌握 Service 的核心概念、配置方法和排查技巧,您可以高效管理 Kubernetes 集群中的服务通信,为后续部署复杂应用(如 Istio 服务网格、Knative 无服务器)打下坚实基础。