使用 Docker 运行 FRR BGP

使用 Docker 运行 FRR BGP

之前写 在 Kubernetes 集群中使用 MetalLB 作为 LoadBalancer(下)- BGP 时,我曾在 OpenWRT 安装 FRR 来进行了测试。需要 OpenWRT 的环境不免会有些繁琐,假如只是做些更简单的测试,比如从 FRR 所在服务器上进行 VIP 的访问,则是不需要 OpenWRT 的,仅仅部署 FRR 就足够了。

今天我就尝试了直接使用 Docker 运行 FRR 来启动 BGP Router 进程,简单的几步即可实现,对环境要求非常低,只需要个 Docker 就行。如果你又更简单的方法,也请留言分享。


创建一个本地目录在管理 FRR 配置,这个目录将会挂载到容器中。

mkdir frr

准备 FRR Daemon 的日志,开启 BGP daemon 进程。

tee > ./frr/daemons <<EOF
# This file tells the frr package which daemons to start.
# Sample configurations for these daemons can be found in
# /usr/share/doc/frr/examples/.
# When activating a daemon for the first time, a config file, even if it is
# empty, has to be present *and* be owned by the user and group "frr", else
# the daemon will not be started by /etc/init.d/frr. The permissions should
# be u=rw,g=r,o=.
# When using "vtysh" such a config file is also needed. It should be owned by
# group "frrvty" and set to ug=rw,o= though. Check /etc/pam.d/frr, too.
# The watchfrr, zebra and staticd daemons are always started.

# If this option is set the /etc/init.d/frr script automatically loads
# the config via "vtysh -b" when the servers are started.
# Check /etc/pam.d/frr if you intend to use "vtysh"!
zebra_options="  -A -s 90000000"
bgpd_options="   -A"
ospfd_options="  -A"
ospf6d_options=" -A ::1"
ripd_options="   -A"
ripngd_options=" -A ::1"
isisd_options="  -A"
pimd_options="   -A"
pim6d_options="  -A ::1"
ldpd_options="   -A"
nhrpd_options="  -A"
eigrpd_options=" -A"
babeld_options=" -A"
sharpd_options=" -A"
pbrd_options="   -A"
bfdd_options="   -A"
vrrpd_options="  -A"
pathd_options="  -A"

# If you want to pass a common option to all daemons, you can use the
# "frr_global_options" variable.

# The list of daemons to watch is automatically generated by the init script.
# This variable can be used to pass options to watchfrr that will be passed
# prior to the daemon list.
# To make watchfrr create/join the specified netns, add the the "--netns"
# option here. It will only have an effect in /etc/frr/<somename>/daemons, and
# you need to start FRR with "/usr/lib/frr/frrinit.sh start <somename>".

# configuration profile

# This is the maximum number of FD's that will be available.  Upon startup this
# is read by the control files and ulimit is called.  Uncomment and use a
# reasonable value for your setup if you are expecting a large number of peers
# in say BGP.

# For any daemon, you can specify a "wrap" command to start instead of starting
# the daemon directly. This will simply be prepended to the daemon invocation.
# These variables have the form daemon_wrap, where 'daemon' is the name of the
# daemon (the same pattern as the daemon_options variables).
# Note that when daemons are started, they are told to daemonize with the `-d`
# option. This has several implications. For one, the init script expects that
# when it invokes a daemon, the invocation returns immediately. If you add a
# wrap command here, it must comply with this expectation and daemonize as
# well, or the init script will never return. Furthermore, because daemons are
# themselves daemonized with -d, you must ensure that your wrapper command is
# capable of following child processes after a fork() if you need it to do so.
# If your desired wrapper does not support daemonization, you can wrap it with
# a utility program that daemonizes programs, such as 'daemonize'. An example
# of this might look like:
# bgpd_wrap="/usr/bin/daemonize /usr/bin/mywrapper"
# This is particularly useful for programs which record processes but lack
# daemonization options, such as perf and rr.
# If you wish to wrap all daemons in the same way, you may set the "all_wrap"
# variable.

准备 BGP 的配置,包括路由器的 AS 以及邻居的配置。

tee >> ./frr/frr.conf <<EOF
ip forwarding
router bgp 65000
 bgp router-id
 no bgp ebgp-requires-policy
 bgp bestpath peer-type multipath-relax
 neighbor remote-as 65001
 neighbor remote-as 65001


该段配置是 FRRouting 中的 BGP 配置。下面是详细的解释:

  1. ip forwarding: 这启用了 IP 转发。它告诉 FRR 它应该允许从一个网络接口传递到另一个网络接口的 IP 数据包转发。
  2. router bgp 65000: 开始定义一个 BGP 路由器进程,其中 65000 是该 BGP 实例的 AS (自治系统) 号。
  3. bgp router-id 设置 BGP 路由器的 router-id。Router-ID 是 BGP 会话中使用的标识符,通常选择为路由器上的一个 IP 地址。
  4. no bgp ebgp-requires-policy: 默认情况下,BGP 需要为 eBGP (外部 BGP) 邻居定义策略(指出允许或拒绝的路由)。这条命令禁用了这个要求,允许所有的路由广播给 eBGP 邻居,除非明确配置了策略来进行过滤。
  5. bgp bestpath peer-type multipath-relax: 默认情况下,当 BGP 考虑多路径路由时,它只会考虑来自相同类型的邻居(内部 BGP 或外部 BGP)的路由。此命令修改了这一行为,允许来自不同类型的邻居的路由被考虑为等价多路径 (ECMP) 的候选。
  6. neighbor remote-as 65001: 定义了一个 BGP 邻居,其 IP 地址为,并指定它位于 AS 65001。这意味着您的路由器(在 AS 65000)将尝试与位于 AS 65001 的 建立 BGP 会话。
  7. exit: 退出 BGP 配置模式,返回到 FRR 的主配置模式。

这段配置基本上定义了一个 BGP 会话,其中本地 AS 号为 65000,与远程邻居其 AS 号为 65001)通信。


准备好配置后就可以启动容器了,注意这里使用的参数。由于做了配置持久化,我使用了 -rm 参数,可以随时销毁参数;使用了主机网络,因此无需暴露 BGP 的 179 端口。

docker run --rm -d --privileged --name frr --net=host -e watchfrr_debug=true -v ./frr:/etc/frr frrouting/frr:latest


ssh 到容器中。

docker exec -it frr sh


show bgp summary

将看到如下的信息,由于两个邻居都未上线,因此可以看到状态是 Active 但是运行时间是 never

IPv4 Unicast Summary (VRF default):
BGP router identifier, local AS number 65000 vrf-id 0
BGP table version 0
RIB entries 0, using 0 bytes of memory
Peers 2, using 1434 KiB of memory

Neighbor        V         AS   MsgRcvd   MsgSent   TblVer  InQ OutQ  Up/Down State/PfxRcd   PfxSnt Desc    4      65001         0         0        0    0    0    never       Active        0 N/A    4      65001         0         0        0    0    0    never       Active        0 N/A

Total number of neighbors 2

后面就可以启动邻居的 BGP 宣告了。


comments powered by Disqus