Documentation Home
MySQL 8.4 Reference Manual
Related Documentation Download this Manual
PDF (US Ltr) - 39.8Mb
PDF (A4) - 39.9Mb
Man Pages (TGZ) - 257.9Kb
Man Pages (Zip) - 364.9Kb
Info (Gzip) - 4.0Mb
Info (Zip) - 4.0Mb


MySQL 8.4 Reference Manual  /  ...  /  Network Namespace Support

7.1.14 网络命名空间支持

网络命名空间是一种从宿主系统复制的逻辑网络栈。网络命名空间对于设置容器或虚拟环境非常有用。每个命名空间都有自己的IP地址、网络接口、路由表等。默认或全局命名空间是宿主系统物理接口存在的那个。

命名空间特定的地址空间可能会在MySQL连接跨越命名空间时产生问题。例如,运行在容器或虚拟网络中的MySQL实例的网络地址空间可能与宿主机的地址空间不同。这可能导致现象,如客户端从一个命名空间的地址在MySQL服务器看来似乎来自另一个地址,即使客户端和服务器都运行在同一台机器上。假设两个进程都运行在IP地址为203.0.113.10的主机上,但使用不同的命名空间,一个连接可能会产生以下结果:

$> mysql --user=admin --host=203.0.113.10 --protocol=tcp

mysql> SELECT USER();
+--------------------+
| USER()             |
+--------------------+
| admin@198.51.100.2 |
+--------------------+

在这种情况下,期望的USER()值是admin@203.0.113.10。这样的行为可能会使得为连接来源分配账户权限变得困难,因为连接的源地址不是它看起来的那样。

为了解决这个问题,MySQL允许指定用于TCP/IP连接的网络命名空间,以便两个连接端点都使用一个一致的地址空间来沟通。

MySQL支持网络命名空间的平台。MySQL中的网络命名空间支持适用于:

  • MySQL服务器,mysqld

  • X插件。

  • MySQL命令行客户端,mysql。(其他客户端不受支持。它们必须在要连接到的服务器的网络命名空间中被调用。)

  • 普通复制。

  • 组复制,只有当使用MySQL通信栈来建立群组通信连接时。

以下部分描述了如何在MySQL中使用网络命名空间:

在使用MySQL中的网络命名空间支持之前,必须满足以下宿主系统前提条件:

  • 宿主操作系统必须支持网络命名空间。(例如,Linux。)

  • 要用于MySQL的任何网络命名空间必须先在宿主系统上创建。

  • 主机名解析必须由系统管理员配置,以支持网络命名空间。

    Note

    一个已知的限制是,MySQL中主机名解析对于指定在网络命名空间特定主机文件中的地址不起作用。例如,如果red命名空间的地址为/etc/netns/red/hosts文件中指定的宿主名无法绑定,既在服务器端也在客户端端都失败。解决方案是使用IP地址而不是宿主名。

  • 系统管理员必须为支持网络命名空间的MySQL二进制(mysqldmysqlmysqlxtest)启用CAP_ SYS_ADMIN操作系统特权。

    Important

    启用CAP_SYS_ADMIN是一个安全敏感的操作,因为它允许一个进程执行除了设置命名空间之外的其他有权限的操作。有关其效果的描述,请参阅https://man7.org/linux/man-pages/man7/capabilities.7.html

    由于CAP_SYS_ADMIN必须由系统管理员显式启用,MySQL二进制默认不支持网络命名空间。系统管理员在启用它之前应该评估运行MySQL进程时的安全影响。

以下示例设置了名为redblue的网络命名空间。您选择的名称可能不同,同样宿主系统上的网络地址和接口也可能不同。

在这里显示的命令应该以超级用户(root) 运行,或者在每个命令前加上sudo。例如,如果你不是root用户,要运行ipsetcap命令,你应该使用sudo ipsudo setcap

为了配置网络命名空间,使用ip命令。对于一些操作,ip命令必须在特定的命名空间内执行(该命名空间必须已经存在)。在这种情况下,请以以下方式开始命令:

