Skip to main content

如何配置 TINC 实现多路容灾?

场景#

网络结构

  • 现有 3 台服务器提供相同的服务,希望使用同一个 IP 进行访问
    • 即为 A B C 主机提供 VIP/虚拟 IP
  • 需要支持 2层 转发 - 网桥、网关
    • 如果不需要 2层 或者不需要任意端口 也可以考虑 Nginx/HAProxy 等进行转发 - 对端口进行负载容灾
    • 使用 mac 寻址
  • 一个节点异常后能够快速切换到其它节点
  • 需要负载均衡 - 多路不会进行负载

原理#

  • Tinc 支持两种工作模式 - Route 和 Switch - 分别工作在 3 层和 2 层 - 默认使用 Route 3 层,需要配置为 Switch 模式工作在 2 层
  • 使用 Switch 模式时每个节点会生成 mac 地址用于路由
  • 访问 IP 时会通过 arp 将 IP 转换为 mac 地址
  • 在多个节点上配置相同的 IP,即可以做到多路容灾

部署#

💡提示

TINC 的基础部署概念在这里不再赘述,请参考 如何部署 TINC 网络

Docker 部署验证#

  • 操作流程
    1. 创建 Docker 网络 - 以使用静态 IP
    • 容器网络 - 172.18.3.0/24
    1. 创建 5 个容器
      • node-1 网络主节点
        • mynet TINC 网络 - 10.1.1.1/24
        • 静态 IP - 172.18.3.100
      • node-2-4 服务节点
        • 服务提供统一的 VIP - 10.1.1.10
        • 每个节点直接访问 IP - 10.1.1.102-104
      • node-5 客户端节点
        • 节点 IP - 10.1.1.2
        • 通过 VIP 访问服务
    2. 初始化 Switch 模式的 Tinc 网络
    3. 从节点加入
    4. 验证访问
    5. 验证服务容灾能力

环境初始化#

💡提示

实际部署与 Docker 操作没有任何区别,只需要注意配置接入点的 Address

# 网络初始化docker network create service --subnet 172.18.3.0/24
# 容器初始化 - 如果需要持久化 tinc 配置可以映射 /etc/tinc/mynet 目录# node-1 节点使用静态 ipdocker run -d --network tinc --ip 172.18.0.100 --cap-add NET_ADMIN --device /dev/net/tun --name node-1 wener/tinc tail -f /dev/null# node 2 3 4 5 节点初始化seq 2 5 | xargs -I {} -n 1 docker run -d --network tinc --cap-add NET_ADMIN --device /dev/net/tun --name node-{} wener/tinc tail -f /dev/null

网络初始化#

# 在 node-1 配置 tinc 网络cat <<'EOF' | docker exec -i node-1 shset -x# 网络名为 mynettinc -n mynet init mynet# 配置 Switch 模式echo Mode=Switch >> /etc/tinc/mynet/tinc.conf
# 配置 TINC 地址echo -e '#!/bin/sh\nifconfig $INTERFACE 10.1.1.1 netmask 255.255.255.0' > /etc/tinc/mynet/tinc-up
# 监听端口echo Port=655 >> /etc/tinc/mynet/hosts/mynet# 外部地址echo Address=172.18.0.100 >> /etc/tinc/mynet/hosts/mynetEOF
# 启动网络docker exec node-1 tinc -n mynet start
# 节点加入 - node-1 邀请其它节点 - 生成 url 其它节点加入for i in $(seq 2 5); do  url=$(docker exec node-1 tinc -n mynet invite node_$i)  docker exec node-$i tinc join $urldone
# 为 node 2 3 4 配置统一的 IP 10.1.1.10seq 2 4 | xargs -I {} -n 1 docker exec node-{} sh -c "echo 'ifconfig \$INTERFACE 10.1.1.10 netmask 255.255.255.0' > /etc/tinc/mynet/tinc-up"
# 为 node 2 3 4 配置额外的管理 IP 10.1.1.102-104seq 2 4 | xargs -I {} -n 1 docker exec node-{} sh -c "echo 'ip addr add 10.1.1.10{}/24 dev mynet' >> /etc/tinc/mynet/tinc-up"
# 为 node-5 配置 10.1.1.2docker exec node-5 sh -c "echo 'ifconfig \$INTERFACE 10.1.1.2 netmask 255.255.255.0' > /etc/tinc/mynet/tinc-up"
# 启动所有节点seq 2 5 | xargs -I {} -n 1 docker exec node-{} tinc -n mynet start
# 在主节点查看链接状态# 所有节点都在docker exec node-1 tinc -n mynet dump nodes

