本文分析 subnet 和 vlan 控制器的源码实现,subnet 对应到 ovn 北向数据库中的逻辑交换机 Logical Switch。
1. Subnet 处理
spec:
cidrBlock: 30.0.1.0/24
default: true
disableInterConnection: false
excludeIps:
- 30.0.1.1
gateway: 30.0.1.1
gatewayNode: ""
gatewayType: distributed
namespaces:
- ns1
natOutgoing: false
private: false
protocol: IPv4
provider: ovn
underlayGateway: false
vpc: test-vpc-1
包括 runAddSubnetWorker,runUpdateSubnetStatusWorker,runDeleteRouteWorker,runDeleteSubnetWorker,subnet 对应到 ovn 北向数据库中的逻辑交换机
switch 8bc8466b-94af-4de0-8afb-250dbb37f446 (net1)
port net1-test-vpc-1
type: router
addresses: ["00:00:00:ED:CD:0B"]
router-port: test-vpc-1-net1
router a7cb924e-300e-4183-a1c9-4676cbfc3765 (test-vpc-1)
port test-vpc-1-net1
mac: "00:00:00:ED:CD:0B"
networks: ["10.0.1.1/24"]
1.1 runAddSubnetWorker
主要处理函数为 handleAddOrUpdateSubnet,添加或者更新 subnet,对应逻辑网络 Logical Switch。
3.1.1 根据 subnet 里 vpc 查找 vpc 信息,根据 vpc 是不是默认进行分别处理,如果 vpc(vpc.status.default)不是默认的,该 vpc 允许的 namespace 必须多于 subnet 允许的 namespace。如果是默认的 vpc,则 subnet 与其他不是默认的 vpc 允许的 namespace 是否有重叠
3.1.2 calcSubnetStatusIP 函数计算子网 IP 可用以及使用个数,可用个数包括减去已经分配的IP 和 网关占用的以及设置的非分配的 IP,进行更新子网 subnet 的 status
status:
activateGateway: ""
conditions:
- lastTransitionTime: "2021-08-09T08:29:54Z"
lastUpdateTime: "2021-08-09T08:29:54Z"
reason: ResetLogicalSwitchAclSuccess
status: "True"
type: Validated
- lastTransitionTime: "2021-08-09T08:29:54Z"
lastUpdateTime: "2021-08-09T08:29:54Z"
reason: ResetLogicalSwitchAclSuccess
status: "True"
type: Ready
- lastTransitionTime: "2021-08-09T08:29:54Z"
lastUpdateTime: "2021-08-09T08:29:54Z"
message: Not Observed
reason: Init
status: Unknown
type: Error
v4availableIPs: 251
v4usingIPs: 2
v6availableIPs: 0
v6usingIPs: 0
3.1.3 ipam.AddOrUpdateSubnet,IPAM 结构体定义了 Subnets 的 map 字段,如果 subnet 名字不在 ipam.Subnets 的 map 中,则调用 NewSubnet 实例化,加入到 ipam.Subnets 的 map 中。函数更新 ipam 缓存的 map 信息,包括子网,保留 IP,freeIP 列表, pod 到 mac 的 map。实现在 pkg/ipam/ipam.go 中,
3.1.4 同一个 VPC 下的子网不能冲突,策略路由表 ID 也不能相同
3.1.5 ovnClient.LogicalSwitchExists 调用命令 “ovn-nbctl --format=csv --data=bare --no-heading --columns=name find logical_switch external_ids:vendor=kube-ovn” 查询该子网 Logical Switch 是否存在,如果不存在则创建,存在更新。ovnClient.AddLbToLogicalSwitch 添加到 load_balancer 中。
_uuid : b16e89f6-aa51-4f88-9c79-69e26951e42e
acls : []
dns_records : []
external_ids : {vendor=kube-ovn}
forwarding_groups : []
load_balancer : [18fb75e2-d609-402c-8966-e0b9b7035ba5, 30acacc0-462b-48f4-9125-8b0a71ed11ce, 4eef6413-5e49-4f55-b13f-59e5a0c40a17, 58dbe888-6d40-4250-a06d-86be6bf7d6dc]
name : net1
other_config : {exclude_ips="10.0.1.1", gateway="10.0.1.1", subnet="10.0.1.0/24"}
ports : [32789ebf-2ff9-433e-bea9-101deabde81f, 81488b05-fc43-4908-80e2-3927f6be3113, b0f5fdf5-0f51-48ce-a27a-65cafb9a976b]
qos_rules : []
3.1.6 reconcileSubnet 函数
reconcileNamespaces 主要是在 namespace 配置中添加注解,扔到 namespace 队列进行处理。
reconcileGateway 函数调整网关,如果 subnet.spec.underlaygateway 设置为 true,指示使用直接使用 underlay 网络网关,而不是 ovs 虚拟网关。则 deleteStaticRoute 删除静态路由,DeleteLogicalSwitchPort 和 DeleteLogicalRouterPort 删除逻辑的网关。 如果 subnet.spec.underlaygateway 设置为 false,网关类型为 distributed,待分析TODO
reconcileVlan,如果子网的 vlan 不为空,则调用 addLocalnet 执行命令 ovn-nbctl --may-exist lsp-add ${logical_switch} ${localnet.subnet1} -- lsp-set-address ${localnet.subnet1} unknown -- lsp-set-type ${localnet.subnet1} localnet -- lsp-set-options ${localnet.subnet1} network_name=${net1} -- set logical_switch_port ${localnet.subnet1} external_ids:vendor=kube-ovn -- set logical_siwtch_port ${localnet.subnet1} tag=${vlanID},涉及 ovn 北向数据库表 logical_switch_port
_uuid : f91da389-801a-45bf-8329-19ac826ab6c0
addresses : [unknown]
dhcpv4_options : []
dhcpv6_options : []
dynamic_addresses : []
enabled : []
external_ids : {vendor=kube-ovn}
ha_chassis_group : []
name : localnet.subnet1
options : {network_name=net1}
parent_name : []
port_security : []
tag : 1000
tag_request : []
type : localnet
up : false
3.1.7 对 subnet.spec.private 处理 true/false, 如果为私有则 SetPrivateLogicalSwitch 函数
将丢弃所有入口流量,除了允许的子网。如果公有,则删除 acl 规则。
3.1.8 更新子网所属的 VPC 状态,扔进 updateVpcStatusQueue 队列处理
3.1.9 如果子网设置 vlan,vlan 的 status 没有包含 subnet 则更新 vlan
spec:
id: 1000
provider: net1
status:
subnets:
- subnet1
总结:
涉及的 ovn 北向数据库包括,Logical_Switch,Logical_switch_port,acl
2. vlan 处理
apiVersion: kubeovn.io/v1
kind: Vlan
metadata:
name: vlan1
spec:
id: 1000
provider: net1
包括 runAddVlanWorker,runUpdateVlanWorker,runDelVlanWorker
2.1 runAddVlanWorker 函数
如果 vlan.spec.provider 未设置,则设置更新为默认的 ovn,如果 vlan 的 status 未包含拥有同样 vlan 的子网,则更新 vlan 的 status
spec:
id: 1000
provider: net1
status:
subnets:
- subnet1
更新 provider-network 资源的 staus
spec:
customInterfaces:
- interface: enp1s0
nodes:
- node1
defaultInterface: eth0
excludeNodes:
- node2
status:
conditions:
- lastTransitionTime: "2021-08-10T09:35:01Z"
lastUpdateTime: "2021-08-10T09:35:01Z"
node: node1
reason: InitOVSBridgeSucceeded
status: "True"
type: Ready
readyNodes:
- node1
vlans:
- vlan1