第31篇 k8s之Ingress 进阶:TLS、重写与认证

IT策士 10余年一线大厂经验,专注 IT 思维、架构、职场进阶。我会在各个平台持续发布最新文章,助你少走弯路。


在第 30 篇中,我们用 Ingress 实现了基于域名和路径的 HTTP 路由,把外部流量分发到了 Flask 应用。但那是"裸奔"的 HTTP------所有数据明文传输,任何人都能嗅探。生产环境的最低安全标准是什么?HTTPS

此外,真实业务中还有两个高频需求:应用可能部署在某个子路径下(如 /api),但代码里写的是根路径 /,这就需要路径重写;某些管理页面希望加上简单的用户名密码保护,而不想改动应用代码。

今天这篇,我们就在第 30 篇的基础上,给 Ingress 加上 TLS 证书路径重写Basic Auth 认证,让你的外部入口达到生产级标准。

一、TLS 证书:给 Ingress 加上 HTTPS

1.1 什么是 TLS?

TLS(Transport Layer Security)是 HTTPS 的基础。它在客户端和服务器之间建立加密通道,确保数据传输不被窃听或篡改。在 K8s 中,TLS 私钥和证书通过 Secret 对象存储,然后在 Ingress YAML 中引用。

你可能会问:这和 Compose 时代用 Nginx 配置 SSL 有什么区别?在 Compose 中,你需要手动把证书文件复制到容器内,修改 Nginx 配置文件,然后重启容器。而在 K8s 中,证书作为 Secret 资源独立管理,Ingress Controller 自动处理 TLS 握手和证书加载,证书更新时只需更新 Secret,无需重启应用 Pod。

1.2 创建自签名证书(实验环境)

生产环境应使用 Let's Encrypt 或购买 CA 签发的证书。实验环境中我们用 OpenSSL 生成自签名证书:

bash 复制代码
# 生成私钥和自签名证书(有效期 365 天)
openssl req -x509 -newkey rsa:4096 -keyout tls.key -out tls.crt -days 365 -nodes \
  -subj "/CN=counter.example.com"

命令参数说明:

  • -x509:生成自签名证书而非证书签名请求

  • -newkey rsa:4096:生成 4096 位 RSA 私钥

  • -days 365:证书有效期 365 天

  • -nodes:不加密私钥(避免 K8s Secret 加载时需要密码)

  • -subj "/CN=counter.example.com":证书的 Common Name,必须与 Ingress 中的 host 一致,否则浏览器会报证书名称不匹配

1.3 创建 TLS Secret

bash 复制代码
kubectl create secret tls counter-tls \
  --cert=tls.crt \
  --key=tls.key

输出:

bash 复制代码
secret/counter-tls created

查看 Secret:

bash 复制代码
kubectl describe secret counter-tls

输出中只会显示证书和密钥的字节数,不会显示原文------K8s 对 Secret 内容进行了 base64 编码存储,虽然并非强加密,但比明文存放更安全:

bash 复制代码
Name:         counter-tls
Type:         kubernetes.io/tls
Data:
tls.crt:      1964 bytes
tls.key:      3244 bytes

安全提醒 :自签名证书仅用于实验。生产环境中,tls.key 私钥属于最高级别的敏感信息,绝不提交到 Git。本系列第 33 篇将介绍如何使用 Sealed Secrets 加密后安全存储。

1.4 配置 TLS Ingress

在第 30 篇的 multi-domain-ingress 基础上,为 counter.example.com 添加 TLS:

bash 复制代码
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: flask-tls-ingress
spec:
  ingressClassName: nginx
  tls:
    - hosts:
        - counter.example.com
      secretName: counter-tls
  rules:
    - host: counter.example.com
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: flask-service
                port:
                  number: 5000

关键字段说明:

  • spec.tls:TLS 配置块,可以为一个或多个域名配置证书

  • hosts:证书绑定的域名列表,必须与证书的 CN 或 SAN 匹配

  • secretName:存储 TLS 私钥和证书的 Secret 名称

bash 复制代码
kubectl apply -f flask-tls-ingress.yaml
kubectl get ingress flask-tls-ingress

输出:

bash 复制代码
NAME              CLASS   HOSTS                  ADDRESS        PORTS     AGE
flask-tls-ingress nginx   counter.example.com    192.168.49.2   80, 443   10s

PORTS 列显示 80, 443------Ingress 现在同时监听 HTTP 和 HTTPS。

1.5 验证 HTTPS

使用 curl 的 -k 参数跳过证书验证(自签名证书不受 curl 信任):

bash 复制代码
MINIKUBE_IP=$(minikube ip)
curl -k -H "Host: counter.example.com" https://$MINIKUBE_IP

输出:

bash 复制代码
Hello World! I have been seen 3 times.

你也可以添加 -v 参数查看 TLS 握手详情,确认加密套件、证书信息等都正确协商:

bash 复制代码
curl -k -v https://$MINIKUBE_IP -H "Host: counter.example.com" 2>&1 | grep -E "SSL|subject|issuer"
# *  subject: CN=counter.example.com
# *  issuer: CN=counter.example.com
# *  SSL certificate verify result: self-signed certificate (18), continuing anyway.

1.6 强制 HTTPS 重定向

当前 Ingress 同时接受 HTTP 和 HTTPS 请求。如果你希望所有 HTTP 流量自动跳转到 HTTPS,可以添加重定向注解:

bash 复制代码
metadata:
  annotations:
    nginx.ingress.kubernetes.io/ssl-redirect: "true"

更新后,再测试 HTTP 请求:

bash 复制代码
curl -H "Host: counter.example.com" http://$MINIKUBE_IP

你会收到 308 Permanent Redirect,Location 头指向 https://counter.example.com/。这一注解仅对 NGINX Ingress Controller 有效,其他 Ingress Controller 的配置方式不同。

二、路径重写:让 Ingress 帮你改写 URL

路径重写是七层反向代理最常见的需求之一。假设你的 Flask 应用只认识 /health/,但你想通过 /counter/health/counter/ 来访问------用路径前缀区分不同应用,同时不给应用增加 /counter 前缀的处理逻辑。Ingress 可以在转发时自动把 /counter 剪掉。

bash 复制代码
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: flask-rewrite-ingress
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /$2
spec:
  ingressClassName: nginx
  rules:
    - http:
        paths:
          - path: /counter(/|$)(.*)
            pathType: ImplementationSpecific
            backend:
              service:
                name: flask-service
                port:
                  number: 5000

这段配置的核心逻辑:

  • path: /counter(/|$)(.*) 匹配 /counter/counter//counter/health 等一切以 /counter 开头的路径

  • rewrite-target: /$2 中,$2 代表正则表达式中第二个捕获组 (.*) 匹配到的内容

  • 例如:/counter/health → 捕获组匹配到 health → 重写为 /health → 转发给 Flask

bash 复制代码
kubectl apply -f flask-rewrite-ingress.yaml
curl http://$(minikube ip)/counter/
# Hello World! I have been seen 4 times.

curl http://$(minikube ip)/counter/health
# {"status":"ok"}

Flask 收到的请求路径是 //health,而不是 /counter//counter/health------Ingress 在转发前把前缀剪掉了。

三、Basic Auth 认证:轻量级访问控制

Basic Auth 是一种最简单的 HTTP 认证方式,不适合作为生产环境的主要安全手段,但可用于保护管理后台、API 文档等内部页面。

3.1 生成 htpasswd 文件

bash 复制代码
# 安装 htpasswd 工具(如果未安装)
# macOS: brew install httpd
# Ubuntu: sudo apt-get install apache2-utils

# 创建用户 admin,生成密码文件
htpasswd -c auth admin
# 输入密码:admin123(实验用,生产环境务必使用强密码)

3.2 创建 Basic Auth Secret

bash 复制代码
kubectl create secret generic basic-auth \
  --from-file=auth
bash 复制代码
kubectl describe secret basic-auth
# Name:         basic-auth
# Type:         Opaque
# Data:
# auth:         45 bytes

3.3 配置带 Basic Auth 的 Ingress

bash 复制代码
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: flask-auth-ingress
  annotations:
    nginx.ingress.kubernetes.io/auth-type: basic
    nginx.ingress.kubernetes.io/auth-secret: basic-auth
    nginx.ingress.kubernetes.io/auth-realm: "Authentication Required - Admin Area"
