# 01-06 OpenWrt HAProxy 负载均衡 > 在 OpenWrt 上安装并配置 HAProxy,将 80/443 流量转发到 K3s 集群节点(Traefik 入口),实现单一入口与负载均衡。 ## 契约与真源(HAProxy 配置文件) **HAProxy 示例配置的唯一真源**:本仓库 **[`ansible/files/01-06/`](../ansible/files/01-06/)**(与文档、脚本共用;上 OpenWrt 前请按实际节点 IP/端口改 `server` 与 `bind`)。 | 文件 | 说明 | |------|------| | [`haproxy-no-check.cfg`](../ansible/files/01-06/haproxy-no-check.cfg) | 最简:无健康检查;HTTP 18080 + TCP 443 透传 18443(见 §2) | | [`haproxy-http.cfg`](../ansible/files/01-06/haproxy-http.cfg) | 80 明文 HTTP 健康检查(`option httpchk`)(§3.2) | | [`haproxy-tls.cfg`](../ansible/files/01-06/haproxy-tls.cfg) | 443 `mode tcp` + TLS 握手检查(§3.3) | | [`haproxy-https.cfg`](../ansible/files/01-06/haproxy-https.cfg) | 443 应用层 HTTPS 检查(HAProxy 终结 TLS 场景)(§3.4) | | [`haproxy-proxy-http-tls.cfg`](../ansible/files/01-06/haproxy-proxy-http-tls.cfg) | HTTP/TLS 检查 + `send-proxy-v2`(§5) | OpenWrt 上实际生效路径多为 **`/etc/haproxy.cfg`** 或 **`/etc/haproxy/haproxy.cfg`**,以 **`/etc/init.d/haproxy`** 为准;将上述文件**复制过去**或合并片段后执行 `haproxy -c -f <路径>` 校验。 ## TL;DR - **HAProxy 配置**:见上表 **[`ansible/files/01-06/`](../ansible/files/01-06/)** `*.cfg` - **自动化验收**:`./ansible/bin/verify.sh run 01-06` - **关键前置**:按本文「前置条件」准备环境变量/Secret/入口 IP - **成功判据**:达到本文「预期」且 playbook 断言通过 - **排障**:见本文「排障」 ## 前置条件 - OpenWrt 与 K3s 节点同网段(如 192.168.2.0/24),OpenWrt 通常为网关(如 192.168.2.1) - 已完成 `01-02-k3s-工作节点.md` 或 `01-05`,Traefik 入口 80/443 已在各节点可达 ## 1. 安装 HAProxy ```bash opkg update opkg install haproxy ``` 若使用 LuCI,可在「系统」→「软件包」中搜索 `haproxy` 安装。 ## 2. 配置(原生) 编辑 `/etc/haproxy.cfg` 或包提供的配置路径(部分 OpenWrt 使用 `/etc/haproxy/haproxy.cfg`)。可在 `/etc/init.d/haproxy` 中查看实际配置文件路径。 **配置目录说明与「cfg 是否正确」的验证层次**:见 `ansible/files/01-06/`(**仅语法**:`./scripts/01-06-verify-haproxy.sh --cfg-only`)。 **无健康检查最简配置**:`ansible/files/01-06/haproxy-no-check.cfg`(与 Ansible 共用,可复制到 OpenWrt 或通过 playbook 下发)。将 `192.168.2.61`~`192.168.2.64` 按实际 K3s 节点 IP 修改。如需健康检查见第 3 节;如需真实客户端 IP 见第 5 节 PROXY Protocol。 ## 3. 健康检查 分四类:**TCP**、**HTTP**、**TLS**、**HTTPS**,由浅到深。 | 类型 | 说明 | 适用端口 | |------|------|----------| | TCP | `server ... check`,端口能连即通过 | 80、443 等 | | HTTP | `option httpchk`,明文 HTTP 请求 | 80 | | TLS | `option ssl-hello-chk`,TLS 握手层 | 443(`mode tcp`) | | HTTPS | `option httpchk` + `server ... ssl`,HTTP over TLS | 443(`mode http`) | 说明:443 业务若为 **TCP 透传**,backend 是 `mode tcp`,只能选 TCP 或 TLS;若需 HTTPS 级检查,需另建 `mode http` 的 backend。 ### 3.1 TCP 在 `haproxy-no-check.cfg` 基础上,各 `server` 行末尾加 `check` 即可。 ### 3.2 HTTP(80 明文) 完整配置:`ansible/files/01-06/haproxy-http.cfg`。`backend k3s_http` 开头加 `option httpchk GET /`,`k3s_https` 仍为 TCP 检查。 ### 3.3 TLS(443 握手,`mode tcp`) 完整配置:`ansible/files/01-06/haproxy-tls.cfg`。`backend k3s_https` 中加 `option ssl-hello-chk`,做 TLS 握手层检查。 ### 3.4 HTTPS(443 应用层,`mode http` + `ssl`) 完整配置:`ansible/files/01-06/haproxy-https.cfg`。适用于 **HAProxy 在 443 终结 TLS(由 HAProxy 提供证书)** 的场景(frontend 需 `bind *:443 ssl crt ...`)。需与 Traefik 路由匹配的 `Host`;自签/内网 CA 用 `verify none`,生产建议 `ca-file`。若仍为 TCP 透传,用 3.3 即可。 ## 4. 启动与验证 **一键部署**(uhttpd 80/443 + HAProxy 18080/18443):`./scripts/01-06-deploy-openwrt-haproxy.sh`。将 uhttpd 恢复监听 80/443(IPv4+IPv6),HAProxy 部署到 18080/18443,与 LuCI 共存。 ```bash /etc/init.d/haproxy enable /etc/init.d/haproxy restart ``` 验证:从内网访问 `http://:18080/` 或 `http://:18080/demo-m1/`(家庭私网常用 18080/18443),应能到达 Traefik 与后端。 **验证**:经 **Linux 工作机**(本环境如 **`ylc65`**,在 `ansible/env/.env.verify` 里用 **`WORKSTATION_SSH`** 配置一行 `ssh user@ylc65 …`)发起 curl,验证 `http://:18080` 与 `https://<域名>:18443`(HTTPS 需正确设置 Host/SNI,例如 `curl --https-hosts ...`)。不部署、不改端口;需 OpenWrt HAProxy 已按 18080/18443 配置。 验证通过后,建议你在本篇文档中**手工**补充状态与备注(环境/日期/覆盖范围)。 ## 5. PROXY Protocol(可选) 若 Traefik 需获取真实客户端 IP,可在 HAProxy 后端每个 `server` 行添加 `send-proxy-v2`,并在 Traefik 配置 `trustedIPs` 包含 OpenWrt 网段(见 `03-02-k3s-traefik-acme.md`)。 **完整配置**:`ansible/files/01-06/haproxy-proxy-http-tls.cfg`(HTTP 检查 + TLS 检查 + PROXY)。 Traefik 端需启用 PROXY protocol 监听并信任 OpenWrt 的 IP,否则会报错。UCI 配置需参考 OpenWrt HAProxy 文档中的相应选项。 ## 6. 端口与防火墙 **80/443 被封**:家庭网络若被运营商封禁 80/443,可改用 18080/18443 等非标准端口,供直接访问或配合 Cloudflare CDN 端口转发。将 frontend 的 `bind *:80`、`bind *:443` 改为 `bind *:18080`、`bind *:18443` 即可;Traefik 入口及后端保持不变。 **防火墙**:确保 OpenWrt 放行实际监听端口(80/443 或 18080/18443 等)入站,或将 HAProxy 监听接口加入相应 zone。 ## 7. 故障排除 | 现象 | 可能原因 | 排查与处理 | |------|----------|------------| | HAProxy 启动失败 | 配置语法错误、端口被占用 | `haproxy -c -f /etc/haproxy.cfg` 校验;用 `netstat -tlnp` 或 `ss -tlnp` 查端口占用 | | curl 到网关 80 返回 LuCI | **uhttpd** 占 80,HAProxy 若用 80 会冲突 | 家庭私网建议 HAProxy 用 18080/18443,与 LuCI 共存 | | 502 Bad Gateway / 后端全部 down | K3s 节点不可达、健康检查过严 | `curl http://<节点IP>/` 直连节点;放宽 `check` 或改用 TCP 检查 | | HTTP 可达但 HTTPS 不通 | TLS 透传与检查类型不匹配 | 443 若为 `mode tcp`,用 TCP 或 TLS 检查;`mode http` 时用 HTTPS 检查并核对 Host | | 日志显示 PROXY protocol 错误 | Traefik 未启用或未信任 OpenWrt | 确认 Traefik 入口启用 PROXY、`trustedIPs` 含 OpenWrt 网段;或暂时去掉 `send-proxy-v2` | | 修改配置后无效果 | 未重启、配置路径错误 | `/etc/init.d/haproxy restart`;确认 `/etc/init.d/haproxy` 中读取的 cfg 路径 | | 外网访问不到 | 运营商封 80/443、防火墙未放行 | 改用 18080/18443 或配合 Cloudflare;检查 `firewall` 规则与 zone 配置 | **常用命令**: ```bash # 校验配置 haproxy -c -f /etc/haproxy.cfg # 手动前台启动(便于看输出、init.d 不可用时) haproxy -f /etc/haproxy.cfg # 查看 HAProxy 状态(若使用 init.d) /etc/init.d/haproxy status # 直连 K3s 节点验证 curl -v http://192.168.2.61/ ``` ## 相关文档 - `01-02-k3s-工作节点.md`:Traefik 入口与 LB 基线 - `02-05-nginx-验证矩阵-一键部署.md`:验证矩阵(按入口 IP 访问) - `03-02-k3s-traefik-acme.md`:PROXY protocol、trustedIPs ## 排障 - **先看 playbook 输出**:失败时先定位是 deploy/wait/http_check 哪一步。 - **集群侧总览**:`kubectl get nodes -o wide`、`kubectl -n kube-system get pods -o wide`。 - **事件与日志**:`kubectl -n describe ...`、`kubectl -n logs ... --tail=200`。