从Service到Ingress:Kubernetes Web服务公网暴露实战指南
当你成功在Kubernetes集群内部署了Web应用后,如何安全、高效地将其暴露给公网用户访问?这不仅是技术实现的挑战,更是生产环境部署的关键环节。本文将带你从ClusterIP Service出发,逐步打通NodePort、Ingress Controller直至HTTPS证书配置的完整链路,解决"服务跑起来了,但外部无法访问"这一典型痛点。
1. 理解Kubernetes网络暴露层级
在Kubernetes中,服务暴露存在明确的层级递进关系:
- ClusterIP Service:默认服务类型,提供集群内部通信
- NodePort Service:通过节点端口暴露服务到集群外部
- LoadBalancer Service:云厂商提供的负载均衡器集成
- Ingress:七层流量管理,支持基于域名的路由
关键区别:前三种属于四层(TCP/UDP)负载均衡,而Ingress实现了七层(HTTP/HTTPS)应用层路由。
典型场景选择矩阵:
| 暴露方式 | 适用场景 | 限制条件 |
|---|---|---|
| ClusterIP | 集群内部服务调用 | 仅限集群内访问 |
| NodePort | 开发测试环境快速暴露 | 端口范围受限(30000-32767) |
| LoadBalancer | 云环境生产部署 | 依赖云厂商实现 |
| Ingress | 生产环境多服务域名管理 | 需要额外部署Controller |
2. 基础服务暴露:从ClusterIP到NodePort
2.1 创建ClusterIP Service
首先为Deployment创建基本的ClusterIP服务:
apiVersion: v1 kind: Service metadata: name: web-service spec: selector: app: web-app ports: - protocol: TCP port: 80 targetPort: 8080注意:确保selector与Deployment中定义的标签匹配
2.2 升级为NodePort Service
修改Service类型实现节点端口映射:
apiVersion: v1 kind: Service metadata: name: web-nodeport spec: type: NodePort selector: app: web-app ports: - protocol: TCP port: 80 targetPort: 8080 nodePort: 31000验证节点端口可访问性:
curl http://<任一节点IP>:31000NodePort的局限性:
- 端口冲突风险(30000-32767范围)
- 缺乏七层路由能力
- 直接暴露节点存在安全隐患
3. 进阶方案:Ingress Controller部署
3.1 安装Nginx Ingress Controller
使用Helm快速部署:
helm upgrade --install ingress-nginx ingress-nginx \ --repo https://kubernetes.github.io/ingress-nginx \ --namespace ingress-nginx --create-namespace验证控制器状态:
kubectl get pods -n ingress-nginx3.2 配置基础Ingress规则
创建域名路由规则:
apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: web-ingress spec: ingressClassName: nginx rules: - host: "app.example.com" http: paths: - pathType: Prefix path: "/" backend: service: name: web-service port: number: 80关键字段说明:
ingressClassName:指定使用的Ingress控制器host:配置的访问域名path:URL路径匹配规则
4. 安全加固:HTTPS证书自动化
4.1 安装cert-manager
证书管理工具部署:
helm install cert-manager jetstack/cert-manager \ --namespace cert-manager \ --create-namespace \ --version v1.8.0 \ --set installCRDs=true4.2 配置Let's Encrypt签发
创建ClusterIssuer资源:
apiVersion: cert-manager.io/v1 kind: ClusterIssuer metadata: name: letsencrypt-prod spec: acme: server: https://acme-v02.api.letsencrypt.org/directory email: admin@example.com privateKeySecretRef: name: letsencrypt-prod solvers: - http01: ingress: class: nginx4.3 启用Ingress HTTPS
更新Ingress配置自动获取证书:
apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: web-ingress annotations: cert-manager.io/cluster-issuer: "letsencrypt-prod" spec: ingressClassName: nginx tls: - hosts: - app.example.com secretName: web-tls rules: - host: "app.example.com" http: paths: - pathType: Prefix path: "/" backend: service: name: web-service port: number: 80验证证书状态:
kubectl get certificate5. 生产环境优化实践
5.1 性能调优参数
Nginx Ingress关键配置示例:
controller: config: keep-alive: "75" keep-alive-requests: "100" upstream-keepalive-connections: "1000" worker-processes: "4"5.2 监控与告警
Prometheus监控指标示例:
apiVersion: monitoring.coreos.com/v1 kind: ServiceMonitor metadata: name: nginx-ingress-monitor labels: release: prometheus spec: selector: matchLabels: app.kubernetes.io/name: ingress-nginx endpoints: - port: metrics interval: 15s5.3 多租户隔离方案
通过Annotations实现路径隔离:
metadata: annotations: nginx.ingress.kubernetes.io/configuration-snippet: | if ($request_uri ~* "/admin/") { set $namespace "restricted"; } nginx.ingress.kubernetes.io/server-snippet: | location ~* "^/admin/" { auth_basic "Restricted Area"; auth_basic_user_file /etc/nginx/auth/.htpasswd; }6. 常见问题排查指南
证书签发失败:
- 检查ACME挑战记录
kubectl describe challenge <challenge-name> - 验证DNS解析是否正确
- 确认防火墙未拦截HTTP-01验证请求
Ingress路由不生效:
- 检查Ingress控制器日志
kubectl logs -n ingress-nginx <controller-pod> - 验证后端服务健康状态
kubectl get endpoints <service-name>
HTTPS重定向循环: 在Ingress中添加修正配置:
annotations: nginx.ingress.kubernetes.io/force-ssl-redirect: "true" nginx.ingress.kubernetes.io/ssl-redirect: "true"经过多个生产环境实践验证,这套方案在保持安全性的同时提供了良好的扩展性。特别是在证书自动续期方面,cert-manager的引入让HTTPS维护成本大幅降低。对于需要灰度发布的场景,可以通过Ingress的Canary注解实现流量切分,这在实际业务迭代中表现出色。