通过 Kind + ContainerLab 模拟 Calico BGP Downward Default 模型

前言

Calico BGP 模式生产环境模型选择可参考另一文章,本文仅用于环境生成脚本存档与参数解析。

模型拓扑

image

部署脚本

为方便体验 Calico BGP Downward Default 模型在集群中的应用,通过 Kind + Docker + ContainerLab 快速部署 k8s 并模拟三层交换机

版本选择

基础设施 版本
Kind v0.31.0
VyOS 1.4.9
Docker 29.3.1
Calicoctl v3.31.5
Kubernetes v1.27.3
ContainerLab 0.59.0

部署脚本

1.主脚本

#!/bin/bash

set -v

# 1.通过 Kind 创建 k8s 集群,部署时关闭默认的 CNI 安装
cat << EOF | HTTP_PROXY= HTTPS_PROXY= http_proxy= https_proxy= kind create cluster --name=calico-bgp-rr --image=kindest/node:v1.27.3 --config=-
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
networking:
  disableDefaultCNI: true
  podSubnet: "10.244.0.0/16"
nodes:
- role: control-plane
  kubeadmConfigPatches:
  - |
    kind: InitConfiguration
    nodeRegistration:
      kubeletExtraArgs:
        node-ip: 10.1.5.10
        node-labels: "rack=rack0"

- role: worker
  kubeadmConfigPatches:
  - |
    kind: JoinConfiguration
    nodeRegistration:
      kubeletExtraArgs:
        node-ip: 10.1.5.11
        node-labels: "rack=rack0"

- role: worker
  kubeadmConfigPatches:
  - |
    kind: JoinConfiguration
    nodeRegistration:
      kubeletExtraArgs:
        node-ip: 10.1.8.10
        node-labels: "rack=rack1"

- role: worker
  kubeadmConfigPatches:
  - |
    kind: JoinConfiguration
    nodeRegistration:
      kubeletExtraArgs:
        node-ip: 10.1.8.11
        node-labels: "rack=rack1"
EOF


# 2.去除 Control 节点污点
controller_node_ip=`kubectl get node -o wide --no-headers | grep -E "control-plane|bpf1" | awk -F " " '{print $6}'`
kubectl taint nodes $(kubectl get nodes -o name | grep control-plane) node-role.kubernetes.io/control-plane:NoSchedule-


# 3.通过 ContainerLab 模拟三层交换机,并创建对应容器生成网卡,通过与 k8s node 容器共享网络方式挂载进去
./2-setup-clab.sh


# 4. 通过 Calicocli 工具更改 k8s node BGP 配置
./3-prep-calico-bgp.sh

2.ContainerLab 环境生成脚本

#!/bin/bash

set -v

for br in br-leaf0 br-leaf1; do
    ip link set $br down > /dev/null 2>&1
    ip link delete $br
    ip link add $br type bridge
    ip link set $br up
done

