kube-ovn-controller 逻辑职责是翻译 kubernetes 网络概念到 OVN,可以理解为 kube-ovn 的控制面功能,通过 kube-apiserver watch 所有网络相关事件,包括 Pod creation/deletion, Service/Endpoint modification, Networkpolicy changes 等等。然后翻译转为 OVN 逻辑网络的修改。也 watch kube-ovn 添加的 CRD,比如 VPC Subnet Vlan IP 等
本文分析 network 策略,service,endpoint 三个控制器的源码实现
1. network pllicy 网络策略处理
包括 runUpdateNpWorker 和 runDeleteNpWorker 两种处理
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: test-network-policy
namespace: default
spec:
podSelector:
matchLabels:
role: db
policyTypes:
- Ingress
- Egress
ingress:
- from:
- ipBlock:
cidr: 172.17.0.0/16
except:
- 172.17.1.0/24
- namespaceSelector:
matchLabels:
project: myproject
- podSelector:
matchLabels:
role: frontend
ports:
- protocol: TCP
port: 6379
egress:
- to:
- ipBlock:
cidr: 10.0.0.0/24
ports:
- protocol: TCP
port: 5978
1.1 handleUpdateNp
ovnClient.DeletePortGroup 调用命令 ovn-nbctl get port_group node.node1 _uuid 查询是否存在,存在则调用 ovn-nbctl pg-del ${name},删除存在的 port group 来更新 acl 规则,acl 用来设置访问控制列表,并且只能应用在逻辑交换机或者port group上,不能应用在逻辑路由器上。 参数包括优先级,方向,匹配域和动作。注意: 只在 acl table 添加规则是没用的,还需要将其应用到逻辑交换机或者 port group。
ovnClient.CreatePortGroup 调用命令 ovn-nbctl --data=bare --no-heading --columns=_uuid find port_group name=allow.all.ingress.default 查询,调用命令 ovn-nbctl pg-add ${name} -- set port_group ${name} external_ids:np=${namespace}/${networkpolicy_name} 创建 port_group
fetchSelectedPorts 根据设置的 podSelector 选择器选择所有标签匹配的 pod 列表
SetPortsToPortGroup 调用命令 ovn-nbctl clear port_group ${name} ports pg-set-ports ${name} ${port列表}
_uuid : dca911e3-23bd-4d18-93b2-38f3be02beab
acls : [2ef5eeb0-0298-4d73-9ec5-89f53fed3019, 45af5469-7e51-4163-8c5a-120f5b9c21f3, 784e4419-a112-4fa9-96bd-4f2ffc8a7655, 83cc0b42-27a5-4274-959d-452757c6869a, 88a129e6-8a45-4577-a394-3b1c6bc1a9e8, 8bee9705-304b-4b4b-aec8-022cb99456be]
external_ids : {np="default/test-network-policy"}
name : test.network.policy.default
ports : []
1.1.1 如果存在 ingress 规则
a. 先处理 ipBlock 这模块,如果 ingress 的 from 未设置则允许设置 0.0.0.0/0,包含 from 则取出允许和拒绝的网段
ovnClient.CreateAddressSet 调用命令 ovn-nbctl --data=bare --no-heading --columns=_uuid find address_set name=allow.all.ingress.default.ingress.allow.IPv4.0 查询。调用命令创建 ovn-nbctl create address_set name=${name} external_ids:np=${namespace}/${networkpolicy名字}/方向
_uuid : d32700a9-49c8-43e2-819f-fde4f13ad632
addresses : ["172.17.0.0/16"]
external_ids : {np="default/test-network-policy/ingress"}
name : test.network.policy.default.ingress.allow.IPv4.0
同样,设置拒绝的的 address_set
b. 如果设置了 from 中的允许和拒绝的内容,则调用 ovnClient.CreateIngressACL 使用命令 acl-add 添加 acl 规则
_uuid : 88a129e6-8a45-4577-a394-3b1c6bc1a9e8
action : drop
direction : from-lport
external_ids : {}
log : true
match : "ip4.src == $test.network.policy.default_ip4"
meter : []
name : "default/test-network-policy"
priority : 2000
severity : warning
c. 如果未设置 ingress,创建 address_set 和 ingress acl 规则
_uuid : 12a2caa5-00f0-447f-87af-690f845e6d77
addresses : []
external_ids : {np="default/allow-all-ingress/ingress"}
name : allow.all.ingress.default.ingress.allow.IPv4.all_uuid : d853e287-dd01-4fc2-b4dd-edc6fb0a58bf
action : drop
direction : to-lport
external_ids : {}
log : true
match : "ip4.dst == $allow.all.ingress.default_ip4"
meter : []
name : "default/allow-all-ingress"
priority : 2000
severity : warning
d. 如果未设置 ingress 内容,则删除所有相关的 acl 方向出口,以及所有其相关的 address_set
1.1.2 如果存在 egress 规则
这里就不详解了,跟 ingress 处理类似
1.1.3 创建网关 ACL 规则
创建 subnet 网关的 ACL 规则,包括 ingress 和 egress 两个方向
_uuid : 3808acb1-b9b1-43f6-ac1a-4f4240879e82
action : allow-related
direction : from-lport
external_ids : {}
log : false
match : "ip4.dst == 10.16.0.1"
meter : []
name : []
priority : 2001
severity : []_uuid : d48d27e3-fdb8-439c-99d9-e29c75fae8f0
action : allow-related
direction : to-lport
external_ids : {}
log : false
match : "ip4.src == 10.16.0.1"
meter : []
name : []
priority : 2001
severity : []
2. Service 处理
包括 runUpdateServiceWorker 和 runDeleteServiceWorker
2.1 runUpdateServiceWorker
这边不处理 Spec.ClusterIP 为空或者 service 类型为 None 的,service 的注解如果未设置 ovn.kubernetes.io/vpc 则使用默认 vpc,如果 SessionAffinity 设置未 ClientIP,会话保持,则使用会话的负载均衡
tcpLb, udpLb := vpc.Status.TcpLoadBalancer, vpc.Status.UdpLoadBalancer
oTcpLb, oUdpLb := vpc.Status.TcpSessionLoadBalancer, vpc.Status.UdpSessionLoadBalancer
if svc.Spec.SessionAffinity == v1.ServiceAffinityClientIP {
tcpLb, udpLb = vpc.Status.TcpSessionLoadBalancer, vpc.Status.UdpSessionLoadBalancer
oTcpLb, oUdpLb = vpc.Status.TcpLoadBalancer, vpc.Status.UdpLoadBalancer
}
status:
default: false
defaultLogicalSwitch: net1
router: test-vpc-1
standby: true
subnets:
- net1
tcpLoadBalancer: vpc-test-vpc-1-tcp-load
tcpSessionLoadBalancer: vpc-test-vpc-1-tcp-sess-load
udpLoadBalancer: vpc-test-vpc-1-udp-load
udpSessionLoadBalancer: vpc-test-vpc-1-udp-sess-load
ovnClient.FindLoadbalancer 调用命令 ovn-nbctl --data=bare --no-heading --columns=_uuid find load_balancer name=vpc-test-vpc-1-tcp-load 查出该 vpc 的 tcp 负载均衡的 uuid,ovnClient.GetLoadBalancerVips 调用命令 ovn-nbctl --data=bare --no-heading get load_balancer vpc-test-vpc-1-tcp-load vips 获得该下的 vip
_uuid : 18fb75e2-d609-402c-8966-e0b9b7035ba5
external_ids : {}
health_check : []
ip_port_mappings : {}
name : vpc-test-vpc-1-tcp-load
options : {}
protocol : tcp
selection_fields : []
vips : {"10.233.14.99:80"="10.0.1.2:80,10.0.1.3:80"}
新添加的 vip 不再已存在中,则 updateEndpointQueue.Add,向 Endpoint 队列添加,根据 service 标签选择器过滤出所有 pod,
3. Endpoint 处理
这里也是不处理,clusterIP 未空或者 service 类型为 none, 遍历所有 pod,如果 pod 注解为空也不处理,根据 endpoint 中的 subnet 结合 pod 的注解 找出 vpc
subsets:
- addresses:
- ip: 10.0.1.2
nodeName: node1
targetRef:
kind: Pod
name: nginx-57dd86f5cc-mgwj5
namespace: ns1
resourceVersion: "368323"
uid: 2283bc51-667b-4f0d-bedf-aa458c5e8245
- ip: 10.0.1.3
nodeName: node1
targetRef:
kind: Pod
name: nginx-57dd86f5cc-s7tk9
namespace: ns1
resourceVersion: "368317"
uid: 6cfc9daf-4637-40a9-85f7-3abdb836169a
ports:
- port: 80
protocol: TCP
则根据 service 的注解 ovn.kubernetes.io/vpc: test-vpc-1,否则设置默认 vpc,ovn-cluster
根据 service 的 ports 字段内容进行处理,遍历所有 service 的 ports,getServicePortBackends 获取后端,调用 ovnClient.CreateLoadBalancerRule 调用命令 ovn-nbctl lb-add ${lb} ${vip} ${ips} ${protocol}
总结:
service 中 clientIP 对应北向数据库中的表 load_balancer
endpoint 对应北向数据库中的表 load_balancer 的 vip
networkpolicy 对应北向数据库中的表 ACL,涉及 port_group