返回

EKS集群应用连MySQL失败?网络排错全指南

mysql

EKS集群中应用与MySQL通信问题

应用程序在Docker容器中运行正常,但部署到EKS集群后,构建工件时遇到 "Communications link failure" 错误。错误信息指示无法与MySQL数据库建立连接,这表明EKS环境下的网络配置可能存在问题。问题表现为应用无法与数据库建立TCP连接,具体原因通常包括网络策略限制、DNS解析问题以及MySQL服务本身的问题。

问题诊断

分析错误信息可以确定连接失败的根本原因在于应用程序尝试连接数据库时,连接被拒绝了。网络问题是第一层需要排查的,它会阻断应用访问数据库服务的能力。容器化应用程序和传统的直接部署在物理服务器上的应用之间的差异在于,在 Kubernetes (EKS) 集群环境中网络可能需要更复杂的配置。

首先要确定应用程序的网络连通性。比如,要确保应用pod的访问网络配置是正确的。通常在kubernetes里网络相关的概念有以下几种需要考虑的因素。

  1. Kubernetes 服务(Service): 检查MySQL 服务(Service)是否正确配置并且运行,Kubernetes Service 负责暴露pod应用,是流量进入pod的入口。
  2. 网络策略(Network Policies): 如果集群启用了网络策略,需检查这些策略是否阻止了应用程序访问MySQL Pod。网络策略默认允许全部出口,但也可能会有更加细粒度的入口策略影响服务间的通信。
  3. DNS解析: 应用程序是通过 DNS 名称来访问数据库服务的。确保应用能正确解析到 Service 的 cluster IP,如果 DNS 解析存在问题则可能导致连接失败。
  4. 防火墙或安全组: EKS节点上的安全组可能会阻止从应用程序到数据库的网络连接。要特别注意相关的端口开放策略。
  5. MySQL配置: 排查是否MySQL监听的地址和端口正确配置,以确保它接收来自应用程序的网络连接。

解决方案

1. 验证MySQL Service

确认MySQL Service 是否正确创建,并已经启动运行。使用kubectl get svc 命令查看 Service 的配置以及集群 IP,确保服务类型是 ClusterIPNodePort 等,确保 pod 是运行着的。

kubectl get svc -n <namespace> # 查看命名空间中的服务
kubectl get pods -n <namespace>  # 查看pods是否正常运行
kubectl describe svc mysql-service -n <namespace> #  替换 `mysql-service`为您的实际MySQL service名称

命令输出中 Cluster IP 将是你的应用程序要使用的数据库地址。检查 pod 和 service 是否属于同一个namespace。

原理: 通过 kubectl 命令检查 Service 配置和 Pod 状态,确保 Kubernetes 能够将请求正确路由到数据库实例。如果service没有运行或者绑定错误的端口和pod,应用肯定会无法正常访问mysql数据库的。

2. 检查网络策略

如果EKS 集群使用了 Kubernetes 网络策略,你需要检查是否有策略阻止了应用 pod 访问数据库 pod。 查看namespace 策略是否存在隔离,需要加入 namespace label 选择器进行解除限制,默认情况会开启所有网络访问权限。

kubectl get networkpolicies -n <namespace>

如果没有指定策略,说明此 namespace 下的策略均为允许。如有策略限制需要检查具体策略配置是否允许应用程序访问MySQL服务。

# 例子:允许指定label的Pod访问特定端口
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-mysql-access
  namespace: <your-namespace> # 你应用的命名空间
spec:
  podSelector:
    matchLabels:
      app: your-app  # 将 your-app替换为你的应用Pod 的标签
  policyTypes:
    - Ingress
  ingress:
    - from:
        - podSelector:
           matchLabels:
              app: your-app # 将 your-app替换为你的应用Pod 的标签
      ports:
      - protocol: TCP
        port: 3306  # 默认 MySQL 端口

将以上YAML配置保存到名为allow-mysql.yaml的文件中,并运行命令:

kubectl apply -f allow-mysql.yaml -n <your-namespace>

原理: 网络策略可以配置网络级别的隔离策略,控制 pod 之间的通信。网络策略配置需要合理配置选择器以控制 pod 之间的访问。
默认kubernetes 集群内部的所有pod都能相互通信,没有做任何策略配置限制,如果策略错误则可能会导致拒绝连接的情况。

3. 确认DNS 解析

确保应用程序能够正确解析 MySQL Service 的名称。Kubernetes 会自动创建 DNS 解析服务,你需要确保 coredns 组件运行正常。尝试在应用 pod 内部使用 nslookup 或者 dig 命令, 检查数据库 Service 名称对应的cluster IP 地址是否可以正常解析。

kubectl exec -it <your-app-pod> -n <namespace> -- nslookup mysql-service.namespace  #替换 <your-app-pod>和`mysql-service.namespace`为您的实际名称和namespace
# 或使用 dig 命令:
kubectl exec -it <your-app-pod> -n <namespace> -- dig mysql-service.namespace  #替换 <your-app-pod>和`mysql-service.namespace`为您的实际名称和namespace

上述命令中 <your-app-pod>是应用程序Pod的名称,<namespace>是应用程序的命名空间, mysql-service.namespace 是 mysql 的 service 的名字加 namespace。如果解析失败则会输出 error 或者 timeout。

原理: kubernetes 使用内部 dns 来解析service名字为集群ip,通过dns服务将应用连接到正确的后端服务实例。
应用pod内部执行解析能直观确定应用pod到mysql serivice的访问能力。

4. 检查 EKS 节点的安全组

如果使用的AWS云环境,需要确认eks节点使用的安全组已经开放MySQL的端口 3306 (或其他使用的端口) ,确保端口能从应用程序所在的安全组流入到 mysql 节点所在的安全组。可以在安全组策略入方向开放端口到所有源 0.0.0.0/0 或者设置只允许同一个vpc中的子网的访问,提高网络安全性。

原理: 安全组如同一个网络防火墙,不合理的端口访问会直接导致服务之间网络不通,拒绝连接。云环境的安全组限制需要注意配置,否则很容易阻断服务之间的通信。

5. MySQL配置检查

确保 MySQL 服务器配置允许来自集群内部的连接。 检查mysql 是否监听 0.0.0.0 ,默认情况, mysql 需要开启配置支持远程访问。可以在mysql的配置文件 my.cnf 中配置bind-address。

bind-address = 0.0.0.0

使用kubectl exec命令进入 mysql pod ,检查配置文件。

kubectl exec -it <mysql-pod> -n <namespace> -- bash
cat /etc/mysql/my.cnf # 或者其他 mysql 配置文件路径

此外还可以使用 mysql -u root -p 进入数据库控制台查看用户权限配置。确认是否有允许应用连接数据库的用户以及配置正确的连接地址。

原理: 通过mysql的配置文件检查mysql实例本身的配置是否有异常。如监听地址是否允许应用连接,用户配置的地址端口以及账号密码是否匹配。

安全建议

  • 始终使用最小权限原则,只为服务提供必要的访问权限。
  • 敏感信息如数据库密码,存储在Kubernetes secret 中。避免将密码直接写入配置文件中。
  • 网络策略设置应以允许为前提,只禁止不需要的网络访问。

遵循这些步骤能有效排查和解决EKS集群中应用与 MySQL 通信的连接问题,保证应用和数据层之间的稳定可靠连接。