【问题标题】:Is it possible to have hostname based routing for MySQL in kubernetes?是否可以在 kubernetes 中为 MySQL 提供基于主机名的路由?
【发布时间】:2020-02-17 09:07:23
【问题描述】:

我有一个场景,我有多个 mysql 服务器在单个 kubernetes 集群的不同命名空间中运行。所有的mysql服务器都属于不同的部门。

我的要求是我应该能够使用主机名连接到不同的mysql服务器,即,

在 ServerA 命名空间中运行的 mysqlServerA 应该可以从集群外部访问:

mysql -h mysqlServerA.mydomain.com -A

在 ServerB 命名空间中运行的 mysqlServerB 应该可以从集群外部访问:

mysql -h mysqlServerB.mydomain.com -A

等等。

我已经尝试使用 Nginx Ingress 控制器的配置映射基于 TCP 的路由,我通过分配不同的端口号将流量从客户端路由到不同的 mysql 服务器:

对于 mysqlServerA:

mysql -h mysqlServer.mydomain.com -A -P 3301

对于 mysqlServerB:

mysql -h mysqlServer.mydomain.com -A -P 3302

这非常有效。但我想知道基于主机名的路由是否可行,因为我不希望每个 mysql 服务都有单独的负载均衡器。

谢谢

【问题讨论】:

  • 是 GKE、EKS、Azure 还是独立设置?
  • 你好。它是数字海洋集群。
  • 这是可能的(但这不是一个直截了当且有点受限的方式)。我现在正在准备答案。

标签: mysql kubernetes routing nginx-ingress traefik-ingress


【解决方案1】:

一般信息

我通过不同的端口号路由流量

你是对的,原因是与 Mysql 的连接是通过 TCP 完成的。这就是为什么绝对不可能有两个同时连接到同一个IP:port 上的两台服务器的原因。

与 HTTP 不同,TCP 没有允许区分流量应路由到的主机的标头。但是,仍然至少有两种方法可以实现您想要实现的功能:) 我稍后会描述。

我想知道基于主机名的路由是否可行 我不希望每个 mysql 服务都有单独的负载均衡器。

K8s 允许a few methods 在集群外访问服务(即hostNetworkhostPortNodePortLoadBalancerIngress

LoadBalancer 是在 LoadBalancerIP:port 上提供流量的最简单方法;但是,由于 TCP 连接的性质,您必须为每个 mysql 实例使用一个 LoadBalancer

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

NodePort 看起来不错,但它只允许您在知道端口时进行连接(这对客户来说可能是乏味的工作)

建议的解决方案

如果有外部 IP 路由到一个或多个集群节点,Kubernetes 服务可以暴露在那些 externalIPs 上。在服务端口上使用外部 IP(作为目标 IP)进入集群的流量将被路由到服务端点之一。 externalIPs 不由 Kubernetes 管理,由集群管理员负责。

在服务规范中,externalIPs 可以与任何ServiceTypes 一起指定。在下面的例子中,mysql-1 可以被1.2.3.4:3306 (externalIP:port) 上的客户端访问,mysql-2 可以被4.3.2.1:3306 上的客户端访问

$ cat stereo-mysql-3306.yaml 
apiVersion: v1
kind: Service
metadata:
  name: mysql-1234-inst-1
spec:
  selector:
    app: mysql-prod
  ports:
    - name: mysql
      protocol: TCP
      port: 3306
      targetPort: 3306
  externalIPs:
    - 1.2.3.4 
---
apiVersion: v1
kind: Service
metadata:
  name: mysql-4321-inst-1
spec:
  selector:
    app: mysql-repl
  ports:
    - name: mysql
      protocol: TCP
      port: 3306
      targetPort: 3306
  externalIPs:
    - 4.3.2.1

注意:您需要将1.2.3.44.3.2.1 分配给您的节点(并将mysqlServerA / mysqlserverB mydomain.com 解析为这些IP)。我已经在我的 GKE 集群上测试了该解决方案并且它可以工作:)。

使用该配置,所有解析为1.2.3.4mysqlServerA.mydomain.com:3306 请求都将通过app: mysql-prod 选择器路由到Endpoints 服务mysql-1234-inst-1mysqlServerA.mydomain.com:3306 将由@ 提供服务987654355@.

当然可以将该配置拆分为 2 个命名空间(一个命名空间 - 一个 mysql - 每个命名空间一个服务)。

考虑到您的 mysql pod 具有 ClusterIP,可以在集群中生成额外的 VPN pod 并通过它连接到 mysqls。

因此,您可以建立 VPN 连接并访问所有集群资源。这是一个非常有限的解决方案,需要为需要访问 mysql 的任何人建立 VPN 连接。

良好的做法是在该解决方案之上添加堡垒服务器。该服务器将负责通过 VPN 提供对集群服务的访问。

希望对您有所帮助。

【讨论】:

  • 非常感谢尼克的详细描述。然而,在我的场景中,我有 100 台属于不同部门的 mysql 服务器在不同的命名空间下运行在一个集群中。我不能使用 externalIP,因为我需要为每个服务维护单独的 IP,在我的情况下可能需要 100 个 IP。我不能使用 VPN 方法,因为数据库也需要从应用程序中访问。
  • 您不需要分配公共 IP。来自专用网络的任何随机 IP 都可以。您只需要将流量从公共网络路由到私有网络(以便它到达您的集群)。
猜你喜欢
  • 2022-01-08
  • 2019-08-09
  • 1970-01-01
  • 2023-03-22
  • 2015-01-16
  • 2016-01-21
  • 1970-01-01
  • 1970-01-01
  • 2019-07-14
相关资源
最近更新 更多