主题
Kubernetes 1.36 使用 Helm 部署 Traefik(HAProxy 四层负载均衡)
本文适用于使用 kubeadm 部署的 Kubernetes v1.36 集群。集群外部继续使用 HAProxy 作为四层负载均衡器,集群内部使用 Traefik 处理域名、路径和 TLS 等七层路由,并通过 PROXY Protocol v2 将真实客户端 IP 传递给业务应用。
文档版本基线:2026-09-04。本文固定使用 Helm v4.2.4、Traefik Helm Chart 41.4.0、Traefik Proxy v3.7.12,避免安装过程中因上游最新版变化而产生不可预期的配置差异。
一、部署架构
1.1 节点规划
| 角色 | 主机名 | IP 地址 | 用途 |
|---|---|---|---|
| 外部负载均衡 | haproxy | 172.22.33.99 | 对外监听 80/443,并转发到 Traefik NodePort |
| 控制平面 | k8s-master01 | 172.22.33.100 | Kubernetes 控制平面 |
| 工作节点 | k8s-node01 | 172.22.33.101 | 运行 Traefik DaemonSet 和业务 Pod |
| 工作节点 | k8s-node02 | 172.22.33.102 | 运行 Traefik DaemonSet 和业务 Pod |
Traefik 使用 DaemonSet,并通过节点亲和性排除带有 node-role.kubernetes.io/control-plane 标签的节点。以后新增普通 Worker 节点并加入集群后,不需要再手工添加 Traefik 专用标签,DaemonSet 会自动在新 Worker 上创建一个 Traefik Pod。
1.2 端口规划
| 流量 | HAProxy 监听端口 | Traefik NodePort | Traefik 容器端口 |
|---|---|---|---|
| HTTP | 80 | 32280 | 8000 |
| HTTPS | 443 | 32443 | 8443 |
1.3 HTTPS 请求链路
text
客户端
│ HTTPS
▼
172.22.33.99:443 HAProxy
│ mode tcp + send-proxy-v2
▼
172.22.33.101:32443 / 172.22.33.102:32443
│ externalTrafficPolicy: Local
▼
Traefik DaemonSet
│ TLS 终止、域名和路径匹配、生成 X-Forwarded-For
▼
main-app-service:80
▼
Demo Nginx PodHAProxy 只做四层转发,不解密 HTTPS。TLS 证书由 Traefik 读取 Kubernetes Secret 后使用。
二、部署前检查
以下操作如果没有特别说明,均在 k8s-master01 上使用 root 用户执行。
2.1 检查 Kubernetes 集群
bash
kubectl get nodes -o wide
kubectl get pods -A确认三个 Kubernetes 节点均为 Ready,Calico、CoreDNS 和 kube-proxy 正常运行。
2.2 检查 NodePort 范围
本文使用 32280 和 32443,均位于 Kubernetes 默认 NodePort 范围 30000-32767 内。
确认端口没有被其他 Service 占用:
bash
kubectl get svc -A -o wide | grep -E '32280|32443' || true如果集群中已经运行 ingress-nginx 并占用了这两个 NodePort,应先使用其他端口部署 Traefik 并完成迁移验证,不能让两个 Service 同时占用相同 NodePort。
2.3 检查域名&提供SSL证书
本文使用:
text
Demo 域名:demo.srebro.cn
TLS Secret:srebro.cn-tls正式 DNS 应将 demo.srebro.cn 解析到 HAProxy 地址:
text
demo.srebro.cn -> 172.22.33.99如果暂时不修改 DNS,可以在测试客户端的 /etc/hosts 中添加:
text
172.22.33.99 demo.srebro.cn2.4 检查镜像访问
本文使用 Traefik 官方镜像 docker.io/traefik:v3.7.12。
bash
docker pull traefik:v3.7.12
# 或者使用加速镜像
docker pull docker.cnb.cool/srebro/docker-images-chrom/traefik:v3.7.12_amd64如果生产环境不能直接访问 Docker Hub,可以提前登录到 node 节点上下载好加速地址的镜像。
三、安装 Helm
3.1 Helm 基本概念
- Chart:一组 Kubernetes YAML 模板组成的软件包,例如
traefik/traefik。 - Release:Chart 安装到集群后形成的一个实例,本文 Release 名称为
traefik。 - values.yaml:覆盖 Chart 默认配置的参数文件,本文用于定义 DaemonSet、NodePort 和 PROXY Protocol。
- Repository:保存和分发 Chart 的仓库。
3.2 下载 Helm
bash
wget https://get.helm.sh/helm-v4.2.4-linux-amd64.tar.gz3.3 安装 Helm 二进制
bash
tar -xf helm-v4.2.4-linux-amd64.tar.gz
install -m 0755 "linux-amd64/helm" /usr/local/bin/helm
helm version预期能够看到 v4.2.4。Helm 只需要安装在执行部署命令的管理节点上,不需要安装到所有 Kubernetes 节点。
3.4 验证 Helm 能访问集群
bash
kubectl config current-context
helm list -A如果 Helm 报 kubeconfig 权限问题,先确认当前用户执行 kubectl get nodes 是否正常。不要把管理员 kubeconfig 随意复制给普通用户。
四、准备 Traefik Helm Chart
4.1 添加 Traefik Chart 仓库
bash
helm repo add traefik https://traefik.github.io/charts
helm repo update
helm search repo traefik/traefik --versions | head -20示例输出:
text
NAME CHART VERSION APP VERSION DESCRIPTION
traefik/traefik 41.4.0 v3.7.12 A Traefik based Kubernetes ingress controller
traefik/traefik 41.3.0 v3.7.11 A Traefik based Kubernetes ingress controller
traefik/traefik 41.2.0 v3.7.10 A Traefik based Kubernetes ingress controller
traefik/traefik 41.1.1 v3.7.9 A Traefik based Kubernetes ingress controller
traefik/traefik 41.1.0 v3.7.9 A Traefik based Kubernetes ingress controller
traefik/traefik 41.0.2 v3.7.6 A Traefik based Kubernetes ingress controller
traefik/traefik 41.0.1 v3.7.5 A Traefik based Kubernetes ingress controller
traefik/traefik 41.0.0 v3.7.5 A Traefik based Kubernetes ingress controller
traefik/traefik 40.3.0 v3.7.4 A Traefik based Kubernetes ingress controller
traefik/traefik 40.2.0 v3.7.1 A Traefik based Kubernetes ingress controller
traefik/traefik 40.1.0 v3.7.1 A Traefik based Kubernetes ingress controller
traefik/traefik 40.0.1 v3.7.0 A Traefik based Kubernetes ingress controller
traefik/traefik 40.0.0 v3.7.0 A Traefik based Kubernetes ingress controller
traefik/traefik 39.0.9 v3.6.15 A Traefik based Kubernetes ingress controller
traefik/traefik 39.0.8 v3.6.13 A Traefik based Kubernetes ingress controller
traefik/traefik 39.0.7 v3.6.12 A Traefik based Kubernetes ingress controller
traefik/traefik 39.0.6 v3.6.11 A Traefik based Kubernetes ingress controller
traefik/traefik 39.0.5 v3.6.10 A Traefik based Kubernetes ingress controller
traefik/traefik 39.0.4 v3.6.9 A Traefik based Kubernetes ingress controller确认列表中存在 Chart 41.4.0,对应的 Traefik 版本是 v3.7.12
4.2 创建工作目录
bash
mkdir -p /etc/kubernetes/addons/traefik
cd /etc/kubernetes/addons/traefik保存一份官方默认配置,便于后续查询参数:
bash
helm show values traefik/traefik \
--version 41.4.0 > traefik-default-values.yaml4.3 创建 traefik-values.yaml
bash
cat >/etc/kubernetes/addons/traefik/traefik-values.yaml <<'EOF'
image:
registry: docker.io
repository: traefik
tag: v3.7.12
pullPolicy: IfNotPresent
# 每个非 control-plane 节点运行一个 Traefik Pod;新增 Worker 后自动运行。
deployment:
kind: DaemonSet
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: node-role.kubernetes.io/control-plane
operator: DoesNotExist
updateStrategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 1
maxSurge: 0
ingressClass:
enabled: true
isDefaultClass: false
name: traefik
providers:
kubernetesCRD:
enabled: true
allowCrossNamespace: false
allowExternalNameServices: false
kubernetesIngress:
enabled: true
allowExternalNameServices: false
publishedService:
enabled: false
ingressEndpoint:
ip: 172.22.33.99
kubernetesGateway:
enabled: false
gateway:
enabled: false
gatewayClass:
enabled: false
api:
dashboard: true
insecure: false
# 不使用 Chart 自动公开 Dashboard,后文单独创建带认证的 IngressRoute。
ingressRoute:
dashboard:
enabled: false
service:
enabled: true
spec:
type: NodePort
externalTrafficPolicy: Local
ports:
traefik:
port: 8080
expose:
default: false
web:
port: 8000
expose:
default: true
exposedPort: 80
nodePort: 32280
protocol: TCP
proxyProtocol:
# 只信任外部 HAProxy,不使用 insecure=true。
trustedIPs:
- 172.22.33.99/32
insecure: false
http:
redirections:
entryPoint:
to: websecure
scheme: https
permanent: true
websecure:
port: 8443
expose:
default: true
exposedPort: 443
nodePort: 32443
protocol: TCP
proxyProtocol:
# 必须与 HAProxy 的 send-proxy-v2 配合。
trustedIPs:
- 172.22.33.99/32
insecure: false
log:
level: INFO
accessLog:
enabled: true
format: json
fields:
defaultMode: keep
headers:
defaultMode: drop
resources:
requests:
cpu: 100m
memory: 128Mi
limits:
cpu: 1000m
memory: 512Mi
EOF关键配置说明:
image.registry/repository/tag:Helm 最终拉取官方镜像docker.io/traefik:v3.7.12。deployment.kind: DaemonSet:每个符合调度条件的非控制平面节点运行一个 Traefik Pod。requiredDuringSchedulingIgnoredDuringExecution:强制排除带有node-role.kubernetes.io/control-plane标签的节点;以后新增普通 Worker 后,无需修改 Helm values,DaemonSet 会自动在新节点创建 Pod。externalTrafficPolicy: Local:HAProxy 访问某个 Worker 的 NodePort 时,只转发给本机 Traefik Pod,不跨节点转发。proxyProtocol.trustedIPs:Traefik 只接受172.22.33.99传入的 PROXY Protocol 地址。ingressEndpoint.ip:让 Ingress 状态显示 HAProxy 地址172.22.33.99。isDefaultClass: false:业务必须显式填写ingressClassName: traefik,避免误接管其他 Ingress。api.insecure: false:禁止无认证暴露 Traefik API 和 Dashboard。
不要配置以下参数:
yaml
proxyProtocol:
insecure: true该参数会信任任意来源提交的 PROXY Protocol 地址,存在伪造客户端 IP 的风险。
五、使用 Helm 部署 Traefik
5.1 渲染并检查 YAML
在真正安装前,先渲染 Chart:
bash
cd /etc/kubernetes/addons/traefik
helm template traefik traefik/traefik \
--namespace traefik \
--version 41.4.0 \
--values traefik-values.yaml \
--include-crds \
> traefik-rendered.yaml检查关键配置:
bash
grep -nE 'kind: DaemonSet|node-role.kubernetes.io/control-plane|nodePort: 32280|nodePort: 32443|externalTrafficPolicy: Local' \
traefik-rendered.yaml示例输出:
text
8800: externalTrafficPolicy: Local
8810: nodePort: 32280
8815: nodePort: 32443
8819:kind: DaemonSet
8858: - key: node-role.kubernetes.io/control-plane5.2 安装 Traefik
bash
helm upgrade --install traefik traefik/traefik \
--namespace traefik \
--create-namespace \
--version 41.4.0 \
--values /etc/kubernetes/addons/traefik/traefik-values.yaml \
--atomic \
--wait \
--timeout 10m参数说明:
upgrade --install:不存在时安装,已经存在时升级,便于重复执行。--version 41.4.0:固定 Chart 版本。--values:使用本文准备的配置文件。--atomic:安装失败时自动回滚本次 Release。--wait:等待 Pod 和 Service 就绪后再返回。--timeout 10m:镜像下载较慢时最多等待 10 分钟。
首次安装时 Helm 会安装 Traefik CRD。后续升级 Chart 时,Helm 不会自动升级已经存在的 CRD,升级章节会单独说明处理方式。
5.3 检查 Helm Release
bash
helm list -n traefik
helm status traefik -n traefik
helm get values traefik -n traefik
helm history traefik -n traefik5.4 检查 Kubernetes 资源
bash
kubectl get crd | grep traefik.io
kubectl get ingressclass
kubectl get daemonset,pod,svc -n traefik -o wide预期结果:
IngressClass中存在traefik。- 当前三节点集群中,
DaemonSet的DESIRED/CURRENT/READY均应为 2;以后增加 Worker 后,该数字应等于非控制平面节点数量。 - 每个非控制平面节点都有一个 Ready Traefik Pod,
k8s-master01上没有 Traefik Pod。 - Service 显示
80:32280/TCP和443:32443/TCP。
进一步检查:
bash
kubectl -n traefik describe daemonset traefik
kubectl -n traefik describe service traefik
kubectl -n traefik logs daemonset/traefik --tail=200六、配置 HAProxy
本章在 HAProxy 服务器 172.22.33.99 上执行。
6.1 备份 HAProxy 配置
bash
cp -a /etc/haproxy/haproxy.cfg \
/etc/haproxy/haproxy.cfg.$(date +%Y%m%d%H%M%S).bak6.2 添加 HTTP/HTTPS 转发
编辑 /etc/haproxy/haproxy.cfg,保留原 Kubernetes API Server 6443 配置,增加或替换原 ingress-nginx 的 80/443 配置:
haproxy
global
log /dev/log local0 warning
chroot /var/lib/haproxy
pidfile /var/run/haproxy.pid
maxconn 4000
user haproxy
group haproxy
daemon
stats socket /var/lib/haproxy/stats
defaults
log global
option tcplog
option dontlognull
timeout connect 5s
timeout client 1h
timeout server 1h
frontend traefik-http
bind *:80
mode tcp
option tcplog
default_backend traefik-http
backend traefik-http
mode tcp
option tcp-check
balance roundrobin
default-server inter 10s downinter 5s rise 2 fall 2
server k8s-node01 172.22.33.101:32280 check send-proxy-v2
server k8s-node02 172.22.33.102:32280 check send-proxy-v2
frontend traefik-https
bind *:443
mode tcp
option tcplog
default_backend traefik-https
backend traefik-https
mode tcp
option tcp-check
balance roundrobin
default-server inter 10s downinter 5s rise 2 fall 2
server k8s-node01 172.22.33.101:32443 check send-proxy-v2
server k8s-node02 172.22.33.102:32443 check send-proxy-v2注意:
- 同一个 HAProxy 实例只能有一个配置绑定
*:80,也只能有一个配置绑定*:443。 - 如果旧 ingress-nginx frontend 仍然绑定这些端口,应修改原配置,不能重复新增相同监听端口。
send-proxy-v2必须保留,否则 Traefik 无法取得真实客户端 IP。- 当前 HAProxy 配置的是两个 Worker 节点,不是控制平面节点。以后新增 Worker 时,需要把新节点的 NodePort 地址加入两个 backend。
6.3 检查并重新加载 HAProxy
bash
haproxy -c -f /etc/haproxy/haproxy.cfg必须看到配置校验成功后才能重新加载:
bash
systemctl reload haproxy
systemctl status haproxy --no-pager
ss -lntp | grep -E ':80 |:443 '检查 HAProxy 到两个 NodePort 的网络:
bash
nc -vz 172.22.33.101 32280
nc -vz 172.22.33.102 32280
nc -vz 172.22.33.101 32443
nc -vz 172.22.33.102 32443externalTrafficPolicy: Local 要求 HAProxy 只访问确实运行着 Ready Traefik Pod 的节点。本文使用 DaemonSet 和排除控制平面节点的节点亲和性确保这一点。
6.4 新增 Worker 节点后的操作
新 Worker 加入集群并变为 Ready 后,DaemonSet 会自动在该节点启动 Traefik,不需要修改 traefik-values.yaml。先确认新节点没有控制平面标签,并检查 Traefik Pod:
bash
kubectl get node <新节点名称> -L node-role.kubernetes.io/control-plane
kubectl -n traefik get pods -o wide等待新节点上的 Traefik Pod 变为 Ready 后,在 HAProxy 主机验证 NodePort。将占位符替换为实际 IP:
bash
nc -vz <新节点IP> 32280
nc -vz <新节点IP> 32443然后分别在 backend traefik-http 和 backend traefik-https 中增加新节点。例如新增 k8s-node03,IP 为 172.22.33.103:
haproxy
backend traefik-http
# 保留已有 server 行
server k8s-node03 172.22.33.103:32280 check send-proxy-v2
backend traefik-https
# 保留已有 server 行
server k8s-node03 172.22.33.103:32443 check send-proxy-v2校验并重新加载 HAProxy:
bash
haproxy -c -f /etc/haproxy/haproxy.cfg
systemctl reload haproxy注意:DaemonSet 能自动覆盖新增 Worker,但 HAProxy 使用的是静态 server 列表,不会自动发现 Kubernetes 新节点,因此每次扩容都必须同步更新 HAProxy 后端。
七、创建 TLS Secret
回到 k8s-master01 执行。
假设证书文件为:
text
/etc/kubernetes/addons/traefik/cert/srebro.cn.pem
/etc/kubernetes/addons/traefik/cert/srebro.cn.key创建或更新 default 命名空间下的 TLS Secret:
bash
kubectl -n default create secret tls srebro.cn-tls \
--cert=/etc/kubernetes/addons/traefik/cert/srebro.cn.pem \
--key=/etc/kubernetes/addons/traefik/cert/srebro.cn.key \
--dry-run=client -o yaml | kubectl apply -f -检查 Secret:
bash
kubectl -n default get secret srebro.cn-tls
kubectl -n default describe secret srebro.cn-tls私钥属于敏感数据,不要将证书私钥直接写入 Git 仓库或本文档。
八、部署 Demo 网站
8.1 创建 Deployment、Service 和测试页面
Demo Nginx 会显示它识别到的客户端 IP 和 Traefik 传入的请求头,方便验证真实 IP 透传。
bash
cat >/etc/kubernetes/addons/traefik/demo-app.yaml <<'EOF'
apiVersion: v1
kind: ConfigMap
metadata:
name: main-app-nginx-config
namespace: default
data:
default.conf: |
# 不使用镜像 nginx.conf 中已经定义的 main,避免 log_format 重名。
log_format traefik_demo '$remote_addr - $host "$request" $status '
'xff="$http_x_forwarded_for" xri="$http_x_real_ip"';
server {
listen 80;
server_name _;
# Traefik Pod 位于 Kubernetes Pod CIDR 中。
set_real_ip_from 10.244.0.0/16;
real_ip_header X-Forwarded-For;
real_ip_recursive on;
access_log /var/log/nginx/access.log traefik_demo;
location / {
default_type text/plain;
return 200 "Traefik demo OK\nremote_addr=$remote_addr\nx_real_ip=$http_x_real_ip\nx_forwarded_for=$http_x_forwarded_for\nhost=$host\n";
}
}
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: main-app
namespace: default
spec:
replicas: 2
selector:
matchLabels:
app: main-app
template:
metadata:
labels:
app: main-app
spec:
containers:
- name: nginx
#image: nginx:1.30.4
image: docker.cnb.cool/srebro/docker-images-chrom/nginx:1.30.4_amd64
imagePullPolicy: IfNotPresent
ports:
- name: http
containerPort: 80
readinessProbe:
httpGet:
path: /
port: http
initialDelaySeconds: 2
periodSeconds: 5
resources:
requests:
cpu: 20m
memory: 32Mi
limits:
cpu: 200m
memory: 128Mi
volumeMounts:
- name: nginx-config
mountPath: /etc/nginx/conf.d/default.conf
subPath: default.conf
readOnly: true
volumes:
- name: nginx-config
configMap:
name: main-app-nginx-config
---
apiVersion: v1
kind: Service
metadata:
name: main-app-service
namespace: default
spec:
selector:
app: main-app
ports:
- name: http
port: 80
targetPort: http
protocol: TCP
EOF
kubectl apply -f /etc/kubernetes/addons/traefik/demo-app.yaml检查应用:
bash
kubectl -n default get pod -l app=main-app -o wide
kubectl -n default get service main-app-service
kubectl -n default get endpointslice -l kubernetes.io/service-name=main-app-service8.2 创建 Traefik Ingress
原 ingress-nginx 案例使用:
yaml
nginx.ingress.kubernetes.io/use-regex: "true"
nginx.ingress.kubernetes.io/rewrite-target: /$2并使用路径 /()(.*)。该规则实际上没有改变请求路径,因此迁移后直接使用标准的 / Prefix 即可,不需要 Middleware。
bash
cat >/etc/kubernetes/addons/traefik/demo-ingress.yaml <<'EOF'
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: baseline-sre-test-ingress
namespace: default
annotations:
traefik.ingress.kubernetes.io/router.entrypoints: websecure
spec:
ingressClassName: traefik
tls:
- hosts:
- demo.srebro.cn
secretName: srebro.cn-tls
rules:
- host: demo.srebro.cn
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: main-app-service
port:
number: 80
EOF
kubectl apply -f /etc/kubernetes/addons/traefik/demo-ingress.yaml检查 Ingress:
bash
kubectl -n default get ingress baseline-sre-test-ingress -o wide
kubectl -n default describe ingress baseline-sre-test-ingressCLASS 应为 traefik,ADDRESS 应显示 172.22.33.99。
九、验证访问和真实客户端 IP
9.1 验证 HTTP 跳转 HTTPS
在 HAProxy 之外的客户端执行:
bash
curl -I --resolve demo.srebro.cn:80:172.22.33.99 \
http://demo.srebro.cn/预期返回 301 或 308,Location 指向:
text
https://demo.srebro.cn/9.2 验证 HTTPS
bash
curl -v --resolve demo.srebro.cn:443:172.22.33.99 \
https://demo.srebro.cn/如果测试证书尚未被客户端信任,可以临时增加 -k,但生产验证应使用完整可信证书链:
bash
curl -vk --resolve demo.srebro.cn:443:172.22.33.99 \
https://demo.srebro.cn/预期响应类似:
text
Traefik demo OK
remote_addr=192.0.2.50
x_real_ip=192.0.2.50
x_forwarded_for=192.0.2.50
host=demo.srebro.cn其中 remote_addr 应是测试客户端地址,而不是:
text
172.22.33.99
172.22.33.101
172.22.33.102
10.244.x.x9.3 检查 Traefik 和业务日志
bash
kubectl -n traefik logs daemonset/traefik --tail=100
kubectl -n default logs deployment/main-app --tail=100真实 IP 传递链路为:
text
客户端 IP
-> HAProxy send-proxy-v2
-> Traefik web/websecure.proxyProtocol.trustedIPs
-> X-Forwarded-For / X-Real-Ip
-> Nginx real_ip 模块
-> $remote_addrexternalTrafficPolicy: Local 负责避免 NodePort 在 Worker 之间二次转发,但它不能代替 PROXY Protocol。因为客户端首先连接 HAProxy,如果没有 send-proxy-v2,Traefik 看到的只能是 HAProxy 地址。
十、安全启用 Traefik Dashboard
Dashboard 用于查看 EntryPoint、Router、Middleware 和 Service 状态,它不是用于点击修改 Kubernetes 配置的管理后台。
本节使用独立域名:
text
traefik.srebro.cn -> 172.22.33.9910.1 创建 Dashboard TLS Secret
Secret 不能跨命名空间引用,因此需要在 traefik 命名空间再创建一份 TLS Secret:
bash
kubectl -n traefik create secret tls srebro.cn-tls \
--cert=/etc/kubernetes/addons/traefik/cert/srebro.cn.pem \
--key=/etc/kubernetes/addons/traefik/cert/srebro.cn.key \
--dry-run=client -o yaml | kubectl apply -f -10.2 创建 BasicAuth Secret
安装 htpasswd:
bash
dnf install -y httpd-tools
mkdir -p /etc/kubernetes/addons/traefik/secrets
chmod 700 /etc/kubernetes/addons/traefik/secrets交互式设置管理员密码,避免把明文密码写进 Shell 历史:
bash
htpasswd -cB /etc/kubernetes/addons/traefik/secrets/dashboard-users admin创建 Secret:
bash
kubectl -n traefik create secret generic traefik-dashboard-auth \
--from-file=users=/etc/kubernetes/addons/traefik/secrets/dashboard-users \
--dry-run=client -o yaml | kubectl apply -f -10.3 创建 Dashboard Middleware 和 IngressRoute
bash
cat >/etc/kubernetes/addons/traefik/dashboard.yaml <<'EOF'
apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
name: traefik-dashboard-auth
namespace: traefik
spec:
basicAuth:
secret: traefik-dashboard-auth
---
apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata:
name: traefik-dashboard
namespace: traefik
spec:
ingressClassName: traefik
entryPoints:
- websecure
routes:
- kind: Rule
match: Host(`traefik.srebro.cn`) && (PathPrefix(`/api`) || PathPrefix(`/dashboard`))
middlewares:
- name: traefik-dashboard-auth
services:
- name: api@internal
kind: TraefikService
tls:
secretName: srebro.cn-tls
EOF
kubectl apply -f /etc/kubernetes/addons/traefik/dashboard.yaml检查资源:
bash
kubectl -n traefik get middleware,ingressroute
kubectl -n traefik describe ingressroute traefik-dashboard访问:
text
https://traefik.srebro.cn/dashboard/最后的 / 不能省略。不要给 Traefik 8080 管理端口创建公网 NodePort,也不要设置 api.insecure=true。


