插件窝 干货文章 为什么使用 ClusterIP + Ingress 无法从外部访问内部 MySQL,而使用 NodePort 却可以?

为什么使用 ClusterIP + Ingress 无法从外部访问内部 MySQL,而使用 NodePort 却可以?

Ingress MySQL NodePort service 105    来源:    2025-03-31

ClusterIP + Ingress 无法访问 MySQL 的原因分析

问题本质

ClusterIP + Ingress 无法访问 MySQL 而 NodePort 可以,这主要是因为 Ingress 和 NodePort 的工作机制不同导致的。

详细原因

  1. Ingress 的设计目的

    • Ingress 主要用于管理 HTTP/HTTPS 服务的访问
    • 它不适用于像 MySQL 这样的 TCP/UDP 服务(默认情况下)
  2. ClusterIP 特性

    • ClusterIP 是 Kubernetes 内部的虚拟 IP,只能在集群内部访问
    • 没有外部暴露机制,除非通过 Ingress 或 NodePort/LoadBalancer
  3. NodePort 的工作方式

    • NodePort 在每个节点上打开一个特定端口(30000-32767范围)
    • 外部流量可以直接通过 <节点IP>:<NodePort> 访问服务

解决方案

如果您需要通过 Ingress 暴露 MySQL 服务,有几种方法:

方案1:使用 TCP/UDP Ingress(如果您的 Ingress 控制器支持)

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: mysql-ingress
  annotations:
    nginx.ingress.kubernetes.io/tcp-services: "3306:default/mysql-service:3306"
spec:
  rules:
  - host: mysql.example.com

方案2:使用 Service 类型 LoadBalancer

apiVersion: v1
kind: Service
metadata:
  name: mysql-service
spec:
  type: LoadBalancer
  ports:
  - port: 3306
    targetPort: 3306
  selector:
    app: mysql

方案3:使用 NodePort(您已经验证可行)

apiVersion: v1
kind: Service
metadata:
  name: mysql-service
spec:
  type: NodePort
  ports:
  - port: 3306
    targetPort: 3306
    nodePort: 30306
  selector:
    app: mysql

最佳实践建议

  1. 生产环境:考虑使用专用数据库而不是通过 Kubernetes 暴露
  2. 安全考虑:MySQL 直接暴露在公网有安全风险,建议使用 VPN 或 SSH 隧道
  3. 性能考虑:Ingress 对 TCP 流量的处理可能不如专用负载均衡器高效

您使用的是哪种 Ingress 控制器(Nginx、Traefik、ALB 等)?这会影响具体的配置方式。