cat << EOF > clab.yaml | containerlab deploy -t clab.yaml -
name: calico-bgp-rr
topology:
  nodes:
    ## 模拟核心层交换机
    spine0:
      kind: linux
      image: burlyluo/vyos:1.4.9
      cmd: /sbin/init
      binds:
        - /lib/modules:/lib/modules
        - ./startup-conf/spine0-boot.cfg:/opt/vyatta/etc/config/config.boot

    spine1:
      kind: linux
      image: burlyluo/vyos:1.4.9
      cmd: /sbin/init
      binds:
        - /lib/modules:/lib/modules
        - ./startup-conf/spine1-boot.cfg:/opt/vyatta/etc/config/config.boot

    ## 这两个 leaf 网桥模拟接入层交换机(BGP Route Reflector)
    leaf0:
      kind: linux
      image: burlyluo/vyos:1.4.9
      cmd: /sbin/init
      binds:
        - /lib/modules:/lib/modules
        - ./startup-conf/leaf0-boot.cfg:/opt/vyatta/etc/config/config.boot
      ## 删除 leaf eth0 是因为默认生成的 eth0 权重高,直接把 spine 下发的 default 路由覆盖了
      exec:
        - ip route del default dev eth0

    leaf1:
      kind: linux
      image: burlyluo/vyos:1.4.9
      cmd: /sbin/init
      binds:
        - /lib/modules:/lib/modules
        - ./startup-conf/leaf1-boot.cfg:/opt/vyatta/etc/config/config.boot
      exec:
        - ip route del default dev eth0

    ## 二层网桥
    br-leaf0:
      kind: bridge
  
    br-leaf1:
      kind: bridge

    server1:
      kind: linux
      image: burlyluo/nettool:latest
      network-mode: container:calico-bgp-rr-control-plane
      exec:
      - ip addr add 10.1.5.10/24 dev net0
      - ip route replace default via 10.1.5.1

    server2:
      kind: linux
      image: burlyluo/nettool:latest
      network-mode: container:calico-bgp-rr-worker
      exec:
      - ip addr add 10.1.5.11/24 dev net0
      - ip route replace default via 10.1.5.1

    server3:
      kind: linux
      image: burlyluo/nettool:latest
      network-mode: container:calico-bgp-rr-worker2
      exec:
      - ip addr add 10.1.8.10/24 dev net0
      - ip route replace default via 10.1.8.1

    server4:
      kind: linux
      image: burlyluo/nettool:latest
      network-mode: container:calico-bgp-rr-worker3
      exec:
      - ip addr add 10.1.8.11/24 dev net0
      - ip route replace default via 10.1.8.1

  ## 用 links 把所有设备连起来后,Kind 节点流量就必须经过 leaf 交换机才能跨机架通信:
  ## - server1/server2 → br-leaf0(rack0 的节点连到 rack0 的网桥)
  ## - server3/server4 → br-leaf1(rack1 的节点连到 rack1 的网桥)
  ## - leaf0 → br-leaf0(leaf 交换机连到对应网桥)
  ## - leaf1 → br-leaf1
  ## - leaf0/leaf1 → spine0/spine1(上联到核心交换机)
  links:
    - endpoints: ["br-leaf0:br-leaf0-net0", "server1:net0"]
      mtu: 1500
    - endpoints: ["br-leaf0:br-leaf0-net1", "server2:net0"]
      mtu: 1500

    - endpoints: ["br-leaf1:br-leaf1-net0", "server3:net0"]
      mtu: 1500
    - endpoints: ["br-leaf1:br-leaf1-net1", "server4:net0"]
      mtu: 1500

    - endpoints: ["leaf0:eth1", "spine0:eth1"]
      mtu: 1500
    - endpoints: ["leaf0:eth2", "spine1:eth1"]
      mtu: 1500
    - endpoints: ["leaf0:eth3", "br-leaf0:br-leaf0-net2"]
      mtu: 1500

    - endpoints: ["leaf1:eth1", "spine0:eth2"]
      mtu: 1500
    - endpoints: ["leaf1:eth2", "spine1:eth2"]
      mtu: 1500
    - endpoints: ["leaf1:eth3", "br-leaf1:br-leaf1-net2"]
      mtu: 1500
EOF

2.1.startup-conf/leaf0-boot.cfg

注:VyOS 配置中不允许使用 # 注释,部署时记得把注释删了

// 接口配置
interfaces {
    ethernet eth1 {
        address "10.1.10.1/24"
        duplex "auto"
        mtu "9000"
        offload {
            gso
            sg
        }
        speed "auto"
    }
    ethernet eth2 {
        address "10.1.12.1/24"
        duplex "auto"
        mtu "9000"
        offload {
            gso
            sg
        }
        speed "auto"
    }
    ethernet eth3 {
        address "10.1.5.1/24"
        duplex "auto"
        mtu "9000"
        offload {
            gso
            sg
        }
        speed "auto"
    }
    loopback lo {
    }
}

