ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

k8s-5:Traefik 配置用户登录,限制 K8S 的 web 服务访问

k8s-5:Traefik 配置用户登录,限制 K8S 的 web 服务访问 1. 为什么 Traefik 暴露的 Web 服务需要加一层登录K8S 集群里用 Traefik 做 Ingress 网关最省事的地方在于一个 IngressRoute 或 Ingress 写几条规则域名就能直接指向后端 Service。但省事的另一面是——默认没有任何身份校验。Traefik Dashboard、Kubernetes Dashboard、内部 Grafana、Prometheus、ArgoCD 这类页面只要域名被解析、端口被放通任何人打开浏览器就能看到集群拓扑、Pod 状态、甚至直接操作资源。我见过最常见的翻车场景是测试环境图方便把 Dashboard 用PathPrefix: /挂到公网域名上结果被扫描器扫到集群里跑的东西一览无余。所以这一篇要解决的就是——在 Traefik 这一层给 Web 服务加用户登录让未登录请求在网关就被拦掉根本到不了后端。落地路径有两条一条是 Traefik 自带的BasicAuth Middleware用 htpasswd 生成账号密码配置量小、见效快适合 Dashboard、内部工具这类人少、要求不高的场景另一条是外部认证把请求转发给一个认证服务ForwardAuth适合要对接公司 SSO、要按用户区分权限的场景。本篇先把 BasicAuth 这条路径完整跑通再讲外部认证的接入骨架最后用 curl 验证未登录被拦、登录后放行。如果你后面还要在集群里跑 AI 编码 Agent、模型调用这类需要统一 Key 管理的服务可以顺带把 TaoToken 的 API 通道接进来让网关鉴权和模型调用鉴权各管一段后面第 4 节会给配置。2. 前置准备Traefik 版本、CRD 与 TaoToken 通道动手之前先确认三件事不然 YAML 写对了也跑不起来。第一Traefik 版本与 CRD 组名。老版本 Traefik 用的是traefik.containo.us/v1alpha1新版本v2.10 之后、v3已经改成traefik.io/v1alpha1。你集群里装的是哪个用这条命令看kubectl get crd | grep middlewares # 输出示例 # middlewares.traefik.containo.us 2024-xx-xx # 或 # middlewares.traefik.io 2024-xx-xxCRD 组名决定了 Middleware YAML 里apiVersion写什么写错会直接报no matches for kind Middleware。下面示例我统一用traefik.io/v1alpha1你按实际输出替换。第二Middleware 与 Ingress 的命名空间关系。Traefik 引用 Middleware 时跨命名空间要写成命名空间-中间件名kubernetescrd。比如 Middleware 在traefik命名空间、名字叫auth那 Ingress 注解里就写traefik-traefik-authkubernetescrd前缀是 Traefik 安装时的 release 名 命名空间。这个格式最容易写错后面排障会专门讲。第三TaoToken 统一 Key 通道。如果你的 Web 服务本身要调模型或 AI 能力建议把 Key 收敛到 TaoToken 一处管理网关这层只做登录校验业务层用统一 Key 调 API。TaoToken 的 API 入口是https://taotoken.net/api控制台在https://taotoken.net/consoleKey 在https://taotoken.net/api-keys生成。这样做的价值是登录账号和 API Key 解耦改密码不影响业务调用轮换 Key 也不用动 Ingress。注意BasicAuth 只解决谁能访问页面不解决页面里的服务能调什么。两层鉴权分开设计后面维护会轻松很多。3. 可复制配置BasicAuth Middleware IngressRoute 骨架这一节是全文核心按生成密码 → 建 Secret → 建 Middleware → 挂到 Ingress四步走每步都给可复制的命令和 YAML。3.1 用 htpasswd 生成账号密码htpasswd来自apache2-utilsDebian/Ubuntu或httpd-toolsCentOS/RHEL。没装的话先装# Debian/Ubuntu apt-get install -y apache2-utils # CentOS/RHEL yum install -y httpd-tools生成一对账号密码-nb表示不写文件、直接输出到终端htpasswd -nb admin admin123 # 输出 # admin:$apr1$itptjwcw$4De5.rgiMF8LwwLMs/vmm.这里admin是用户名admin123是密码冒号后面那串是 apr1 哈希。注意密码里如果有$、!这类字符用单引号包住否则 shell 会先做变量替换生成的哈希就错了。3.2 把哈希写进 SecretTraefik 的 BasicAuth 要求 Secret 里的users字段是base64 编码后的 htpasswd 内容。先生成 base64htpasswd -nb admin admin123 | openssl base64 -A # 输出 # YWRtaW46JGFwcjEkaXRwdGp3Y3ckNERlNS5yZ2lNRjhMd3dMTXMvdm1tLgo-A很关键它让 base64 输出成一行不加的话会换行Secret 里就会多出\nTraefik 解析失败。然后写 Secret YAMLapiVersion: v1 kind: Secret metadata: name: authsecret namespace: traefik type: Opaque data: users: | YWRtaW46JGFwcjEkaXRwdGp3Y3ckNERlNS5yZ2lNRjhMd3dMTXMvdm1tLgo应用它kubectl apply -f authsecret.yaml kubectl get secret authsecret -n traefik3.3 创建 BasicAuth MiddlewareMiddleware 负责怎么校验Secret 负责校验谁。两者分开改密码只动 Secret不动 MiddlewareapiVersion: traefik.io/v1alpha1 kind: Middleware metadata: name: auth namespace: traefik spec: basicAuth: secret: authsecretkubectl apply -f middleware.yaml kubectl get middleware -n traefik # NAME AGE # auth 10s3.4 挂到 IngressRoute 或 Ingress方式一IngressRouteTraefik 原生 CRD推荐apiVersion: traefik.io/v1alpha1 kind: IngressRoute metadata: name: dashboard-auth namespace: traefik spec: entryPoints: - websecure routes: - match: Host(dashboard.example.com) kind: Rule services: - name: kubernetes-dashboard port: 80 middlewares: - name: auth namespace: traefik tls: certResolver: letsencrypt方式二标准 Ingress 注解如果你用的是标准 IngressMiddleware 通过注解引用格式是命名空间-中间件名kubernetescrdapiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: dashboard-auth namespace: traefik annotations: traefik.ingress.kubernetes.io/router.entrypoints: websecure traefik.ingress.kubernetes.io/router.middlewares: traefik-authkubernetescrd spec: rules: - host: dashboard.example.com http: paths: - path: / pathType: Prefix backend: service: name: kubernetes-dashboard port: number: 80两种方式选一种即可。IngressRoute 的好处是中间件引用更直观、支持namespace字段标准 Ingress 的好处是兼容其他 Ingress Controller迁移成本低。3.5 外部认证ForwardAuth骨架如果 BasicAuth 不够用比如要对接公司 SSO、要按用户返回不同权限就用 ForwardAuthTraefik 把每个请求先转发给一个认证服务认证服务返回 2xx 就放行返回 401/403 就拦截。apiVersion: traefik.io/v1alpha1 kind: Middleware metadata: name: forward-auth namespace: traefik spec: forwardAuth: address: http://auth-service.auth.svc.cluster.local:4180/oauth2/auth trustForwardHeader: true authResponseHeaders: - X-Auth-User - X-Auth-Emailaddress指向你的认证服务比如 oauth2-proxy、Authelia。authResponseHeaders会把认证服务返回的用户信息透传给后端后端就能知道当前是谁在访问。这条路径配置量比 BasicAuth 大但扩展性强适合多用户、多角色的场景。4. 验证请求curl 测未登录拦截与登录放行配置写完不算完必须验证拦得住、放得行。用 curl 三步走。第一步不带凭证应该返回 401。curl -I https://dashboard.example.com/ # HTTP/2 401 # www-authenticate: Basic realmtraefik看到401和www-authenticate头说明 Middleware 生效了请求在网关就被拦下没到后端。第二步带错误密码应该还是 401。curl -I -u admin:wrongpass https://dashboard.example.com/ # HTTP/2 401第三步带正确凭证应该返回 200。curl -I -u admin:admin123 https://dashboard.example.com/ # HTTP/2 200 # content-type: text/html三步都符合预期BasicAuth 就通了。浏览器访问会弹出原生登录框输入账号密码后进入 Dashboard。第四步可选验证 TaoToken 通道。如果后端服务要调模型用统一 Key 测一下 API 连通性curl -s https://taotoken.net/api/v1/models \ -H Authorization: Bearer $TAOTOKEN_API_KEY | head -c 300返回模型列表就说明 Key 通道正常。这样网关鉴权和 API 鉴权各测一遍问题定位时能快速区分是哪一层出的错。5. 本篇常见错排查配置过程中最容易踩的坑集中在下面几个按出现频率排序。报错一no matches for kind Middleware。原因是apiVersion写错。老集群是traefik.containo.us/v1alpha1新集群是traefik.io/v1alpha1。用kubectl get crd | grep middlewares确认后替换。报错二访问返回 404不是 401。说明 Middleware 没被引用上。检查 Ingress 注解里的traefik-release-namekubernetescrd格式前缀是 Traefik 安装时的 release 名和命名空间不是随便写的。用helm list -A | grep traefik看 release 名用kubectl get middleware -A看中间件实际在哪个命名空间。报错三登录框反复弹出密码明明对。九成是 Secret 里的 base64 有问题。检查两点openssl base64有没有加-A不加会换行htpasswd生成时密码有没有被 shell 吃掉特殊字符。重新生成一遍用kubectl get secret authsecret -n traefik -o jsonpath{.data.users} | base64 -d看解码后内容对不对。报错四改了密码不生效。Secret 更新后 Traefik 不会自动重载需要滚动重启或等它 watch 到变更。稳妥做法是用kubectl create secret ... --dry-runclient -o yaml | kubectl apply -f -更新然后kubectl rollout restart deployment traefik -n traefik。htpasswd -nb admin newpass456 | openssl base64 -A /tmp/users.b64 kubectl create secret generic authsecret -n traefik \ --from-fileusers/tmp/users.b64 \ --dry-runclient -o yaml | kubectl apply -f - kubectl rollout restart deployment traefik -n traefik报错五ForwardAuth 一直 500。检查address能不能从 Traefik Pod 里访问到用kubectl exec -it traefik-pod -n traefik -- wget -qO- http://auth-service.auth.svc.cluster.local:4180/oauth2/auth测连通性。DNS 名写错、Service 端口不对、认证服务本身没起来都会导致 500。报错六TLS 证书没签发浏览器提示不安全。这跟 BasicAuth 无关是 certResolver 配置问题。确认certResolver名字和 Traefik 静态配置里的一致且域名能通过 ACME 挑战。6. 下一步把鉴权与 Key 管理分开维护BasicAuth 跑通之后建议做两件事让后续维护更省心。一是把 Middleware 和 Secret 拆成独立文件用 Git 管理。改密码只提交 Secret 变更改校验逻辑只提交 Middleware 变更回滚时边界清晰。二是把业务层的 API Key 收敛到 TaoToken网关这层只管谁能进业务层用统一 Key 调模型Key 轮换、额度查看都在控制台一处完成不用在多个 Ingress 注解里翻。如果你后面要在集群里跑长期编码 Agent 或自动化任务可以看下 Coding Plan 的接入方式把模型调用通道固定下来日常调试模型行为用模型对话页面直接验证Key 的生成和轮换在 API Keys 页面操作接入细节和参数说明在接入文档里查。这几处配合起来网关鉴权和模型鉴权就是两条独立的线出问题时能快速定位是哪一层。
返回列表