10 KiB
02-05 Nginx 验证矩阵(Ingress / IngressRoute)— 综合一键部署
定位:02 系列尾部,整合 02-01~02-04 的综合一键部署。4 种组合(控制节点/工作节点 × Ingress/IngressRoute)均有具体 Deployment + Service + 路由,节点 IP 访问(如
http://入口IP/demo-m1/)。分课清单另见ansible/files/02-01/~02-04/(与下表 YAML 同构副本,便于单篇学习;改矩阵时请同步或接受漂移)。
TL;DR
- 自动化验收:
./ansible/bin/verify.sh run 02-05 - 关键前置:按本文「前置条件」准备环境变量/Secret/入口 IP
- 成功判据:达到本文「预期」且 playbook 断言通过
- 排障:见本文「排障」
前置条件
- 已完成
01-02-k3s-工作节点.md(Traefik 与 LB 可用) - M1:Deployment 需含
nodeSelector: node-role.kubernetes.io/control-plane: ""及控制平面污点的 toleration(见下 YAML),否则控制节点若有NoSchedule污点会导致 Pod 一直 Pending、访问 /demo-m1 报 "no available server";若控制节点无该标签,需先打标或改 M1 为 hostname(同 M2) - M2:Deployment 必须含
nodeSelector: kubernetes.io/hostname: <控制节点名>(示例ylc61),按实际修改 - M3:Deployment 含
nodeSelector: node-role.kubernetes.io/worker: "",随机调度到任一工作节点;需工作节点有该标签 - M4:Deployment 必须含
nodeSelector: kubernetes.io/hostname: ylc64(指定工作节点),按实际修改
部署说明(Pod、路径)
| 场景 | 路径 | 说明 |
|---|---|---|
| M1 控制节点 + Ingress | /demo-m1 |
nginx-m1,随机一台控制节点 |
| M2 控制节点 + IngressRoute | /demo-m2 |
nginx-m2,指定一台控制节点 |
| M3 工作节点 + Ingress | /demo-m3 |
nginx-m3,随机一台工作节点 |
| M4 工作节点 + IngressRoute | /demo-m4 |
nginx-m4,指定一台工作节点 |
完整配置(与 Ansible 共用)
配置位于 ansible/files/02-05/(4 个文件对应 M1~M4),文档与 Ansible 共用此目录:
| 文件 | 场景 | 路径 | 节点 |
|---|---|---|---|
| 01-control-ingress.yaml | M1 控制+Ingress | /demo-m1 | nodeSelector control-plane + toleration |
| 02-control-ingressroute.yaml | M2 控制+IngressRoute | /demo-m2 | hostname 指定(默认 ylc61) |
| 03-worker-ingress.yaml | M3 工作+Ingress | /demo-m3 | nodeSelector worker(随机) |
| 04-worker-ingressroute.yaml | M4 工作+IngressRoute | /demo-m4 | hostname 指定(默认 ylc64) |
按需修改 M2(ylc61)、M4(ylc64)的 hostname;M3 需工作节点有 node-role.kubernetes.io/worker 标签。计算机名使用短主机名(ylc61~ylc64)便于配合 Cloudflare CDN。
部署
kubectl apply -f ansible/files/02-05/ -R
kubectl get pod,svc,ing,ingressroute -n default -o wide
验证(用 IP 访问)
直接用入口节点 IP 访问(将 192.168.2.61 改为你的入口 IP;按 01-02/01-05 已配 LB 时任选节点 IP)。
for path in demo-m1 demo-m2 demo-m3 demo-m4; do
code=$(curl -s -o /dev/null -w "%{http_code}" --max-time 3 "http://192.168.2.61/${path}/" 2>/dev/null || echo "---")
echo "/${path}/: ${code}"
done
预期:4 个路径均返回 200,页面分别显示 M1、M2、M3、M4(及对应说明、Backend: M1 等),便于区分是哪个后端。
M1 仍显示 nginx 欢迎页时:进入容器排查
若访问 /demo-m1 报 "no available server":多为 M1 Pod 未调度(Pending),Service 无 endpoint。控制节点常有 node-role.kubernetes.io/control-plane:NoSchedule 污点,Deployment 需加上述 toleration 才能调度。可用下面命令逐项检查:
# 1. M1 Pod 是否存在、是否 Running(Pending 说明未调度)
kubectl get pod -n default -l app=nginx-m1 -o wide
# 2. M1 Service 是否有 endpoint(无 endpoint 则 Traefik 报 no available server)
kubectl get endpoints -n default nginx-m1
# 3. 若 Pod 为 Pending,看调度失败原因(Events 里会写 taint/未满足)
kubectl describe pod -n default -l app=nginx-m1
# 4. 确认控制节点标签与污点(M1 需调度到带 control-plane 的节点,且 Deployment 需有对应 toleration)
kubectl get nodes -o custom-columns=NAME:.metadata.name,LABEL:.metadata.labels.node-role\.kubernetes\.io/control-plane,TAINT:.spec.taints
若 Events 为 node(s) didn't match Pod's node affinity/selector:说明没有任何节点带 node-role.kubernetes.io/control-plane 标签,需给控制节点打标(控制节点一般为运行 k3s server 的那台,如 ylc61):
# 先看节点名:kubectl get nodes
# 再给控制节点打标(把 ylc61 换成实际控制节点名)
kubectl label node ylc61 node-role.kubernetes.io/control-plane= --overwrite
打标后 M1 Pod 会自动调度到该节点并 Running;若仍 Pending,再执行一次 kubectl get pod -n default -l app=nginx-m1 -o wide 与 kubectl describe pod -n default -l app=nginx-m1 看 Events。
下面为"M1 能访问但仍是默认页"时的容器内排查。在已配置 KUBECONFIG 的机器上执行(将 KUBECONFIG 改为实际路径,如 /etc/rancher/k3s/k3s.yaml):
# 1. 看 html 目录下有哪些文件(是否包含我们挂的 index.html)
kubectl exec -n default deployment/nginx-m1 -- ls -la /usr/share/nginx/html/
# 2. 看 index.html 内容(应是 M1 的 HTML,若仍是 Welcome to nginx 说明挂载未生效)
kubectl exec -n default deployment/nginx-m1 -- cat /usr/share/nginx/html/index.html
# 3. 看 conf.d 下有哪些配置(是否有多个 server,或 default.conf 被覆盖)
kubectl exec -n default deployment/nginx-m1 -- ls -la /etc/nginx/conf.d/
# 4. 看 default.conf 内容(应含 root、index、X-Backend M1)
kubectl exec -n default deployment/nginx-m1 -- cat /etc/nginx/conf.d/default.conf
# 5. 看 nginx 最终生效的 server 配置(确认谁在监听 80、root 指向哪)
kubectl exec -n default deployment/nginx-m1 -- nginx -T 2>&1 | grep -A 200 "server {"
根据输出可判断:若 index.html 仍是默认欢迎页 → ConfigMap/volumeMount 未生效或未覆盖到该路径;若 conf.d/ 下有多于一个 *.conf 或 default.conf 不是我们的内容 → 配置被覆盖或未挂载;若 nginx -T 里 80 端口的 root 不是 /usr/share/nginx/html 或没有我们的 location → 被其他 server 块优先。把上述命令的输出贴出后,即可针对性改 manifest 或挂载方式。
为何 M1~M4 都是单文件(subPath)挂载,却只有 M1 不正常?
Manifest 里四份写法一致,若只有 M1 仍显示默认页,多半是集群里 nginx-m1 的 Deployment/ReplicaSet 曾用旧 spec 部署过,导致当前 Pod 未带 volumeMount。根因未查清时,最稳妥是删除 M1 部署再重新部署(见下)。
单文件部署(按目录 apply 全部 M1~M4):
# 在仓库根目录执行时:
kubectl apply -f ansible/files/02-05/ -R
# 若当前在 ansible/ 目录下,改用:
kubectl apply -f files/02-05-nginx-matrix/ -R
M1 未生效时:删除部署再重新部署(推荐)
先删 M1 的 Deployment,再 apply 01,这样会新建唯一的 ReplicaSet,不会留下旧 spec 的 Pod。
# 1. 只删 M1 的 Deployment(Service/Ingress/Middleware/ConfigMap 保留,稍后 apply 会复用或更新)
kubectl delete deployment nginx-m1 -n default
# 2. 重新部署 M1(在 ansible/ 目录下)
kubectl apply -f files/02-05-nginx-matrix/01-control-ingress.yaml
# 若在仓库根目录:
# kubectl apply -f ansible/files/02-05/01-control-ingress.yaml
# 3. 等 Pod Running 后验证
kubectl get pod -n default -l app=nginx-m1
kubectl exec -n default deployment/nginx-m1 -- cat /usr/share/nginx/html/index.html
kubectl exec -n default deployment/nginx-m1 -- cat /etc/nginx/conf.d/default.conf
使用 Ansible 部署时,playbook 会自动跑一遍上述诊断并打印「M1 容器内诊断结果」,便于直接查看。
Ansible 一键部署
可使用 Ansible playbook 自动完成复制 manifests、apply、等待 Pod 就绪及 curl 验证:
- Playbook:
ansible/playbooks/verify/02-05.yml - Manifests 位置:
ansible/files/02-05/(M1 control-plane / M2 M4 节点名 ylc61、ylc64,M3 worker;按实际修改 M2/M4 节点名) - 执行(在 ansible/ 目录下):
cd ansible
ansible-playbook -i inventory.ini playbooks/verify/02-05.yml
若 manifests 目录未找到,可改为在仓库根目录执行:
ansible-playbook -i ansible/inventory.ini ansible/playbooks/verify/02-05.yml
Playbook 会:拷贝 manifests 到控制节点 → 先删除全部 nginx 矩阵 Deployment(nginx-m1~m4,若存在)→ kubectl apply → rollout restart M1~M4 → 等待 Pod 就绪 → 输出 16 个目标(4 节点 × 4 路径)的 curl 矩阵。先删再 apply 可避免旧 ReplicaSet 导致任一 Mx 仍显示默认页。
删除
手动 kubectl apply 的:用同一目录删除
kubectl delete -f ansible/files/02-05/ -R
Ansible playbook 部署的:在仓库根或 ansible 同级的机器上,用 manifests 删除(需配置 KUBECONFIG)
export KUBECONFIG=/etc/rancher/k3s/k3s.yaml # 或从控制节点拷贝 kubeconfig
kubectl delete -f ansible/files/02-05/ -R
统一使用仓库真源目录清理,避免与临时目录副本发生偏差。
按资源名删除(适用于 manifests 已不可用)
kubectl delete deployment,svc,ingress -n default nginx-m1 nginx-m2 nginx-m3 nginx-m4
kubectl delete ingressroute -n default nginx-m2 nginx-m4
kubectl delete middleware -n default stripprefix-m1 stripprefix-m2 stripprefix-m3 stripprefix-m4
kubectl delete configmap -n default nginx-m1-html nginx-m2-html nginx-m3-html nginx-m4-html
下一步
03-01-k3s-traefik-dashboard.md:Dashboard03-02-k3s-traefik-acme.md- 返回
00-00-构建总览.md按导航继续
相关文档
02-01~02-04:分篇说明(路径 /demo-m1~m4、nodeSelector 与本文一致)03-02-k3s-traefik-acme.md06-01-k3s-networkpolicy-故障排查.md
排障
- 先看 playbook 输出:失败时先定位是 deploy/wait/http_check 哪一步。
- 集群侧总览:
kubectl get nodes -o wide、kubectl -n kube-system get pods -o wide。 - 事件与日志:
kubectl -n <ns> describe ...、kubectl -n <ns> logs ... --tail=200。