// 路由策略
policy {
    // 定义一个名为 PL-DEFAULT 的前缀列表
    prefix-list PL-DEFAULT {
	    // 规则编号 10(编号越小优先级越高)
        rule 10 {
		    // 匹配到了就"放行",给后面 route-map 用(仅表示"命中",不是最终放行/拒绝)
            action "permit"
			// 匹配目标
            prefix "0.0.0.0/0"
        }
    }
	// 阻止默认路由向上游传播
    route-map RM-BLOCK-DEFAULT-UPSTREAM {
        rule 10 {
		    // 如果这条路由是默认路由(0.0.0.0/0),直接拒绝,不传递
			// 因为 Calico BGP Downward Default 模型会向下转递 defalut 路由
			// 模拟时不能倒反天罡,把下面的路由传给上面
            action "deny"
            match {
                ip {
                    address {
                        prefix-list "PL-DEFAULT"
                    }
                }
            }
        }
		// 其余的全部放行
        rule 99 {
            action "permit"
        }
    }
    route-map RM-DEFAULT-ONLY {
        rule 10 {
            action "permit"
            match {
                ip {
                    address {
                        prefix-list "PL-DEFAULT"
                    }
                }
            }
        }
        rule 99 {
            action "deny"
        }
    }
}

protocols {
    bgp {
        address-family {
		    // BGP 路由宣告(我能到达哪些网段)
			// 注:宣告的前提是该网段必须在本机路由表中已存在(直连或静态路由),否则 BGP 不会真正通告出去
            ipv4-unicast {
                network 10.1.5.0/24 {
                }
                network 10.1.10.0/24 {
                }
                network 10.1.12.0/24 {
                }
            }
        }
		// k8s node 邻居
        neighbor 10.1.5.10 {
            address-family {
                ipv4-unicast {
				    // 主动向  k8s node 发一条 0.0.0.0/0 默认路由。效果是让 k8s node 认为"发往任何未知地址的流量都交给 leaf0"
                    default-originate
                    route-map {
					    // 出方向过滤策略(前面讲过的)只允许发默认路由
                        export "RM-DEFAULT-ONLY"
                    }
                }
            }
			// eBGP,k8s node AS
            remote-as "65500"
        }
        neighbor 10.1.5.11 {
            address-family {
                ipv4-unicast {
                    default-originate
                    route-map {
                        export "RM-DEFAULT-ONLY"
                    }
                }
            }
            remote-as "65500"
        }
        neighbor 10.1.10.2 {
            address-family {
                ipv4-unicast {
                    route-map {
                        export "RM-BLOCK-DEFAULT-UPSTREAM"
                    }
                }
            }
            remote-as "500"
        }
        neighbor 10.1.12.2 {
            address-family {
                ipv4-unicast {
                    route-map {
                        export "RM-BLOCK-DEFAULT-UPSTREAM"
                    }
                }
            }
            remote-as "800"
        }
        parameters {
            bestpath {
                as-path {
                    multipath-relax
                }
            }
            router-id "10.1.5.1"
        }
        system-as "64512"
    }
}

system {
    // 配置版本管理
	// 可通过 rollback N 回滚到第 N 个版本。超过 100 个后最旧的自动删除
    config-management {
        commit-revisions "100"
    }
	// 连接追踪模块
	// 没有 SNAT 的话应该用不到这里...
    conntrack {
        modules {
            ftp
            h323
            nfs
            pptp
            sip
            sqlnet
            tftp
        }
    }
	// 串口控制台
	// 容器环境下应该也没用。这是物理服务器/虚拟机通过串口线连接终端时用的
	// 容器里通过 docker exec 或 kubectl exec 访问,不经过串口
    console {
        device ttyS0 {
            speed "9600"
        }
    }
	// 主机名
    host-name "leaf0"
	// 账户
    login {
        user vyos {
            authentication {
                encrypted-password "$6$QxPS.uk6mfo$9QBSo8u1FkH16gMyAVhus6fU3LOzvLR9Z9.82m3tiHFAxTtIkhaZSWssSgzt4v4dGAL8rhVQxTg0oAG9/q11h/"
                plaintext-password ""
            }
        }
    }
	// 时区
    time-zone "Asia/Shanghai"
}

2.2.startup-conf/leaf1-boot.cfg

