Kubernetes服务自动化HTTPS:Ingress与Cert-Manager实战
最近有个新服务要上线,作为后端开发,我知道HTTPS是现在标配,但一想到要在Kubernetes里搞TLS证书、配置Ingress,还不能老是手动更新证书,就感觉一团乱麻。相信不少后端同学也有类似困惑。别担心,今天就手把手教你如何利用 Ingress 和 Cert-Manager,搭配 Let's Encrypt,实现Kubernetes服务自动化HTTPS,从此告别证书焦虑!
1. 理清思路:我们需要什么?
我们最终目标是:
- 服务上线:一个运行在Kubernetes里的后端服务。
- HTTPS访问:外部用户通过
https://your-domain.com访问到我们的服务。 - 证书自动化:TLS证书能够自动申请、自动续期,不用我们操心。
为了实现这些,Kubernetes生态中有几个关键角色:
- Deployment & Service:部署你的后端应用并对外暴露(通常是ClusterIP类型)。
- Ingress Controller:集群内部的流量入口,通常是Nginx Ingress Controller或Traefik等,负责将外部请求路由到正确的Service。
- Ingress:Kubernetes资源对象,定义了外部流量如何路由到集群内部的服务,以及TLS配置。
- Cert-Manager:一个Kubernetes附加组件,用于自动化地管理和签发TLS证书,支持Let's Encrypt等多种CA。
- Let's Encrypt:一个免费、开放、自动化的证书颁发机构。
2. 前置准备
在开始之前,请确保你的Kubernetes集群已经满足以下条件:
- Ingress Controller已安装:例如Nginx Ingress Controller。如果没装,可以参考官方文档安装。
- 有一个可用的域名:并解析到你的Ingress Controller的外部IP或负载均衡器上。
3. 安装 Cert-Manager
Cert-Manager是自动化证书管理的核心。我们通过Helm来安装它,这是最推荐的方式:
# 1. 添加Cert-Manager Helm仓库
helm repo add jetstack https://charts.jetstack.io
helm repo update
# 2. 安装Cert-Manager
# 建议安装最新稳定版本,这里以v1.13.0为例,请根据实际情况调整
kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.13.0/cert-manager.crds.yaml
helm install cert-manager jetstack/cert-manager \
--namespace cert-manager \
--create-namespace \
--version v1.13.0 \
--set installCRDs=true # 如果已经手动安装CRDs,这里可以省略或设置为false
安装完成后,检查cert-manager命名空间下的所有Pod是否都已Running。
4. 配置 Issuer 或 ClusterIssuer
Issuer 或 ClusterIssuer 是Cert-Manager用来与证书颁发机构(如Let's Encrypt)交互的资源。
Issuer:只能在其所在的命名空间中颁发证书。ClusterIssuer:可以为集群中任何命名空间颁发证书,更常用,因为它提供更广的适用性。
这里我们配置一个ClusterIssuer,使用Let's Encrypt的staging环境(用于测试,避免达到生产环境的速率限制)和production环境。
4.1 Let's Encrypt Staging ClusterIssuer (测试环境)
创建一个letencrypt-staging-clusterissuer.yaml文件:
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: letsencrypt-staging
spec:
acme:
email: your-email@example.com # 替换为你的邮箱,用于接收证书通知
server: https://acme-staging-v02.api.letsencrypt.org/directory # Let's Encrypt测试环境
privateKeySecretRef:
name: letsencrypt-staging-private-key # 用于存储ACME账户私钥
solvers:
- http01: # 使用HTTP-01挑战,需要Ingress Controller支持
ingress:
class: nginx # 如果你使用其他Ingress Controller,请替换为对应的class
应用配置:
kubectl apply -f letencrypt-staging-clusterissuer.yaml
4.2 Let's Encrypt Production ClusterIssuer (生产环境)
测试成功后,我们将使用生产环境。创建一个letencrypt-production-clusterissuer.yaml文件:
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: letsencrypt-prod
spec:
acme:
email: your-email@example.com # 替换为你的邮箱
server: https://acme-v02.api.letsencrypt.org/directory # Let's Encrypt生产环境
privateKeySecretRef:
name: letsencrypt-prod-private-key
solvers:
- http01:
ingress:
class: nginx
应用配置:
kubectl apply -f letencrypt-production-clusterissuer.yaml
注意:your-email@example.com非常重要,Let's Encrypt会通过此邮箱发送证书到期通知。
5. 部署你的服务和Ingress
假设你已经有了一个后端服务,例如一个名为my-backend-service的Service,暴露在端口80。现在我们来创建Deployment和Service(如果还没有),然后配置Ingress。
5.1 示例应用 Deployment & Service (如果已有可跳过)
创建一个my-app.yaml文件:
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-backend
labels:
app: my-backend
spec:
replicas: 1
selector:
matchLabels:
app: my-backend
template:
metadata:
labels:
app: my-backend
spec:
containers:
- name: my-backend
image: nginx:latest # 替换为你的后端服务镜像
ports:
- containerPort: 80 # 你的服务监听端口
---
apiVersion: v1
kind: Service
metadata:
name: my-backend-service
spec:
selector:
app: my-backend
ports:
- protocol: TCP
port: 80 # Service暴露的端口
targetPort: 80 # Pod监听的端口
type: ClusterIP
应用配置:
kubectl apply -f my-app.yaml
5.2 配置 Ingress 启用 HTTPS
现在是最关键的一步!我们将创建一个Ingress资源,它会告诉Ingress Controller如何路由流量,同时通过cert-manager.io/cluster-issuer注解,让Cert-Manager自动为我们申请和管理TLS证书。
创建一个my-ingress.yaml文件:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: my-backend-ingress
annotations:
kubernetes.io/ingress.class: nginx # 指定你的Ingress Controller类型
cert-manager.io/cluster-issuer: letsencrypt-staging # 或者 letsencrypt-prod
nginx.ingress.kubernetes.io/rewrite-target: /$1 # 如果你的后端路径需要重写
spec:
tls:
- hosts:
- your-domain.com # 替换为你的域名
secretName: my-backend-tls-secret # Cert-Manager会将证书存储到这个Secret中
rules:
- host: your-domain.com # 替换为你的域名
http:
paths:
- path: / # 匹配所有路径,可以根据需要调整
pathType: Prefix
backend:
service:
name: my-backend-service # 你的Service名称
port:
number: 80 # 你的Service端口
注意:
- 一开始建议使用
letsencrypt-staging进行测试,避免生产环境速率限制。 - 确认
your-domain.com已经指向你的Ingress Controller的外部IP。 secretName是Cert-Manager存放证书的Kubernetes Secret的名字,无需提前创建。
应用配置:
kubectl apply -f my-ingress.yaml
6. 验证证书状态
部署Ingress后,Cert-Manager会开始工作:
- 它会看到Ingress上的
cert-manager.io/cluster-issuer注解。 - 创建一个
Certificate资源(你也可以手动创建)。 - 创建一个
Order和Challenge来完成Let's Encrypt的验证。 - 当挑战成功后,Let's Encrypt签发证书。
- Cert-Manager获取证书并将其存储到一个名为
my-backend-tls-secret的Secret中。 - Ingress Controller会自动加载这个Secret中的证书。
你可以通过以下命令查看Certificate的状态:
kubectl get certificate
kubectl describe certificate my-backend-tls-secret # 替换为你的secretName
当Status中的Ready显示为True时,说明证书已经成功签发并可用。
7. 测试你的服务
现在,打开浏览器,访问 https://your-domain.com (替换为你的域名)。你应该能看到你的服务通过HTTPS安全地运行了!浏览器会显示安全连接,证书信息也会显示由Let's Encrypt签发。
8. 切换到生产环境
如果你在测试环境(staging)成功获取了证书,并且访问正常,现在可以将Ingress中的cert-manager.io/cluster-issuer注解改为letsencrypt-prod,然后重新kubectl apply -f my-ingress.yaml。Cert-Manager会为你自动申请生产环境的证书。
9. 自动化续期
Cert-Manager会自动监控证书的有效期。在证书临近过期时(通常是30天内),它会自动触发续期流程,确保你的HTTPS连接始终有效,无需任何手动干预。
总结
通过 Ingress、Cert-Manager 和 Let's Encrypt 的组合,我们实现了Kubernetes服务对外提供HTTPS访问,并且证书的申请、续期全部自动化,极大减轻了开发和运维的负担。现在,你可以专注于业务逻辑,而不用再为证书问题而烦恼了!