第 7 / 18 篇

第 6 章 Service:给会变化的 Pod 一个稳定入口

名字稳定,后端可以变化

Deployment 创建的 Pod 会更换,而调用者希望访问一个固定名字。Service 提供一个稳定的服务抽象,通过标签选择对应的 Pod,并维护转发所需的后端信息。现代集群使用 EndpointSlice 记录后端地址。

把以下内容保存为 service.yaml:

apiVersion: v1
kind: Service
metadata:
  name: hello-web
spec:
  selector:
    app: hello-web
  ports:
    - name: http
      port: 80
      targetPort: 80
  type: ClusterIP

port 是 Service 的入口端口,targetPort 是后端 Pod 的目标端口,两者可以不同。选择器必须对应 Pod 的标签。Service 和 Deployment 可以同名,因为它们是不同类型的对象。

kubectl apply -n k8s-book -f service.yaml
kubectl get services -n k8s-book
kubectl get endpointslices -n k8s-book -l kubernetes.io/service-name=hello-web
kubectl port-forward -n k8s-book service/hello-web 8080:80

再次访问 http://localhost:8080。这里的端口转发会选择一个后端 Pod,适合开发调试;它并不等价于完整测试 Service 负载均衡路径。后端 Pod 被替换时,可能需要重新运行转发命令。

从集群内部验证 DNS 和访问

在另一个终端运行以下一次性检查。它会创建一个临时客户端 Pod,执行请求后删除。

kubectl run netcheck -n k8s-book --rm -i --restart=Never \
  --image=busybox:1.37 -- wget -qO- http://hello-web

应该输出 NGINX 页面的 HTML。如果本次运行异常中断,临时 Pod 可能残留,可用 kubectl delete pod netcheck -n k8s-book 清理后重试。BusyBox 是用于此练习的小型工具镜像,不属于应用本身。

状态显示就绪与一次真实请求成功是两项证据。刚滚动更新时,服务后端与节点转发规则可能还在传播;可在有限时间内重复只读 HTTP 检查,确认页面实际恢复。持续失败就继续排查后端、DNS 与网络,不应只看 Ready 就宣布整条路径成功。

同一命名空间里的 Pod 通常可用 hello-web 访问该 Service。跨命名空间可用 hello-web.k8s-book。完整名称通常为 hello-web.k8s-book.svc.cluster.local,其中集群域名可由管理员配置,并非永远是 cluster.local。你的电脑一般不能直接解析这种集群内部名称。

常见访问方式

方式 主要用途 本地练习的注意点
ClusterIP 集群内访问 本书默认使用
NodePort 通过节点端口访问 kind 节点在容器里,还涉及宿主机映射
LoadBalancer 由外部负载均衡实现提供入口 裸机或 kind 通常需要额外实现,可能一直 Pending
Ingress 按 HTTP 域名、路径路由 必须安装相应控制器
port-forward 本地调试 依赖持续运行的 kubectl 会话

创建 Ingress YAML 不会自动获得可工作的入口。Ingress API 仍可使用,但其功能已冻结;学习新入口能力时可以进一步了解 Gateway API,同样需要相应控制器与配置。本书不要求把应用开放到公网。

本章自测:Service 通过什么找到 Pod?Service 没有后端时,应首先检查什么?