高可用验证#

# 一个会话一直 PING 服务 IP - 观察链接情况# 注意是从 node-5 pingdocker exec -it node-5 ping 10.1.1.10
# 以下在 node-5 执行docker exec node-5 sh
# 获取当前 10.1.1.10 对应的 macip neigh show 10.1.1.10# 获取 该 mac 对应的 tinc 节点tinc -n mynet info $(ip neigh show 10.1.1.10 | egrep -o '..:\S+')

在宿主机上停止当前节点

# 将当前 10.1.1.10 的节点停止node=$(docker exec node-5 sh -c "tinc -n mynet info \$(ip neigh show 10.1.1.10 | egrep -o '..:\S+') | grep -o node_. | grep -o '\d'")docker stop node-$node

此时会观察到 10秒 左右的 PING 丢包,我看到的日志是这样的

64 bytes from 10.1.1.10: seq=411 ttl=64 time=0.617 ms64 bytes from 10.1.1.10: seq=412 ttl=64 time=1.033 ms64 bytes from 10.1.1.10: seq=420 ttl=64 time=4.084 ms64 bytes from 10.1.1.10: seq=421 ttl=64 time=0.796 ms

然后再在 node-5 上确认当前新的节点

tinc -n mynet info $(ip neigh show 10.1.1.10 | egrep -o '..:\S+')

至此,完成验证。当然也可以继续停止当前节点然后观察,或者启动新的节点观察,总之 tinc 的行为符合预期,达到目的。

销毁环境#

# 停止容器seq 1 5 | xargs -I {} -n 1 docker rm -f node-{}# 删除网络docker network rm service

Ansible 部署#

💡提示 Ansible 执行基于 wenerme/alpine-admin 提供的任务

配置和仓库节点如下,按需更改 IP

hosts.yaml

all:  hosts:    # 主节点    mynet:      ansible_host: 172.18.3.100      tinc_address: 10.1.1.1      tinc_conf:      - {name: Mode, value: switch}      tinc_host_conf:      - {name: Port, value: 655}      - {name: Address, value: 172.18.3.100}    # 服务节点    node-2: {ansible_host: 172.18.3.1, tinc_address: 10.1.1.10}    node-3: {ansible_host: 172.18.3.2, tinc_address: 10.1.1.10}    node-4: {ansible_host: 172.18.3.3, tinc_address: 10.1.1.10}  children:    tinc-nodes:      hosts:        node-[2:4]:  vars:    tinc_netname: mynet    tinc_subnet: 10.1.1.0/24    # 从节点使用随机端口避免检测    tinc_host_conf:      - {name: Port, value: 0}

使用 Ansible 部署

# 简化操作 - 使用 -i hosts.yaml 指定了仓库adhoc(){ local task=$1; shift; ansible-playbook $PWD/adhoc.yaml -e task=$task -i hosts.yaml $*; }
# 为所有节点配置仓库 - https://github.com/wenerme/repository# 因为目前官方仓库没有adhoc wener-repo
# 安装 tincadhoc tinc-install
# 初始化网路adhoc tinc-init -l mynet# 启动服务adhoc tinc-service -l mynet
# 加入 TINC 网络adhoc tinc-join -l tinc-nodes# 启动服务adhoc tinc-service -l tinc-nodes
# 查看主机信息 - 包含 tinc 网络adhoc tinc-service -l host-info

完成部署。使用 ansible 能够快速部署大规模的 tinc 网络。