用 Service 把流量接上
目标
亲手创建五种 Service 类型和 Ingress,并主动制造 selector 不匹配、endpoint 为空的情况,再将其修复。
为什么这很重要
考试中“创建了 Service 却无法连接”的问题,大多出在 selector、端口或 Ready 状态三者之一。理解 Service 对象本身并不传输流量,而是通过 selector 生成后端列表的声明,诊断顺序就会自然确定:先检查 endpoint 是否包含 IP。有 IP 时,问题在数据平面或端口;没有 IP 时,问题在 selector 或 Pod Ready 状态。
区分 targetPort 与 port 也很重要。port 是 Service 开放的端口,targetPort 是 Pod 侧端口。两者相同时可以省略,因此容易混淆;一旦设为不同值,错误就会暴露出来。
步骤
- 创建 namespace
cka-net和 Deploymentweb(副本数 2,镜像nginx:1.27,Pod 标签app=web)。然后创建 ClusterIP Serviceweb-svc。port 为 80,targetPort 为 80,selector 为app=web。 - 创建 Deployment
api(副本数 2,镜像nginx:1.27,Pod 标签app=api)。先创建 Serviceapi-svc,并错误地使用 selectorapp=api-server,并将 endpoint 查询结果保存到/root/cka-net/endpoints-before.txt。然后将 selector 修正为app=api。 - 创建 NodePort Service
web-np。port 为 80,selector 为app=web,nodePort 明确指定为30080。 - 创建 Deployment
db(副本数 1,镜像nginx:1.27,Pod 标签app=db)和 headless Servicedb-headless。clusterIP 为None,port 为 5432,selector 为app=db。 - 创建 Service
multi-svc。selector 为app=web,包含两个端口——名称http(port 80、targetPort 8080)和名称metrics(port 9090)。 - 创建 Service
ext-db。type 为ExternalName,externalName 为nas.homelab.internal。 - 创建 Ingress
web-ing。ingressClassName 为nginx,host 为cka.homelab.internal;路径/(pathType Prefix)转发到web-svc的 80 端口,路径/api(pathType Prefix)转发到api-svc的 80 端口。
参考
- 也可以使用
kubectl get endpointslice -n cka-net -l kubernetes.io/service-name=web-svc查看 endpoint。 - 第 2 步的执行顺序也是评分内容。必须在修复之前先保存文件。
- 常见错误 1:试图之后修改
clusterIP: None。该字段不可变。 - 常见错误 2:Ingress 中遗漏
pathType。在 v1 中这是必填字段,缺少时会被拒绝。
ClusterIP Service 与 endpoint
创建 namespace cka-net 和 Deployment web(副本数 2,镜像 nginx:1.27,Pod 标签 app=web)。然后创建 ClusterIP Service web-svc。port 为 80,targetPort 为 80,selector 为 app=web。
kubectl expose 最快,但要确认它设置了什么 selector。只有 Pod 达到 Ready 后,endpoint 才会填充。
selector 拼写错误导致 endpoint 为空
创建 Deployment api(副本数 2,镜像 nginx:1.27,Pod 标签 app=api)。先创建 Service api-svc,并错误地使用 selector app=api-server,并将 endpoint 查询结果保存到 /root/cka-net/endpoints-before.txt。然后将 selector 修正为 app=api。
先使用错误的 selector 创建对象,亲眼确认 endpoint 为空并保存到文件,然后再修复。不遵守顺序就不会留下证据。
手动指定 NodePort 编号
创建 NodePort Service web-np。port 为 80,selector 为 app=web,nodePort 明确指定为 30080。
nodePort 位于 ports 数组内。默认范围是 30000~32767,超出范围的值会被拒绝。
headless Service
创建 Deployment db(副本数 1,镜像 nginx:1.27,Pod 标签 app=db)和 headless Service db-headless。clusterIP 为 None,port 为 5432,selector 为 app=db。
将 clusterIP 设为 None 后不会分配 VIP。该字段创建后无法修改,若创建错误,请重新创建对象。
暴露两个端口
创建 Service multi-svc。selector 为 app=web,包含两个端口——名称 http(port 80、targetPort 8080)和名称 metrics(port 9090)。
存在两个以上端口时,每个端口都必须有 name。port 和 targetPort 可以使用不同值。
使用 ExternalName 封装外部系统
创建 Service ext-db。type 为 ExternalName,externalName 为 nas.homelab.internal。
ExternalName Service 没有 selector 和端口,也不会获得 ClusterIP。如果先创建成了其他类型,重新创建会更干净。
综合:使用 Ingress 连接两个 Service
创建 Ingress web-ing。ingressClassName 为 nginx,host 为 cka.homelab.internal;路径 /(pathType Prefix)转发到 web-svc 的 80 端口,路径 /api(pathType Prefix)转发到 api-svc 的 80 端口。
ingressClassName 是 spec 字段,而不是注解。每个 path 都必须包含 pathType,后端通过 service.name 和 service.port.number 指定。