ip netns exec namespace_name

例如,这个命令在red命名空间中启动了环回接口:

ip netns exec red ip link set lo up

为了添加名为redblue的命名空间,每个命名空间都有自己的虚拟以太网设备,用于作为两个命名空间之间的链接,以及每个命名空间的环回接口:

ip netns add red
ip link add veth-red type veth peer name vpeer-red
ip link set vpeer-red netns red
ip addr add 192.0.2.1/24 dev veth-red
ip link set veth-red up
ip netns exec red ip addr add 192.0.2.2/24 dev vpeer-red
ip netns exec red ip link set vpeer-red up
ip netns exec red ip link set lo up

ip netns add blue
ip link add veth-blue type veth peer name vpeer-blue
ip link set vpeer-blue netns blue
ip addr add 198.51.100.1/24 dev veth-blue
ip link set veth-blue up
ip netns exec blue ip addr add 198.51.100.2/24 dev vpeer-blue
ip netns exec blue ip link set vpeer-blue up
ip netns exec blue ip link set lo up

# if you want to enable inter-subnet routing...
sysctl net.ipv4.ip_forward=1
ip netns exec red ip route add default via 192.0.2.1
ip netns exec blue ip route add default via 198.51.100.1

命名空间之间的链接图形如下所示:

red              global           blue

192.0.2.2   <=>  192.0.2.1
(vpeer-red)      (veth-red)

                 198.51.100.1 <=> 198.51.100.2
                 (veth-blue)      (vpeer-blue)

为了查看哪些命名空间和链接存在:

ip netns list
ip link list

为了查看全局命名空间和命名命名空间的路由表:

ip route show
ip netns exec red ip route show
ip netns exec blue ip route show

为了移除redblue的链接和命名空间:

ip link del veth-red
ip link del veth-blue

ip netns del red
ip netns del blue

sysctl net.ipv4.ip_forward=0

为了使MySQL支持网络命名空间的二进制文件能够实际使用命名空间,你必须为它们授予CAP_ SYS_ADMIN能力。以下setcap命令假设你已经更改到了包含你的MySQL二进制文件的目录(根据你的系统调整路径):

cd /usr/local/mysql/bin

为了授予CAP_SYS_ADMIN能力给适当的二进制文件:

setcap cap_sys_admin+ep ./mysqld
setcap cap_sys_admin+ep ./mysql
setcap cap_sys_admin+ep ./mysqlxtest

为了检查CAP_SYS_ADMIN能力:

$> getcap ./mysqld ./mysql ./mysqlxtest
./mysqld = cap_sys_admin+ep
./mysql = cap_sys_admin+ep
./mysqlxtest = cap_sys_admin+ep

为了移除CAP_SYS_ADMIN能力:

setcap -r ./mysqld
setcap -r ./mysql
setcap -r ./mysqlxtest
Important

如果你重新安装了已经应用了setcap的二进制文件,你必须再次使用setcap。例如,如果你进行了MySQL的在位升级,忘记授予CAP_SYS_ADMIN能力会导致命名空间相关的问题。服务器因为尝试绑定到带有命名空间的地址而失败,出现以下错误:

[ERROR] [MY-013408] [Server] setns() failed with error 'Operation not permitted'

使用带有--network-namespace选项的客户端会像这样失败:

ERROR: Network namespace error: Operation not permitted

假设前面的宿主系统要求已经得到满足,MySQL允许配置服务器端的命名空间,以便于监听(入站)连接和客户端的命名空间以便于出站连接。

在服务器端,bind_addressadmin_addressmysqlx_bind_address系统变量的扩展语法允许指定用于监听入站连接的网络命名空间。要为给定的IP地址或主机名指定命名空间,添加一个斜杠和命名空间名称。例如,服务器my.cnf文件可能包含以下行:

[mysqld]
bind_address = 127.0.1.1,192.0.2.2/red,198.51.100.2/blue
admin_address = 102.0.2.2/red
mysqlx_bind_address = 102.0.2.2/red