spec:
  ingressClassName: nginx
  rules:
    - host: admin.example.com
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: flask-service
                port:
                  number: 5000

注解说明:

  • auth-type: basic 启用 Basic Auth

  • auth-secret: basic-auth 指定存储 htpasswd 文件的 Secret

  • auth-realm 浏览器弹窗中显示的提示文字

bash 复制代码
kubectl apply -f flask-auth-ingress.yaml

3.4 验证认证效果

不带认证信息(拒绝访问)

bash 复制代码
curl -H "Host: admin.example.com" http://$(minikube ip)
# <html>
# <head><title>401 Authorization Required</title></head>
# ...

带认证信息(通过)

bash 复制代码
curl -H "Host: admin.example.com" -u "admin:admin123" http://$(minikube ip)
# Hello World! I have been seen 5 times.

在实际应用中,你可以将 TLS 和 Basic Auth 组合使用,确保用户名密码在加密通道中传输:

bash 复制代码
spec:
  tls:
    - hosts:
        - admin.example.com
      secretName: admin-tls
  rules:
    - host: admin.example.com
      # ... Basic Auth 规则

四、Ingress 注解 vs Ingress Controller 原生能力

本篇用到了多个 NGINX Ingress Controller 特有的注解(ssl-redirectrewrite-targetauth-type)。这些注解并非 K8s Ingress API 标准的一部分,而是 NGINX Ingress Controller 的扩展。其他 Controller(如 Traefik、Kong)有自己的注解体系或 CRD 配置方式。

选择建议:对于中小规模集群,NGINX Ingress Controller 的注解已足够灵活。当你需要更细粒度的流量控制(如金丝雀发布、限流、熔断、基于请求头的路由),可以考虑使用 Ingress Controller 提供的自定义 CRD(如 NGINX 的 VirtualServer)或升级到 Service Mesh(如 Istio)。第 49 篇将进一步探讨这两者的选型边界。

五、命令速查表

六、本篇总结

  • TLS 证书:用 Secret 存储私钥和证书,Ingress 统一处理 HTTPS 握手,支持自签名证书测试和生产 CA 证书。

  • 路径重写 :通过 rewrite-target 注解,Ingress 在转发请求时自动修改 URL 路径,让后端应用无需感知路由前缀。

  • Basic Auth:轻量级 HTTP 认证,适用于保护管理页面和内部 API,通过注解引用 htpasswd Secret。

  • 注解的本质:Ingress 注解是特定 Ingress Controller 的功能扩展,不同 Controller 的注解体系不同。选择 Ingress Controller 时需考虑其功能边界是否满足需求。

通过本篇,你的 Ingress 已经具备生产级安全入口的基本能力------HTTPS 加密传输、路径灵活路由、轻量级访问控制。下一篇------第 32 篇:配置管理:ConfigMap 详解,我们将回到应用配置本身,学习如何用 ConfigMap 将配置与镜像解耦,实现配置的版本化管理和动态更新。

想了解更多还可以去各个平台搜索「IT策士」,一起升级 IT 思维 !

相关推荐
川石课堂软件测试1 小时前
作为一名测试工程师如何学习Kubernetes(k8s)技能
学习·测试工具·容器·职场和发展·kubernetes·测试用例·harmonyos
无聊的老谢2 小时前
DDD 驱动的电信网络优化微服务建模实战
微服务·云原生·架构
qq_452396232 小时前
第十一篇:《Docker Compose:多容器应用编排入门》
运维·docker·容器
Geoking.2 小时前
Docker安装Nacos指南
运维·docker·容器
日取其半万世不竭3 小时前
密码管理工具私有化部署,Vaultwarden 备份恢复怎么做?
数据库·docker·容器
赵民勇3 小时前
Rootless容器详解
linux·容器
IT策士3 小时前
第32篇 k8s 之 配置管理:ConfigMap 详解
云原生·容器·kubernetes
人道领域3 小时前
Windows 保姆级 Docker 安装教程(WSL2 版),一篇入门docker
windows·docker·容器
lbb 小魔仙3 小时前
Docker一键部署 EasyNode 面板,随时随地可视化管理服务器
服务器·docker·容器