interfaces {
    ethernet eth1 {
        address "10.1.34.1/24"
        duplex "auto"
        mtu "9000"
        offload {
            gso
            sg
        }
        speed "auto"
    }
    ethernet eth2 {
        address "10.1.11.1/24"
        duplex "auto"
        mtu "9000"
        offload {
            gso
            sg
        }
        speed "auto"
    }
    ethernet eth3 {
        address "10.1.8.1/24"
        duplex "auto"
        mtu "9000"
        offload {
            gso
            sg
        }
        speed "auto"
    }
    loopback lo {
    }
}
nat {
    source {
        rule 100 {
            outbound-interface {
                name "eth0"
            }
            source {
                address "10.1.0.0/16"
            }
            translation {
                address "masquerade"
            }
        }
    }
}
policy {
    prefix-list PL-DEFAULT {
        rule 10 {
            action "permit"
            prefix "0.0.0.0/0"
        }
    }
    route-map RM-BLOCK-DEFAULT-UPSTREAM {
        rule 10 {
            action "deny"
            match {
                ip {
                    address {
                        prefix-list "PL-DEFAULT"
                    }
                }
            }
        }
        rule 99 {
            action "permit"
        }
    }
    route-map RM-DEFAULT-ONLY {
        rule 10 {
            action "permit"
            match {
                ip {
                    address {
                        prefix-list "PL-DEFAULT"
                    }
                }
            }
        }
        rule 99 {
            action "deny"
        }
    }
}
protocols {
    bgp {
        address-family {
            ipv4-unicast {
                network 10.1.8.0/24 {
                }
                network 10.1.11.0/24 {
                }
                network 10.1.34.0/24 {
                }
            }
        }
        neighbor 10.1.8.10 {
            address-family {
                ipv4-unicast {
                    default-originate
                    route-map {
                        export "RM-DEFAULT-ONLY"
                    }
                }
            }
            remote-as "65500"
        }
        neighbor 10.1.8.11 {
            address-family {
                ipv4-unicast {
                    default-originate
                    route-map {
                        export "RM-DEFAULT-ONLY"
                    }
                }
            }
            remote-as "65500"
        }
        neighbor 10.1.11.2 {
            address-family {
                ipv4-unicast {
                    route-map {
                        export "RM-BLOCK-DEFAULT-UPSTREAM"
                    }
                }
            }
            remote-as "800"
        }
        neighbor 10.1.34.2 {
            address-family {
                ipv4-unicast {
                    route-map {
                        export "RM-BLOCK-DEFAULT-UPSTREAM"
                    }
                }
            }
            remote-as "500"
        }
        parameters {
            bestpath {
                as-path {
                    multipath-relax
                }
            }
            router-id "10.1.8.1"
        }
        system-as "64512"
    }
}
system {
    config-management {
        commit-revisions "100"
    }
    conntrack {
        modules {
            ftp
            h323
            nfs
            pptp
            sip
            sqlnet
            tftp
        }
    }
    console {
        device ttyS0 {
            speed "9600"
        }
    }
    host-name "leaf1"
    login {
        user vyos {
            authentication {
                encrypted-password "$6$QxPS.uk6mfo$9QBSo8u1FkH16gMyAVhus6fU3LOzvLR9Z9.82m3tiHFAxTtIkhaZSWssSgzt4v4dGAL8rhVQxTg0oAG9/q11h/"
                plaintext-password ""
            }
        }
    }
    time-zone "Asia/Shanghai"
}

2.3.startup-conf/spine0-boot.cfg

