用 Service 找到 Pod,再挂上配置与存储
目标
亲手观察 Service 如何查找 Pod、找不到时呈现什么状态,并验证 ConfigMap/Secret 注入、PVC 请求及服务 DNS 名称规则。
为什么重要
绝大多数 Service 故障不是“服务没有创建”,而是**“服务已经创建,后面却没有任何对象”。Kubernetes 不会验证选择器是否真的选中 Pod。即使一个拼写错误让端点变成 0 个,kubectl get svc 看起来仍然正常。因此,本实验会故意制造这种情况**。亲手制造过一次的故障,在实际工作中三分钟就能诊断。
ConfigMap/Secret 是 Kubernetes 对十二要素原则“配置来自环境”的实现。镜像在各处应保持相同,变化的应是注入值。但请记住,Secret 虽名为秘密,在默认设置下并未加密——这是 KCSA 的重要主题。
PVC 就是一份“申请单”。Pod 不直接指向“NFS 服务器 10.0.0.5 的 /export/data”,而是申请“1Gi 的 RWO 存储”。借助这一间接层,同一份清单可同时用于笔记本集群和生产环境。
步骤
- 创建命名空间
kcna-net,在其中创建 Deploymentshop:镜像nginx:1.27-alpine,replicas 2,Pod 模板标签app=shop。 - 创建 Service
shop-svc:类型ClusterIP,port 80,选择器app=shop。确认选中 2 个端点。 - 在同一命名空间创建 Service
broken-svc:port 80,但故意把选择器写成app=shopp(多一个 p)。确认端点为 0,并将修复它的正确选择器保存到/root/kcna-net/diagnosis.txt,内容为一行app=shop。 - 创建 Service
shop-np:类型NodePort,port 80,nodePort 为30080,选择器app=shop。 - 创建 ConfigMap
shop-config(键APP_MODE,值production)和 Secretshop-secret(键API_KEY,值为任意字符串)。再创建 Podshop-client,让环境变量APP_MODE取自shop-config的APP_MODE键,环境变量API_KEY取自shop-secret的API_KEY键。镜像为nginx:1.27-alpine。 - 创建 PVC
shop-data:请求容量1Gi,accessModes 为ReadWriteOnce,storageClassName 为standard。 - 将
shop-svc的完整 DNS 名称(FQDN)以一行保存到/root/kcna-net/dns.txt,并在同一命名空间创建无头服务shop-headless:选择器app=shop,port 80,将 clusterIP 指定为无头模式。
参考
- 可用
kubectl get endpointslice -n kcna-net -l kubernetes.io/service-name=shop-svc -o yaml查看端点。kubectl describe svc的 Endpoints 行也很方便。 - 第 5 步 Pod 的 env 项使用
valueFrom.configMapKeyRef/valueFrom.secretKeyRef,各自都需要name和key两个字段。 - 集群域名默认是
cluster.local。 - 常见错误 1:第 3 步创建错误选择器后立即修复。此步骤必须保持错误状态才能通过。
- 常见错误 2:误以为第 6 步 PVC 处于 Pending 是创建错误而删除重建。没有动态供应器时 Pending 属于正常状态,评分只检查请求内容。
建立后端 Deployment
创建命名空间 kcna-net,在其中创建 Deployment shop:镜像 nginx:1.27-alpine,replicas 2,Pod 模板标签 app=shop。
服务要先有可查找的目标。Pod 模板上的标签稍后必须与选择器匹配,请确认实际添加了什么标签。
确认 ClusterIP 服务和端点
创建 Service shop-svc:类型 ClusterIP,port 80,选择器 app=shop。确认选中 2 个端点。
可以用 kubectl expose 创建,也可编写 YAML。创建后必须确认端点真的存在——服务创建成功和流量有目的地是两回事。
故意重现选择器拼写错误
在同一命名空间创建 Service broken-svc:port 80,但故意把选择器写成 app=shopp(多一个 p)。确认端点为 0,并将修复它的正确选择器保存到 /root/kcna-net/diagnosis.txt,内容为一行 app=shop。
本步骤的目标是制造故障。让服务选择器多一个字符,同时确认它不会报错且端点为 0。诊断文件中以一行 key=value 写入正确选择器。
用 NodePort 创建外部入口
创建 Service shop-np:类型 NodePort,port 80,nodePort 为 30080,选择器 app=shop。
NodePort 默认范围是 30000-32767。不指定编号时会随机分配;若要使用评分指定的编号,必须在清单中明确填写。
注入 ConfigMap 和 Secret
创建 ConfigMap shop-config(键 APP_MODE,值 production)和 Secret shop-secret(键 API_KEY,值为任意字符串)。再创建 Pod shop-client,让环境变量 APP_MODE 取自 shop-config 的 APP_MODE 键,环境变量 API_KEY 取自 shop-secret 的 API_KEY 键。镜像为 nginx:1.27-alpine。
使用 kubectl create configmap 和 kubectl create secret generic 的 --from-literal 会很快。Pod 的每个 env 项通过 valueFrom 指定 configMapKeyRef / secretKeyRef;必须同时填写引用名称和键。
用 PVC 编写存储申请
创建 PVC shop-data:请求容量 1Gi,accessModes 为 ReadWriteOnce,storageClassName 为 standard。
PVC 是“申请单”。本实验集群没有动态供应器,可能一直 Pending,这本身正常;评分检查 spec。accessModes 是数组,storageClassName 是字符串。
DNS 名称规则与无头服务
将 shop-svc 的完整 DNS 名称(FQDN)以一行保存到 /root/kcna-net/dns.txt,并在同一命名空间创建无头服务 shop-headless:选择器 app=shop,port 80,将 clusterIP 指定为无头模式。
服务的完整 DNS 名称由四部分组成。无头服务通过给 clusterIP 字段指定一个特殊值创建;kubectl expose 不便设置该值,最好使用 YAML。