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-redirect、rewrite-target、auth-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 思维 !