十一、扩展四层 TCP 服务
如果还要通过 Traefik 代理 MySQL、Redis 或其他 TCP 服务,需要同时增加:
- Traefik EntryPoint。
- Traefik Service 中的固定 NodePort。
IngressRouteTCP。- HAProxy TCP frontend/backend。
以 MySQL 为例,可以在 traefik-values.yaml 的 ports 下增加:
yaml
mysql:
port: 3306
expose:
default: true
exposedPort: 3306
nodePort: 32306
protocol: TCP
proxyProtocol:
trustedIPs:
- 172.22.33.99/32
insecure: false更新 Traefik:
bash
helm upgrade traefik traefik/traefik \
--namespace traefik \
--version 41.4.0 \
--values /etc/kubernetes/addons/traefik/traefik-values.yaml \
--atomic --wait --timeout 10m创建 TCP 路由:
yaml
apiVersion: traefik.io/v1alpha1
kind: IngressRouteTCP
metadata:
name: mysql
namespace: database
spec:
ingressClassName: traefik
entryPoints:
- mysql
routes:
- match: HostSNI(`*`)
services:
- name: mysql
port: 3306HAProxy 对应配置:
haproxy
frontend mysql
bind *:3306
mode tcp
option tcplog
default_backend traefik-mysql
backend traefik-mysql
mode tcp
option tcp-check
balance roundrobin
server k8s-node01 172.22.33.101:32306 check send-proxy-v2
server k8s-node02 172.22.33.102:32306 check send-proxy-v2对于 HTTP/HTTPS,Traefik 可以通过 X-Forwarded-For 把客户端地址交给应用。纯 TCP 没有 HTTP Header;如果 TCP 后端也必须取得客户端地址,需要通过 ServersTransportTCP 继续向后端发送 PROXY Protocol,并且后端程序本身必须支持 PROXY Protocol。否则后端只能看到 Traefik 的连接地址。
数据库等敏感服务不应默认暴露到公网,应同时使用网络 ACL、HAProxy 源地址限制或 Traefik MiddlewareTCP IPAllowList。
十二、Helm 常用运维命令
12.1 查看当前配置
bash
helm list -n traefik
helm status traefik -n traefik
helm get values traefik -n traefik --all
helm get manifest traefik -n traefik
helm history traefik -n traefik12.2 修改配置
修改:
text
/etc/kubernetes/addons/traefik/traefik-values.yaml然后执行:
bash
helm upgrade traefik traefik/traefik \
--namespace traefik \
--version 41.4.0 \
--values /etc/kubernetes/addons/traefik/traefik-values.yaml \
--atomic --wait --timeout 10m12.3 回滚
查看历史版本:
bash
helm history traefik -n traefik回滚到指定修订,例如 Revision 1:
bash
helm rollback traefik 1 -n traefik --wait --timeout 10m12.4 升级 Chart 和 CRD
先阅读目标版本的发布说明。Traefik Chart 的大版本可能包含不兼容变更,不能只修改版本号后直接升级。
bash
helm repo update
helm search repo traefik/traefik --versions | head -20假设目标版本为 <NEW_CHART_VERSION>,先升级 CRD:
bash
helm show crds traefik/traefik \
--version <NEW_CHART_VERSION> | \
kubectl apply --server-side --force-conflicts -f -再升级 Release:
bash
helm upgrade traefik traefik/traefik \
--namespace traefik \
--version <NEW_CHART_VERSION> \
--values /etc/kubernetes/addons/traefik/traefik-values.yaml \
--atomic --wait --timeout 10m不要使用 --reuse-values 跨 Traefik Chart 大版本升级,因为旧字段可能与新 Chart 默认值冲突。
12.5 卸载说明
以下命令会删除 Traefik Release,执行前先确认业务入口已经迁移:
bash
helm uninstall traefik -n traefikHelm 卸载通常不会自动删除 CRD;直接删除 CRD 会连带删除对应的 IngressRoute、Middleware 等自定义资源,因此不要在生产集群中随意执行 CRD 删除命令。
十三、常见问题
13.1 HAProxy 到 NodePort 不通
检查:
bash
kubectl -n traefik get pod -o wide
kubectl -n traefik get svc traefik -o yaml
iptables -t nat -L KUBE-NODEPORTS -n | grep -E '32280|32443'在 HAProxy 节点测试:
bash
nc -vz 172.22.33.101 32443
nc -vz 172.22.33.102 32443使用 externalTrafficPolicy: Local 时,目标 Worker 必须有本机 Ready Traefik Pod。
十四、参考资料
- 旧 ingress-nginx 案例:IngressNginx v1.14.3 部署笔记
- Helm 安装文档:https://helm.sh/docs/intro/install/
- Helm Releases:https://github.com/helm/helm/releases
- Traefik Helm Chart:https://github.com/traefik/traefik-helm-chart
- Traefik Chart 41.4.0:https://artifacthub.io/packages/helm/traefik/traefik/41.4.0
- Traefik Kubernetes Ingress:https://doc.traefik.io/traefik/reference/routing-configuration/kubernetes/ingress/
- Traefik Kubernetes CRD:https://doc.traefik.io/traefik/reference/install-configuration/providers/kubernetes/kubernetes-crd/
- Traefik EntryPoint 和 PROXY Protocol:https://doc.traefik.io/traefik/reference/install-configuration/entrypoints/
- Traefik Dashboard:https://doc.traefik.io/traefik/operations/dashboard/
- Traefik IngressRouteTCP:https://doc.traefik.io/traefik/reference/routing-configuration/kubernetes/crd/tcp/ingressroutetcp/