interfaces {
    ethernet eth1 {
        address "10.1.10.2/24"
        duplex "auto"
        offload {
            gso
            sg
        }
        speed "auto"
    }
    ethernet eth2 {
        address "10.1.34.2/24"
        duplex "auto"
        offload {
            gso
            sg
        }
        speed "auto"
    }
    loopback lo {
    }
}
nat {
    source {
        rule 100 {
            outbound-interface {
                name "eth0"
            }
            source {
                address "10.1.0.0/16"
            }
            translation {
                address "masquerade"
            }
        }
    }
}
policy {
    prefix-list PL-DEFAULT {
        rule 10 {
            action "permit"
            prefix "0.0.0.0/0"
        }
    }
    route-map RM-DEFAULT-ONLY {
        rule 10 {
            action "permit"
            match {
                ip {
                    address {
                        prefix-list "PL-DEFAULT"
                    }
                }
            }
        }
        rule 99 {
            action "deny"
        }
    }
}
protocols {
    bgp {
        address-family {
            ipv4-unicast {
                network 10.1.10.0/24 {
                }
                network 10.1.34.0/24 {
                }
            }
        }
        neighbor 10.1.10.1 {
            address-family {
                ipv4-unicast {
                    default-originate
                    route-map {
                        export "RM-DEFAULT-ONLY"
                    }
                }
            }
            remote-as "64512"
        }
        neighbor 10.1.34.1 {
            address-family {
                ipv4-unicast {
                    default-originate
                    route-map {
                        export "RM-DEFAULT-ONLY"
                    }
                }
            }
            remote-as "64512"
        }
        parameters {
            bestpath {
                as-path {
                    multipath-relax
                }
            }
            router-id "10.1.10.2"
        }
        system-as "500"
    }
}
system {
    config-management {
        commit-revisions "100"
    }
    conntrack {
        modules {
            ftp
            h323
            nfs
            pptp
            sip
            sqlnet
            tftp
        }
    }
    console {
        device ttyS0 {
            speed "9600"
        }
    }
    host-name "spine0"
    login {
        user vyos {
            authentication {
                encrypted-password "$6$QxPS.uk6mfo$9QBSo8u1FkH16gMyAVhus6fU3LOzvLR9Z9.82m3tiHFAxTtIkhaZSWssSgzt4v4dGAL8rhVQxTg0oAG9/q11h/"
                plaintext-password ""
            }
        }
    }
    time-zone "Asia/Shanghai"
}

2.4.startup-conf/spine1-boot.cfg

interfaces {
    ethernet eth1 {
        address "10.1.12.2/24"
        duplex "auto"
        mtu "9000"
        offload {
            gso
            sg
        }
        speed "auto"
    }
    ethernet eth2 {
        address "10.1.11.2/24"
        duplex "auto"
        mtu "9000"
        offload {
            gso
            sg
        }
        speed "auto"
    }
    loopback lo {
    }
}
nat {
    source {
        rule 100 {
            outbound-interface {
                name "eth0"
            }
            source {
                address "10.1.0.0/16"
            }
            translation {
                address "masquerade"
            }
        }
    }
}
policy {
    prefix-list PL-DEFAULT {
        rule 10 {
            action "permit"
            prefix "0.0.0.0/0"
        }
    }
    route-map RM-DEFAULT-ONLY {
        rule 10 {
            action "permit"
            match {
                ip {
                    address {
                        prefix-list "PL-DEFAULT"
                    }
                }
            }
        }
        rule 99 {
            action "deny"
        }
    }
}
protocols {
    bgp {
        address-family {
            ipv4-unicast {
                network 10.1.11.0/24 {
                }
                network 10.1.12.0/24 {
                }
            }
        }
        neighbor 10.1.11.1 {
            address-family {
                ipv4-unicast {
                    default-originate
                    route-map {
                        export "RM-DEFAULT-ONLY"
                    }
                }
            }
            remote-as "64512"
        }
        neighbor 10.1.12.1 {
            address-family {
                ipv4-unicast {
                    default-originate
                    route-map {
                        export "RM-DEFAULT-ONLY"
                    }
                }
            }
            remote-as "64512"
        }
        parameters {
            bestpath {
                as-path {
                    multipath-relax
                }
            }
            router-id "10.1.12.2"
        }
        system-as "800"
    }
}
system {
    config-management {
        commit-revisions "100"
    }
    conntrack {
        modules {
            ftp
            h323
            nfs
            pptp
            sip
            sqlnet
            tftp
        }
    }
    console {
        device ttyS0 {
            speed "9600"
        }
    }
    host-name "spine1"
    login {
        user vyos {
            authentication {
                encrypted-password "$6$QxPS.uk6mfo$9QBSo8u1FkH16gMyAVhus6fU3LOzvLR9Z9.82m3tiHFAxTtIkhaZSWssSgzt4v4dGAL8rhVQxTg0oAG9/q11h/"
                plaintext-password ""
            }
        }
    }
    time-zone "Asia/Shanghai"
}

3.Calico BGP 配置脚本

3.1.Calico BGP 模式 yaml 清单

https://github.com/projectcalico/calico/blob/v3.31.5/manifests/calico.yaml
./calico.yaml 提前准备好下一脚本中的部署文件,并修改部署参数

            # Auto-detect the BGP IP address.
            - name: IP
              value: "autodetect"
            # Enable IPIP
            - name: CALICO_IPV4POOL_IPIP
              value: "Never"
            # Enable or Disable VXLAN on the default IP pool.
            - name: CALICO_IPV4POOL_VXLAN
              value: "Never"
            # Enable or Disable VXLAN on the default IPv6 IP pool.
            - name: CALICO_IPV6POOL_VXLAN
              value: "Never"

3.2.通过 Calicocli 工具配置 BGP

#!/bin/bash

set -v

# 1. Install CNI[Calico v3.31.5]
# https://github.com/projectcalico/calico/blob/v3.31.5/manifests/calico.yaml
kubectl apply -f ./calico.yaml

kubectl wait --timeout=100s --for=condition=Ready=true pods --all -A

# 1.2. disable bgp fullmesh
cat << EOF | calicoctl  --allow-version-mismatch apply -f -
apiVersion: projectcalico.org/v3
items:
- apiVersion: projectcalico.org/v3
  kind: BGPConfiguration
  metadata:
    name: default
  spec:
    logSeverityScreen: Info
    ## 关闭节点间的全互联(BGP Full-Mesh)
    nodeToNodeMeshEnabled: false
kind: BGPConfigurationList
metadata:
EOF

# 1.3. add bgp configuration for the nodes
## 所有 K8s Node 统一使用 AS 65500(Downward Default 模型的核心变化)
cat << EOF | calicoctl  --allow-version-mismatch apply -f -
apiVersion: projectcalico.org/v3
kind: Node
metadata:
  annotations:
    projectcalico.org/kube-labels: '{"beta.kubernetes.io/arch":"amd64","beta.kubernetes.io/os":"linux","kubernetes.io/arch":"amd64","kubernetes.io/hostname":"calico-bgp-rr-control-plane","kubernetes.io/os":"linux","node-role.kubernetes.io/control-plane":"","node-role.kubernetes.io/master":"","node.kubernetes.io/exclude-from-external-load-balancers":"","rack":"rack0"}'
  labels:
    beta.kubernetes.io/arch: amd64
    beta.kubernetes.io/os: linux
    kubernetes.io/arch: amd64
    kubernetes.io/hostname: calico-bgp-rr-control-plane
    kubernetes.io/os: linux
    node-role.kubernetes.io/control-plane: ""
    node-role.kubernetes.io/master: ""
    node.kubernetes.io/exclude-from-external-load-balancers: ""
    rack: rack0
  name: calico-bgp-rr-control-plane
spec:
  addresses:
  - address: 10.1.5.10
    type: InternalIP
  bgp:
    ## 所有 Node 统一 AS 65500
    asNumber: 65500
    ipv4Address: 10.1.5.10/24
  orchRefs:
  - nodeName: calico-bgp-rr-control-plane
    orchestrator: k8s
status:
  podCIDRs:
  - 10.244.0.0/24
EOF

cat << EOF | calicoctl  --allow-version-mismatch apply -f -
apiVersion: projectcalico.org/v3
kind: Node
metadata:
  annotations:
    projectcalico.org/kube-labels: '{"beta.kubernetes.io/arch":"amd64","beta.kubernetes.io/os":"linux","kubernetes.io/arch":"amd64","kubernetes.io/hostname":"calico-bgp-rr-worker","kubernetes.io/os":"linux","rack":"rack0"}'
  creationTimestamp: "2022-12-05T08:40:29Z"
  labels:
    beta.kubernetes.io/arch: amd64
    beta.kubernetes.io/os: linux
    kubernetes.io/arch: amd64
    kubernetes.io/hostname: calico-bgp-rr-worker
    kubernetes.io/os: linux
    rack: rack0
  name: calico-bgp-rr-worker
spec:
  addresses:
  - address: 10.1.5.11
    type: InternalIP
  bgp:
    ## 所有 Node 统一 AS 65500
    asNumber: 65500
    ipv4Address: 10.1.5.11/24
  orchRefs:
  - nodeName: calico-bgp-rr-worker
    orchestrator: k8s