这些规则适用:

  • 可以为IP地址或主机名指定网络命名空间。

  • 不能为通配符IP地址指定网络命名空间。

  • 对于给定的地址,网络命名空间是可选的。如果给定,它必须以/ns后缀形式立即跟在地址之后。

  • 没有/ns后缀的地址使用宿主系统的全局命名空间。全局命名空间是默认值。

  • 带有/ns后缀的地址使用名为ns的命名空间。

  • 宿主系统必须支持网络命名空间,每个命名空间都必须在之前设置。给定一个不存在的命名空间会产生错误。

  • bind_addressmysqlx_bind_address接受多个以逗号分隔的地址列表,变量值可以指定全局命名空间、命名命名空间或两者兼备的地址。

如果在服务器启动时发生错误,尝试使用命名空间,服务器不会启动。如果X插件在插件初始化期间发生错误,以至于无法绑定到任何地址,插件将失败其初始化序列,服务器将不加载它。

在客户端侧,网络命名空间可以在以下上下文中指定:

  • 对于 mysql 客户端和 mysqlxtest 测试套件客户端,使用 --network-namespace 选项。例如:

    mysql --host=192.0.2.2 --network-namespace=red

    如果省略了 --network-namespace 选项,连接将使用默认(全局)命名空间。

  • 对于从副本服务器到源服务器的复制连接,使用 CHANGE REPLICATION SOURCE TO 语句,并指定 NETWORK_NAMESPACE 选项。例如:

    CHANGE REPLICATION SOURCE TO
      SOURCE_HOST = '192.0.2.2',
      NETWORK_NAMESPACE = 'red';

    如果省略了 NETWORK_NAMESPACE 选项,复制连接将使用默认(全局)命名空间。

以下示例设置了一个 MySQL 服务器,该服务器监听全局、redblue 命名空间的连接,并展示如何配置从 redblue 命名空间连接的帐户。假设 redblue 命名空间已经按照 主机系统前提条件 创建了。

  1. 配置服务器以在多个命名空间中监听地址。将这些行放入服务器 my.cnf 文件中,并启动服务器:

    [mysqld]
    bind_address = 127.0.1.1,192.0.2.2/red,198.51.100.2/blue

    该值告诉服务器在全局命名空间中监听本地回环地址 127.0.0.1,在 red 命名空间中监听地址 192.0.2.2,以及在 blue 命名空间中监听地址 198.51.100.2

  2. 连接到全局命名空间中的服务器,并创建权限允许从每个命名空间地址空间的帐户连接:

    $> mysql -u root -h 127.0.0.1 -p
    Enter password: root_password
    
    mysql> CREATE USER 'red_user'@'192.0.2.2'
           IDENTIFIED BY 'red_user_password';
    mysql> CREATE USER 'blue_user'@'198.51.100.2'
           IDENTIFIED BY 'blue_user_password';
  3. 验证您可以在每个命名空间中连接到服务器:

    $> mysql -u red_user -h 192.0.2.2 --network-namespace=red -p
    Enter password: red_user_password
    
    mysql> SELECT USER();
    +--------------------+
    | USER()             |
    +--------------------+
    | red_user@192.0.2.2 |
    +--------------------+
    $> mysql -u blue_user -h 198.51.100.2 --network-namespace=blue -p
    Enter password: blue_user_password
    
    mysql> SELECT USER();
    +------------------------+
    | USER()                 |
    +------------------------+
    | blue_user@198.51.100.2 |
    +------------------------+
    Note

    您可能会看到 USER() 的不同结果,该函数返回一个值,包括主机名而不是 IP 地址,如果您的 DNS 已经配置为能够解析地址到相应的主机名,并且服务器未使用 skip_ name_resolve 系统变量运行。

    您还可以尝试不使用 --network-namespace 选项调用 mysql,以查看连接尝试是否成功,以及如果成功,USER() 值如何受到影响。

对于复制监控目的,这些信息源有一个列,显示适用于连接的网络命名空间: