👋 大家好,欢迎来到我的技术博客!
📚 在这里,我会分享学习笔记、实战经验与技术思考,力求用简单的方式讲清楚复杂的问题。
🎯 本文将围绕Kubernetes这个话题展开,希望能为你带来一些启发或实用的参考。
🌱 无论你是刚入门的新手,还是正在进阶的开发者,希望你都能有所收获!
文章目录
- Kubernetes - Ingress 配置 HTTPS,实现安全的 HTTPS 访问 🛡️🌐
- 一、HTTPS 与 TLS:为什么我们必须使用它? 🔐
- 1.1 数据泄露的代价
- 1.2 浏览器与搜索引擎的“惩罚机制”
- 1.3 法规合规的硬性要求
- 1.4 TLS 的工作原理简述
- 1.5 证书类型与信任链
- 二、Kubernetes Ingress 基础回顾 🚦
- 2.1 Ingress 的核心结构
- 2.2 Ingress Controller 是什么?
- 2.3 Ingress 与 Service 的关系
- 三、证书管理方案选型:手动 vs 自动化 🤖
- 3.1 推荐方案:cert-manager + Let’s Encrypt
- 四、实战部署:从零搭建 HTTPS Ingress 系统 🛠️
- 4.1 环境准备
- 4.2 部署 cert-manager
- 4.3 创建 Let’s Encrypt Issuer
- 4.4 部署 Java Web 应用
- Java 代码示例:`HelloController.java`
- `pom.xml`(Maven 依赖)
- 构建 Docker 镜像
- 4.5 部署 Java 应用到 Kubernetes
- 4.6 创建 Ingress 并启用 HTTPS
- 4.7 等待证书签发
- 五、验证 HTTPS 访问:从浏览器到命令行 🧪
- 5.1 使用 curl 测试
- 5.2 浏览器验证
- 5.3 强制 HTTP 跳转测试
- 六、进阶配置:增强安全性与性能 🚀
- 6.1 启用 HSTS(HTTP Strict Transport Security)
- 6.2 启用 TLS 1.3 与强加密套件
- 6.3 启用 Gzip 压缩
- 6.4 防止点击劫持与 XSS
- 6.5 限制请求速率(防暴力破解)
- 七、监控与告警:让证书永不过期 🔔
Kubernetes - Ingress 配置 HTTPS,实现安全的 HTTPS 访问 🛡️🌐
在当今互联网环境中,安全已成为不可妥协的底线。无论是用户登录、支付交易,还是 API 调用,数据的加密传输都已成为行业标配。HTTP 协议早已无法满足现代应用对隐私与完整性的要求,HTTPS 凭借 TLS/SSL 加密机制,成为构建可信网络服务的基石。在 Kubernetes 集群中,Ingress 作为流量入口的核心组件,承担着将外部请求路由至内部服务的重任。如何在 Ingress 上正确配置 HTTPS,实现端到端的安全访问,是每一位云原生工程师必须掌握的技能。
本文将带你从零开始,系统性地构建一个基于 Kubernetes Ingress 的 HTTPS 安全访问体系。我们将深入理解 TLS 证书的原理、ACME 协议的自动化流程、Ingress Controller 的工作模式,并结合真实 Java 应用示例,演示如何部署一个完整的、支持 HTTPS 的微服务系统。你将学会如何使用 Let’s Encrypt 自动签发证书、如何配置 Nginx Ingress 实现双向认证、如何处理证书轮换、如何调试常见错误,以及如何通过监控与日志保障服务的长期稳定运行。
无论你是刚接触 Kubernetes 的新手,还是希望深化安全架构的资深工程师,本文都将为你提供可落地、可复用的实践指南。让我们一起,把安全从口号变成代码,从理论变成生产环境中的坚实盾牌。🔐
一、HTTPS 与 TLS:为什么我们必须使用它? 🔐
在讨论如何配置之前,我们先明确一个核心问题:为什么 HTTPS 不是“可选项”,而是“必选项”?
1.1 数据泄露的代价
想象一下,你的用户在未加密的 HTTP 网站上输入了邮箱和密码。攻击者只需在同一个 Wi-Fi 网络中监听流量,就能轻松截获明文凭证。根据 IBM 2023 年《数据泄露成本报告》,单次数据泄露的平均成本已高达445 万美元。而其中,38% 的泄露事件起源于未加密的通信通道。
🔗 https://www.ibm.com/reports/data-breach —— IBM 数据泄露成本报告(权威数据来源)
1.2 浏览器与搜索引擎的“惩罚机制”
现代浏览器(Chrome、Firefox、Safari)对非 HTTPS 网站会显示“不安全”红色警告,直接劝退用户。Google 更是在其搜索算法中将 HTTPS 作为排名因子,非加密网站将被降权。你可能不在乎排名,但你的用户会在意是否被浏览器“拉黑”。
1.3 法规合规的硬性要求
GDPR(欧盟通用数据保护条例)、CCPA(加州消费者隐私法案)、等保 2.0、《个人信息保护法》等国内外法规,均明确要求对用户敏感信息传输进行加密。不使用 HTTPS,意味着你可能面临巨额罚款甚至业务关停。
1.4 TLS 的工作原理简述
HTTPS 并非独立协议,而是 HTTP over TLS(Transport Layer Security)。TLS 的核心流程如下:
- 客户端发起连接(Client Hello):携带支持的加密套件、随机数。
- 服务端响应(Server Hello):选择加密套件,发送证书(含公钥)。
- 证书验证:客户端使用信任的 CA(证书颁发机构)验证证书签名。
- 密钥交换:客户端生成预主密钥,用服务端公钥加密后发送。
- 会话密钥生成:双方使用预主密钥 + 随机数生成对称密钥。
- 加密通信:后续所有数据使用对称密钥加密传输。
✅ 重点:对称加密用于数据传输(高效),非对称加密用于密钥交换(安全)。
1.5 证书类型与信任链
| 类型 | 说明 | 适用场景 |
|---|---|---|
| DV(域名验证) | 仅验证域名所有权 | 个人博客、测试环境 |
| OV(组织验证) | 验证企业身份 | 企业官网、B2B 服务 |
| EV(扩展验证) | 最严格审核,地址栏显示公司名 | 银行、电商 |
| 自签名证书 | 无第三方 CA 签名 | 仅限内网测试 |
在 Kubernetes 中,我们主要使用DV 证书,并通过Let’s Encrypt(免费、自动化)自动签发。
🔗 https://letsencrypt.org/ —— Let’s Encrypt 官网(全球最大的免费证书颁发机构)
二、Kubernetes Ingress 基础回顾 🚦
Ingress 是 Kubernetes 中用于管理外部访问集群服务的 API 对象。它通常与 Ingress Controller 配合使用,后者是一个实际处理 HTTP/HTTPS 请求的反向代理(如 Nginx、Traefik、HAProxy)。
2.1 Ingress 的核心结构
apiVersion:networking.k8s.io/v1kind:Ingressmetadata:name:my-app-ingressnamespace:defaultannotations:kubernetes.io/ingress.class:"nginx"cert-manager.io/cluster-issuer:"letsencrypt-prod"spec:tls:-hosts:-example.comsecretName:tls-secretrules:-host:example.comhttp:paths:-path:/pathType:Prefixbackend:service:name:my-java-appport:number:8080tls:定义 HTTPS 证书绑定的域名和 Secret 名称。rules:定义域名与后端服务的映射。annotations:配置 Ingress Controller 的行为,如使用哪个 issuer、是否启用压缩等。
2.2 Ingress Controller 是什么?
Ingress Controller 并非 Kubernetes 内置组件,而是由社区或厂商提供的独立部署应用。最流行的是:
- NGINX Ingress Controller:高性能、配置灵活,适合生产环境。
- Traefik:自动发现服务,适合动态微服务架构。
- HAProxy:高可用、负载均衡能力强。
- Contour:基于 Envoy,支持 gRPC、WebSocket。
我们以NGINX Ingress Controller为例,因其生态成熟、文档丰富、社区支持广泛。
🔗 https://kubernetes.github.io/ingress-nginx/ —— Nginx Ingress 官方文档
2.3 Ingress 与 Service 的关系
外部用户 → Ingress Controller(监听 443) → Ingress 规则 → Service(ClusterIP) → Pod(Java 应用)Java 应用本身无需关心 HTTPS,它只需监听 HTTP(如 8080),由 Ingress Controller 负责 TLS 终止(TLS Termination),然后以 HTTP 明文转发给后端服务。这种方式称为SSL Offloading,是主流架构。
⚠️ 注意:若需端到端加密(客户端 → Ingress → Pod 全程 HTTPS),需在 Pod 内启用 HTTPS,但会增加证书管理复杂度,一般不推荐。
三、证书管理方案选型:手动 vs 自动化 🤖
在 Kubernetes 中,证书管理有三种主流方式:
| 方式 | 描述 | 优点 | 缺点 |
|---|---|---|---|
| 手动上传 Secret | 本地生成证书,kubectl create secret tls | 简单可控 | 证书过期需人工轮换,易遗忘 |
| cert-manager + Let’s Encrypt | 自动申请、续期、更新证书 | 完全自动化,免费,安全 | 需配置 Issuer、DNS 验证 |
| 自建 CA + 签发 | 使用私有 PKI 系统签发 | 适用于内网、合规要求高 | 成本高,运维复杂 |
3.1 推荐方案:cert-manager + Let’s Encrypt
cert-manager是 Kubernetes 原生的证书管理控制器,它能自动监听 Ingress 资源中的注解,向 Let’s Encrypt 申请证书,并自动更新到 Secret 中。
✅ 优势:
- 证书有效期 90 天,自动续期
- 支持 DNS-01 和 HTTP-01 验证
- 与 Ingress 深度集成
- 支持多 Issuer(Prod / Staging)
我们将在下一节完整部署这套体系。
四、实战部署:从零搭建 HTTPS Ingress 系统 🛠️
现在,我们进入实战环节。我们将完成以下步骤:
- 部署 cert-manager
- 创建 Let’s Encrypt 生产环境 Issuer
- 部署一个 Java Web 应用
- 创建 Ingress 并启用 HTTPS
- 验证并测试访问
4.1 环境准备
假设你已拥有一个可用的 Kubernetes 集群(Minikube、EKS、GKE、Rancher 等均可),并已配置kubectl连接。
💡 建议:使用公网可访问的域名(如
your-app.example.com),并已将 A 记录解析到集群的 Ingress Controller 公网 IP。
4.2 部署 cert-manager
# 添加 Jetstack Helm 仓库helm repoaddjetstack https://charts.jetstack.io helm repo update# 安装 cert-managerhelminstallcert-manager jetstack/cert-manager\--namespacecert-manager\--create-namespace\--setinstallCRDs=true等待所有 Pod 运行:
kubectl get pods-ncert-manager输出应类似:
NAME READY STATUS RESTARTS AGE cert-manager-5b7b8c8d8f-7x9q2 1/1 Running 0 2m cert-manager-cainjector-7d6b9d5c5d-9z2kx 1/1 Running 0 2m cert-manager-webhook-6d9b8c8b8f-4w9lq 1/1 Running 0 2m4.3 创建 Let’s Encrypt Issuer
创建prod-issuer.yaml:
apiVersion:cert-manager.io/v1kind:ClusterIssuermetadata:name:letsencrypt-prodspec:acme:# Let's Encrypt 生产环境 URL(非测试)server:https://acme-v02.api.letsencrypt.org/directoryemail:admin@example.comprivateKeySecretRef:name:letsencrypt-prod-private-keysolvers:-http01:ingress:class:nginx应用配置:
kubectl apply-fprod-issuer.yaml验证 Issuer 状态:
kubectl describe clusterissuer letsencrypt-prod若看到Status: Ready,说明配置成功。
📌 注意:
http01验证要求 Ingress Controller 能被公网访问。若你处于内网或防火墙后,需改用dns01(需配置 DNS 提供商 API)。
4.4 部署 Java Web 应用
我们创建一个简单的 Spring Boot 应用作为后端服务。
Java 代码示例:HelloController.java
packagecom.example.demo;importorg.springframework.web.bind.annotation.GetMapping;importorg.springframework.web.bind.annotation.RestController;importjava.time.LocalDateTime;importjava.time.format.DateTimeFormatter;@RestControllerpublicclassHelloController{@GetMapping("/api/hello")publicStringhello(){Stringtimestamp=LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));returnString.format("{\"message\": \"Hello from Kubernetes!\", \"timestamp\": \"%s\", \"env\": \"production\"}",timestamp);}@GetMapping("/health")publicStringhealth(){return"OK";}}pom.xml(Maven 依赖)
<?xml version="1.0" encoding="UTF-8"?><projectxmlns="http://maven.apache.org/POM/XML/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.example</groupId><artifactId>k8s-https-demo</artifactId><version>1.0.0</version><packaging>jar</packaging><name>k8s-https-demo</name><description>Demo Spring Boot app for Kubernetes HTTPS</description><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>3.2.0</version><relativePath/></parent><properties><java.version>17</java.version></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build></project>构建 Docker 镜像
# Dockerfile FROM eclipse-temurin:17-jre-slim WORKDIR /app COPY target/k8s-https-demo-1.0.0.jar app.jar EXPOSE 8080 ENTRYPOINT ["java", "-jar", "app.jar"]构建并推送:
dockerbuild-tyour-registry.com/k8s-https-demo:latest.dockerpush your-registry.com/k8s-https-demo:latest💡 若你使用的是公共镜像仓库(如 Docker Hub),请替换
your-registry.com为实际地址。
4.5 部署 Java 应用到 Kubernetes
创建java-app-deployment.yaml:
apiVersion:apps/v1kind:Deploymentmetadata:name:java-applabels:app:java-appspec:replicas:2selector:matchLabels:app:java-apptemplate:metadata:labels:app:java-appspec:containers:-name:java-appimage:your-registry.com/k8s-https-demo:latestports:-containerPort:8080resources:requests:memory:"128Mi"cpu:"250m"limits:memory:"256Mi"cpu:"500m"livenessProbe:httpGet:path:/healthport:8080initialDelaySeconds:30periodSeconds:10readinessProbe:httpGet:path:/healthport:8080initialDelaySeconds:5periodSeconds:5---apiVersion:v1kind:Servicemetadata:name:java-app-servicespec:selector:app:java-appports:-protocol:TCPport:80targetPort:8080type:ClusterIP部署:
kubectl apply-fjava-app-deployment.yaml验证 Pod 状态:
kubectl get pods-lapp=java-app4.6 创建 Ingress 并启用 HTTPS
创建ingress-https.yaml:
apiVersion:networking.k8s.io/v1kind:Ingressmetadata:name:java-app-ingressannotations:kubernetes.io/ingress.class:"nginx"cert-manager.io/cluster-issuer:"letsencrypt-prod"nginx.ingress.kubernetes.io/ssl-redirect:"true"nginx.ingress.kubernetes.io/backend-protocol:"HTTP"spec:tls:-hosts:-your-domain.com# 替换为你的域名secretName:tls-secretrules:-host:your-domain.comhttp:paths:-path:/pathType:Prefixbackend:service:name:java-app-serviceport:number:80✅ 关键注解说明:
cert-manager.io/cluster-issuer:告诉 cert-manager 使用哪个 Issuer 签发证书nginx.ingress.kubernetes.io/ssl-redirect: "true":强制 HTTP 重定向到 HTTPSnginx.ingress.kubernetes.io/backend-protocol: "HTTP":告知 Nginx 后端是 HTTP(非 HTTPS)
应用配置:
kubectl apply-fingress-https.yaml4.7 等待证书签发
证书申请是异步过程。查看证书状态:
kubectl get certificate-A输出示例:
NAMESPACE NAME READY SECRET AGE default tls-secret True tls-secret 8m若READY为False,查看详细信息:
kubectl describe certificate tls-secret常见错误:
DNS record not found:域名未正确解析到 Ingress IPFailed to authorize:防火墙阻止了 HTTP-01 验证请求Too many certificates already issued:Let’s Encrypt 有频率限制(每域名 50 次/周)
✅ 解决方案:使用
letsencrypt-staging先测试,成功后再切换到生产环境。
创建staging-issuer.yaml用于测试:
apiVersion:cert-manager.io/v1kind:ClusterIssuermetadata:name:letsencrypt-stagingspec:acme:server:https://acme-staging-v02.api.letsencrypt.org/directoryemail:admin@example.comprivateKeySecretRef:name:letsencrypt-staging-private-keysolvers:-http01:ingress:class:nginx修改 Ingress 注解为:
cert-manager.io/cluster-issuer:"letsencrypt-staging"测试通过后,再切回生产环境。
五、验证 HTTPS 访问:从浏览器到命令行 🧪
当tls-secret状态变为True,证书已成功创建。我们来验证整个链路是否畅通。
5.1 使用 curl 测试
curl-vhttps://your-domain.com/api/hello预期输出:
* TLS 1.3 connected * Server certificate: * subject: CN=your-domain.com * start date: Apr 10 12:00:00 2024 GMT * expire date: Jul 9 12:00:00 2024 GMT * issuer: C=US, O=Let's Encrypt, CN=R3 * SSL certificate verify ok. > GET /api/hello HTTP/2 > Host: your-domain.com > ... < HTTP/2 200 < content-type: application/json < {"message": "Hello from Kubernetes!", "timestamp": "2024-04-10 15:30:22", "env": "production"}✅ 成功!说明:
- HTTPS 连接建立
- 证书有效
- Ingress 路由正确
- Java 应用返回数据
5.2 浏览器验证
在浏览器中访问https://your-domain.com/api/hello
你会看到:
- 地址栏显示 🔒 小锁图标
- 点击锁 → 证书信息 → 由 Let’s Encrypt R3 签发
- 无任何“不安全”警告
5.3 强制 HTTP 跳转测试
访问http://your-domain.com/api/hello
预期:自动跳转到https://...,状态码 308。
curl-Ihttp://your-domain.com/api/hello输出:
HTTP/1.1 308 Permanent Redirect Location: https://your-domain.com/api/hello说明ssl-redirect: "true"生效。
六、进阶配置:增强安全性与性能 🚀
6.1 启用 HSTS(HTTP Strict Transport Security)
HSTS 强制浏览器在未来一段时间内只使用 HTTPS 访问,防止 SSL Stripping 攻击。
添加注解:
annotations:nginx.ingress.kubernetes.io/hsts:"true"nginx.ingress.kubernetes.io/hsts-max-age:"31536000"# 1年nginx.ingress.kubernetes.io/hsts-include-subdomains:"true"nginx.ingress.kubernetes.io/hsts-preload:"true"✅ 作用:浏览器访问一次 HTTPS 后,未来 1 年内即使输入
http://也会自动转为 HTTPS。
6.2 启用 TLS 1.3 与强加密套件
Nginx Ingress 默认使用较旧的加密套件。我们通过configmap强化安全:
创建nginx-config.yaml:
apiVersion:v1kind:ConfigMapmetadata:name:nginx-configurationnamespace:ingress-nginxdata:ssl-protocols:"TLSv1.2 TLSv1.3"ssl-ciphers:"ECDHE-RSA-AES256-GCM-SHA512:DHE-RSA-AES256-GCM-SHA512:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-SHA384"ssl-prefer-server-ciphers:"true"hsts:"true"hsts-max-age:"31536000"应用:
kubectl apply-fnginx-config.yaml🔗 https://ssl-config.mozilla.org/ —— Mozilla SSL 配置生成器(推荐使用 Intermediate 配置)
6.3 启用 Gzip 压缩
减少带宽,提升响应速度:
annotations:nginx.ingress.kubernetes.io/use-gzip:"true"6.4 防止点击劫持与 XSS
annotations:nginx.ingress.kubernetes.io/security-headers:|X-Frame-Options: DENY X-Content-Type-Options: nosniff X-XSS-Protection: "1; mode=block" Referrer-Policy: strict-origin-when-cross-origin6.5 限制请求速率(防暴力破解)
annotations:nginx.ingress.kubernetes.io/limit-rps:"10"nginx.ingress.kubernetes.io/limit-connections:"5"七、监控与告警:让证书永不过期 🔔
证书过期是导致服务中断的“隐形杀手”。据统计,超过 15% 的网站因证书过期而宕机。
🙌 感谢你读到这里!
🔍 技术之路没有捷径,但每一次阅读、思考和实践,都在悄悄拉近你与目标的距离。
💡 如果本文对你有帮助,不妨 👍点赞、📌收藏、📤分享给更多需要的朋友!
💬 欢迎在评论区留下你的想法、疑问或建议,我会一一回复,我们一起交流、共同成长 🌿
🔔 关注我,不错过下一篇干货!我们下期再见!✨