status:
  podCIDRs:
  - 10.244.1.0/24
EOF


cat << EOF | calicoctl  --allow-version-mismatch apply -f -
apiVersion: projectcalico.org/v3
kind: Node
metadata:
  annotations:
    projectcalico.org/kube-labels: '{"beta.kubernetes.io/arch":"amd64","beta.kubernetes.io/os":"linux","kubernetes.io/arch":"amd64","kubernetes.io/hostname":"calico-bgp-rr-worker2","kubernetes.io/os":"linux","rack":"rack1"}'
  creationTimestamp: "2022-12-05T08:40:29Z"
  labels:
    beta.kubernetes.io/arch: amd64
    beta.kubernetes.io/os: linux
    kubernetes.io/arch: amd64
    kubernetes.io/hostname: calico-bgp-rr-worker2
    kubernetes.io/os: linux
    rack: rack1
  name: calico-bgp-rr-worker2
spec:
  addresses:
  - address: 10.1.8.10
    type: InternalIP
  bgp:
    ## 所有 Node 统一 AS 65500
    asNumber: 65500
    ipv4Address: 10.1.8.10/24
  orchRefs:
  - nodeName: calico-bgp-rr-worker2
    orchestrator: k8s
status:
  podCIDRs:
  - 10.244.2.0/24
EOF

cat << EOF | calicoctl  --allow-version-mismatch apply -f -
apiVersion: projectcalico.org/v3
kind: Node
metadata:
  annotations:
    projectcalico.org/kube-labels: '{"beta.kubernetes.io/arch":"amd64","beta.kubernetes.io/os":"linux","kubernetes.io/arch":"amd64","kubernetes.io/hostname":"calico-bgp-rr-worker3","kubernetes.io/os":"linux","rack":"rack1"}'
  creationTimestamp: "2022-12-05T08:40:29Z"
  labels:
    beta.kubernetes.io/arch: amd64
    beta.kubernetes.io/os: linux
    kubernetes.io/arch: amd64
    kubernetes.io/hostname: calico-bgp-rr-worker3
    kubernetes.io/os: linux
    rack: rack1
  name: calico-bgp-rr-worker3
spec:
  addresses:
  - address: 10.1.8.11
    type: InternalIP
  bgp:
    ## 所有 Node 统一 AS 65500
    asNumber: 65500
    ipv4Address: 10.1.8.11/24
  orchRefs:
  - nodeName: calico-bgp-rr-worker3
    orchestrator: k8s
status:
  podCIDRs:
  - 10.244.3.0/24
EOF

# 1.4. peer to leaf0 switch
## Leaf AS 统一为 64512
cat << EOF | calicoctl  --allow-version-mismatch apply -f -
apiVersion: projectcalico.org/v3
kind: BGPPeer
metadata:
  name: rack0-to-leaf0
spec:
  peerIP: 10.1.5.1
  asNumber: 64512
  nodeSelector: rack == 'rack0'
EOF

# 1.5. peer to leaf1 switch
## Leaf AS 统一为 64512
cat << EOF | calicoctl --allow-version-mismatch  apply -f -
apiVersion: projectcalico.org/v3
kind: BGPPeer
metadata:
  name: rack1-to-leaf1
spec:
  peerIP: 10.1.8.1
  asNumber: 64512
  nodeSelector: rack == 'rack1'
EOF

4.部署测试 Pod

本质上是 nginx,用于部署后查询主机路由、抓包,验证效果

apiVersion: apps/v1
kind: StatefulSet
metadata:
  labels:
    app: nginx
  name: pod
spec:
  replicas: 4
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - image: burlyluo/nettool:latest
        name: nettoolbox
        env:
          - name: NETTOOL_NODE_NAME
            valueFrom:
              fieldRef:
                fieldPath: spec.nodeName
        securityContext:
          privileged: true
      affinity:
        podAntiAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
          - labelSelector:
              matchLabels:
                app: nginx
            topologyKey: kubernetes.io/hostname
posted @ 2026-05-17 12:18  怎么还在写代码  阅读(33)  评论(0)    收藏  举报