当前位置: 首页 > news >正文

HCIP-OpenStack组件之neutron

neutron(ovs、ovn)

OVS

OVS(Open vSwitch)是虚拟交换机,遵循SDN(Software Defined Network,软件定义网络)架构来管理的。
OVS介绍参考:https://mp.weixin.qq.com/s?__biz=MzAwMDQyOTcwOA==&mid=2247485088&idx=1&sn=f7eb3126eaa7d8c2a5056332694aea8b&chksm=9ae85d43ad9fd455f5b293c7a7fa60847b14eea18030105f2f330ce5076e7ec44eca7d30abad&cur_album_id=2470011981178322946&scene=189#wechat_redirect
在这里插入图片描述
ovs由三个组件组成:dataPath、vswitchd和ovsdb。
dataPath(opevswitch.ko):openvswitch.ko是ovs的内核模块,当openvswitch.ko模块被加载到内核时,会在网卡上注册一个钩子函数,每当网络包到达网卡时这个钩子函数就会被调用。openvswitch.ko模块在处理网络包时,会先匹配内核中能不能匹配到策略(内核流表)来处理,如果匹配到了策略,则直接在内核态根据该策略做网络包转发,这个过程全程在内核中完成,处理速度非常快,也称之为fast path(快速通道);如果内核中没有匹配到相应策略,则把数据包交给用户态的vswitchd进程处理,此时叫作slow path(慢通道)。dataPath模块可以通过ovs-dpctl命令来配置。
vswitchd:vswitchd是ovs的核心模块,它工作在用户空间(user space),负责与OpenFlow控制器、第三方软件通信。vswitchd接收到数据包时,会去匹配用户态流表,如果匹配成功则根据相关规则转发;如果匹配不成功,则会根据OpenFlow协议规范处理,把数据包上报给控制器(如果有)或者丢弃。
ovsdb:ovs数据库,存储整个ovs的配置信息,包括接口、交换内容、vlan、虚拟交换机信息等。
ovs相关术语解释:
1、Bridge:网桥,也就是交换机(不过是虚拟的,即vSwitch),一台主机中可以创建多个网桥。当数据包从网桥的某个端口进来后,网桥会根据一定的规则把该数据包转发到另外的端口,也可以修改或者丢弃报文。Bridge桥指的是虚拟交换机。
2、Port:交换机的端口,有以下几种类型:
Normal: 将物理网卡添加到bridge时它们会成为Port,类型为Normal。此时物理网卡配置ip已没有意义,它已经“退化成一根网线”只负责数据报文的进出。Normal类型的Port常用于vlan模式下多台物理主机相连的那个口,交换机的一端属于Trunk模式。
Internal: 此类型的Port,ovs会自动创建一个虚拟网卡接口(Interface),此端口收到数据都会转发给这块网卡,从网卡发出的数据也会通过Port交给ovs处理。当ovs创建一个新的Bridge时,会自动创建一个与网桥同名的Internal Port,同时也会创建一个与网桥同名的Interface。另外,Internal Port可配置IP地址,然后将其up,即可实现ovs三层网络。
Patch: 与veth pair功能类似,常用于连接两个Bridge。veth pair:两个网络虚拟端口(设备)
Tunnel: 实现overlay网络,支持GRE、vxlan、STT、Geneve和IPSec等隧道协议。Tunnel:隧道,三层
3、Interface:网卡,虚拟的(TUN/TAP)或物理的都可以。TAP:单个网络虚拟端口(设备),基于二层;TUN:基于三层。
4、Controller:控制器,ovs可以接收一个或多个OpenFlow控制器的管理,主要功能为下发流表来控制转发规则。
5、FlowTable:流表,ovs进行数据转发的核心功能,定义了端口之间的转发数据规则。每条流表规则可以分为匹配和动作两部分,“匹配”决定哪些数据将被处理,“动作”则决定了这些数据将被如何处理。
在这里插入图片描述
ens160的ip地址没有了,用的是br-ex的ip地址出去的。
在这里插入图片描述
ovs安装
1.开启一台新的linux
2.配置在线yum源(openstack那个在线yum源)

配置yum源(先把原有的备份后清空)
# cd /etc/yum.repos.d/      # rm -rf *
# cat cloud.repo [highavailability]
name=CentOS Stream 8 - HighAvailability
baseurl=https://mirrors.aliyun.com/centos/8-stream/HighAvailability/x86_64/os/
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-centosofficial
gpgcheck=1
repo_gpgcheck=0
metadata_expire=6h
countme=1
enabled=1[nfv]
name=CentOS Stream 8 - NFV
baseurl=https://mirrors.aliyun.com/centos/8-stream/NFV/x86_64/os/
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-centosofficial
gpgcheck=1
repo_gpgcheck=0
metadata_expire=6h
countme=1
enabled=1[rt]
name=CentOS Stream 8 - RT
baseurl=https://mirrors.aliyun.com/centos/8-stream/RT/x86_64/os/
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-centosofficial
gpgcheck=1
repo_gpgcheck=0
metadata_expire=6h
countme=1
enabled=1[resilientstorage]
name=CentOS Stream 8 - ResilientStorage
baseurl=https://mirrors.aliyun.com/centos/8-stream/ResilientStorage/x86_64/os/
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-centosofficial
gpgcheck=1
repo_gpgcheck=0
metadata_expire=6h
countme=1
enabled=1[extras-common]
name=CentOS Stream 8 - Extras packages
baseurl=https://mirrors.aliyun.com/centos/8-stream/extras/x86_64/extras-common/
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-SIG-Extras-SHA512
gpgcheck=1
repo_gpgcheck=0
metadata_expire=6h
countme=1
enabled=1[extras]
name=CentOS Stream  - Extras
mirrorlist=http://mirrorlist.centos.org/?release=&arch=&repo=extras&infra=
#baseurl=http://mirror.centos.org///extras//os/
baseurl=https://mirrors.aliyun.com/centos/8-stream/extras/x86_64/os/
gpgcheck=1
enabled=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-centosofficial[centos-ceph-pacific]
name=CentOS - Ceph Pacific
baseurl=https://mirrors.aliyun.com/centos/8-stream/storage/x86_64/ceph-pacific/
gpgcheck=0
enabled=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-SIG-Storage[centos-rabbitmq-38]
name=CentOS-8 - RabbitMQ 38
baseurl=https://mirrors.aliyun.com/centos/8-stream/messaging/x86_64/rabbitmq-38/
gpgcheck=1
enabled=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-SIG-Messaging[centos-nfv-openvswitch]
name=CentOS Stream 8 - NFV OpenvSwitch
baseurl=https://mirrors.aliyun.com/centos/8-stream/nfv/x86_64/openvswitch-2/
gpgcheck=1
enabled=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-SIG-NFV
module_hotfixes=1[baseos]
name=CentOS Stream 8 - BaseOS
baseurl=https://mirrors.aliyun.com/centos/8-stream/BaseOS/x86_64/os/
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-centosofficial
gpgcheck=1
repo_gpgcheck=0
metadata_expire=6h
countme=1
enabled=1[appstream]
name=CentOS Stream 8 - AppStream
baseurl=https://mirrors.aliyun.com/centos/8-stream/AppStream/x86_64/os/
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-centosofficial
gpgcheck=1
repo_gpgcheck=0
metadata_expire=6h
countme=1
enabled=1[centos-openstack-victoria]
name=CentOS 8 - OpenStack victoria
baseurl=https://mirrors.aliyun.com/centos/8-stream/cloud/x86_64/openstack-victoria/
#baseurl=https://repo.huaweicloud.com/centos/8-stream/cloud/x86_64/openstack-yoga/
gpgcheck=1
enabled=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-SIG-Cloud
module_hotfixes=1[powertools]
name=CentOS Stream 8 - PowerTools
#mirrorlist=http://mirrorlist.centos.org/?release=&arch=&repo=PowerTools&infra=
baseurl=https://mirrors.aliyun.com/centos/8-stream/PowerTools/x86_64/os/
gpgcheck=1
enabled=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-centosofficial# yum clean all  清理缓存
# yum makecache  重新建立缓存
# yum repolist all  列出yum仓库(13个)

3.安装基础包及ovs(Tab补全命令,安装bash-completion包后执行bash就行)
安装openvswitch3.1过程报错说找不到gpgkey文件就禁用gpgcheck=0再次安装就行了
yum install -y vim net-tools bash-completion centos-release-openstack-victoria.noarch tcpdump openvswitch3.1

或再单独安装yum install -y openvswitch3.1*
查看安装版本:[root@ovs ~]# ovs-vsctl --version
4.启动ovs服务
[root@ovs ~]# systemctl start openvswitch
[root@ovs ~]# systemctl enable openvswitch
[root@ovs ~]# ps -ef | grep openvswitch
[root@ovs ~]# ovs-vsctl show 查看ovs虚拟交换机信息
[root@ovs ~]# ovs-vsctl --help 求帮助 或[root@ovs ~]# man ovs-vsctl
5、创建ovs虚拟交换机
当创建一个虚拟交换机会生成一个和虚拟交换机同名的Port 和Interface,type为internal(内部的)

[root@ovs ~]# ovs-vsctl add-br br-int
[root@ovs ~]# ovs-vsctl add-br br-memeda  添加
[root@ovs ~]# ovs-vsctl del-br br-memeda  删除
[root@ovs ~]# ovs-vsctl list-br   查看
br-int
br-memeda
[root@ovs ~]# ovs-vsctl show   查询ovs虚拟交换机信息,Bridge桥指的是虚拟交换机
54c67146-9a9f-40be-8cb7-e8792879aafaBridge br-memedaPort br-memedaInterface br-memedatype: internalBridge br-intPort br-intInterface br-inttype: internalovs_version: "3.1.3"

用轻量级namespace网络命名空间模拟虚拟机
在这里插入图片描述

[root@ovs ~]# ip netns    查看网络命名空间
[root@ovs ~]# ip netns add ns1    添加网络命名空间
[root@ovs ~]# ip netns add ns2
[root@ovs ~]# ip netns
ns2
ns1

创建两个veth pair(一个veth pair有两个网络虚拟接口,veth可理解为网卡端口) 并将一端虚拟接口(veth1和veth2)连接到两个网络命名空间里面。veth pair:两个网络虚拟端口(设备)。
在这里插入图片描述

创建两个veth pair,并分别把这两个veth pair的一端放到上述两个网络命名空间
# ip link help 或# man ip link 求帮助
第一个网络命名空间配置
[root@ovs ~]# ip link add veth11 type veth peer name veth1
[root@ovs ~]# ip link set veth1 netns ns1
[root@ovs ~]# ip netns exec ns1 ip link set veth1 up
第二个网络命名空间配置
[root@ovs ~]# ip link add veth22 type veth peer name veth2
[root@ovs ~]# ip link set veth2 netns ns2
[root@ovs ~]# ip netns exec ns2 ip link set veth2 up

将另外一端虚拟接口(veth11和veth22)连接到ovs虚拟交换机上
在这里插入图片描述

[root@ovs ~]# ip link set veth11 up
[root@ovs ~]# ip link set veth22 up
[root@ovs ~]# ovs-vsctl add-port br-memeda veth11
[root@ovs ~]# ovs-vsctl add-port br-memeda veth22
[root@ovs ~]# ovs-vsctl show  发现br-memeda虚拟交换机多了2个Port(Port veth22、Port veth11)
3b79f2e1-f433-4015-905e-8945dcada530Bridge br-memedaPort br-memedaInterface br-memedatype: internalPort veth22Interface veth22Port veth11Interface veth11Bridge br-intPort br-intInterface br-inttype: internalovs_version: "3.1.3"

为两个网络命名空间手动设置ip地址
在这里插入图片描述

[root@ovs ~]# ip netns exec ns1 ip addr add 1.1.1.1/24 dev veth1
[root@ovs ~]# ip netns exec ns1 ip a
1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN group default qlen 1000link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
7: veth1@if8: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group d                                                                        efault qlen 1000link/ether fe:f9:3b:cb:9b:c5 brd ff:ff:ff:ff:ff:ff link-netnsid 0inet 1.1.1.1/24 scope global veth1valid_lft forever preferred_lft foreverinet6 fe80::fcf9:3bff:fecb:9bc5/64 scope linkvalid_lft forever preferred_lft forever
[root@ovs ~]# ip netns exec ns2 ip addr add 1.1.1.2/24 dev veth2
[root@ovs ~]# ip netns exec ns2 ip a
1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN group default qlen 1000link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
9: veth2@if10: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group                                                                         default qlen 1000link/ether 0a:e3:ac:a8:f3:bc brd ff:ff:ff:ff:ff:ff link-netnsid 0inet 1.1.1.2/24 scope global veth2valid_lft forever preferred_lft foreverinet6 fe80::8e3:acff:fea8:f3bc/64 scope linkvalid_lft forever preferred_lft forever
两个网络命名空间测试连通性
[root@ovs ~]# ip netns exec ns1 ping -c 3 1.1.1.2
PING 1.1.1.2 (1.1.1.2) 56(84) bytes of data.
64 bytes from 1.1.1.2: icmp_seq=1 ttl=64 time=2.98 ms
64 bytes from 1.1.1.2: icmp_seq=2 ttl=64 time=0.167 ms
64 bytes from 1.1.1.2: icmp_seq=3 ttl=64 time=0.081 ms--- 1.1.1.2 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2065ms
rtt min/avg/max/mdev = 0.081/1.075/2.979/1.346 ms
[root@ovs ~]# ip netns exec ns2 ping -c 3 1.1.1.1
PING 1.1.1.1 (1.1.1.1) 56(84) bytes of data.
64 bytes from 1.1.1.1: icmp_seq=1 ttl=64 time=0.923 ms
64 bytes from 1.1.1.1: icmp_seq=2 ttl=64 time=0.084 ms
64 bytes from 1.1.1.1: icmp_seq=3 ttl=64 time=0.091 ms--- 1.1.1.1 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2007ms
rtt min/avg/max/mdev = 0.084/0.366/0.923/0.393 ms

vlan虚拟的本地局域网,vlan隔离为了减少网络阻塞和数据包安全
ovs虚拟交换机能和物理交换机一样定义vlan,一个vlan10(tag10),一个vlan20(tag20),把插在ovs交换机上的两个虚拟网络设备对端口分别打上不同的tag(默认是0),也就是配置到不同的vlan里,再验证网络连通性。
在这里插入图片描述

[root@ovs ~]# ovs-vsctl set port veth11 tag=10
[root@ovs ~]# ovs-vsctl set port veth22 tag=20
[root@ovs ~]# ovs-vsctl show  发现br-memeda虚拟交换机的Port veth22和Port veth11下面多了tag标签
3b79f2e1-f433-4015-905e-8945dcada530Bridge br-memedaPort br-memedaInterface br-memedatype: internalPort veth22tag: 20Interface veth22Port veth11tag: 10Interface veth11Bridge br-intPort br-intInterface br-inttype: internalovs_version: "3.1.3"

添加不同vlan(tag标签)后ping不通,需借助路由或物理三层交换机

[root@ovs ~]# ip netns exec ns1 ping -c 3 1.1.1.2
PING 1.1.1.2 (1.1.1.2) 56(84) bytes of data.--- 1.1.1.2 ping statistics ---
3 packets transmitted, 0 received, 100% packet loss, time 2064ms

在这里插入图片描述

[root@ovs ~]# ovs-vsctl set port veth22 tag=10  把veth22也改成tag=10就相当于同一个vlan二层互通了
[root@ovs ~]# ovs-vsctl show
3b79f2e1-f433-4015-905e-8945dcada530Bridge br-memedaPort br-memedaInterface br-memedatype: internalPort veth22tag: 10Interface veth22Port veth11tag: 10Interface veth11Bridge br-intPort br-intInterface br-inttype: internalovs_version: "3.1.3"
[root@ovs ~]# ip netns exec ns1 ping -c 3 1.1.1.2   同一个vlan(tag标签)能ping通进行二层通信
PING 1.1.1.2 (1.1.1.2) 56(84) bytes of data.
64 bytes from 1.1.1.2: icmp_seq=1 ttl=64 time=1.43 ms
64 bytes from 1.1.1.2: icmp_seq=2 ttl=64 time=0.093 ms
64 bytes from 1.1.1.2: icmp_seq=3 ttl=64 time=0.086 ms--- 1.1.1.2 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2051ms
rtt min/avg/max/mdev = 0.086/0.535/1.426/0.630 ms

FlowTable:流表,ovs进行数据转发的核心功能,定义了端口之间的转发数据规则。每条流表规则可以分为匹配和动作两部分,“匹配”决定哪些数据将被处理,“动作”则决定了这些数据将被如何处理。
流量走向,添加流表,针对流量进口添加规则。
在这里插入图片描述
在这里插入图片描述

查看ovs默认的流表
[root@ovs ~]# ovs-ofctl dump-flows br-memeda   查看虚拟交换机的流规则cookie=0x0, duration=2161.884s, table=0, n_packets=49, n_bytes=3682, priority=0 action                                                                        s=NORMAL
此时ovs就类似于传统交换机,我们给ovs交换机添加一条优先级为2(数字越大优先级越高,高于默认表项的0优先级)的流表项,把veth11进来的请求都drop掉,发现ns1不能ping通ns2。
[root@ovs ~]# ovs-ofctl add-flow br-memeda "priority=2,in_port=veth11,actions=drop"  添加流规则
[root@ovs ~]# ovs-ofctl dump-flows br-memedacookie=0x0, duration=2.578s, table=0, n_packets=0, n_bytes=0, priority=2,in_port=veth11 actions=dropcookie=0x0, duration=2217.329s, table=0, n_packets=49, n_bytes=3682, priority=0 actions=NORMAL
[root@ovs ~]# ip netns exec ns1 ping -c 3 1.1.1.2
PING 1.1.1.2 (1.1.1.2) 56(84) bytes of data.--- 1.1.1.2 ping statistics ---
3 packets transmitted, 0 received, 100% packet loss, time 2076ms
删除刚添加的表项,ns1与ns2又能正常通信
[root@ovs ~]# ovs-ofctl del-flows br-memeda "in_port=veth11"  删除刚添加的流规则就互通了
[root@ovs ~]# ip netns exec ns1 ping -c 3 1.1.1.2
PING 1.1.1.2 (1.1.1.2) 56(84) bytes of data.
64 bytes from 1.1.1.2: icmp_seq=1 ttl=64 time=0.766 ms
64 bytes from 1.1.1.2: icmp_seq=2 ttl=64 time=0.096 ms
64 bytes from 1.1.1.2: icmp_seq=3 ttl=64 time=0.088 ms--- 1.1.1.2 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2043ms
rtt min/avg/max/mdev = 0.088/0.316/0.766/0.318 ms
[root@ovs ~]# ovs-ofctl dump-flows br-memedacookie=0x0, duration=2315.744s, table=0, n_packets=59, n_bytes=4438, priority=0 action                                                                        s=NORMAL

OVN

OVN建立在OVS之上的,遵循SDN(Software Defined Network,软件定义网络)架构来管理的,用软件将控制面和转发面分离,OVN做控制面,OVS做转发面。
ovn是建立在ovs之上的,ovn必须有底层的ovs,ovs可理解为二层交换机,ovn可理解为三层交换机。
OVS介绍参考:https://mp.weixin.qq.com/s?__biz=MzAwMDQyOTcwOA==&mid=2247485357&idx=1&sn=1e80c02232e2bdafec8dcf71dd4fa265&chksm=9ae85c4ead9fd5584e488f7f7f5b7d2ad4bd86c18cb780d057653b23eac4001dabe8f9b6d98a&cur_album_id=2470011981178322946&scene=189#wechat_redirect
单纯的ovs在云计算领域还存在着一些问题,例如:
1、ovs只能做二层转发,没有三层的能力,无法在ovs上进行路由配置等操作;
2、ovs没有高可用配置;
3、在虚拟化领域vm从一台物理机迁移到另一台物理机,以及容器领域container从一个节点迁移到另一个节点都是非常常见的场景,而单纯的ovs的配置只适用于当前节点。当发生上述迁移过程时,新的节点因对应的ovs没有相关配置,会导致迁移过来的vm或者container无法正常运作。
针对这些问题,出现了ovn(Open Virtual Network),ovn提供的功能包括:
1、分布式虚拟路由器(distributed virtual routers)
2、分布式虚拟交换机(distributed logical switches)
3、访问控制列表(ACL)
4、DHCP
5、DNS server
在openstack里面,创建一个网络,就相当于创建了一个逻辑虚拟交换机,这个逻辑交换机(网络)信息会被保存到北向数据库里面。openstack创建一个网络,会以逻辑交换机(switch)的形式保存到北向数据库。
在这里插入图片描述
在这里插入图片描述
ovn官网对ovn的逻辑架构如下所示:

                                    CMS||+-----------|-----------+|           |           ||     OVN/CMS Plugin    ||           |           ||           |           ||   OVN Northbound DB   ||           |           ||           |           ||       ovn-northd      ||           |           |+-----------|-----------+||+-------------------+| OVN Southbound DB |+-------------------+||+------------------+------------------+|                  |                  |HV 1          |                  |    HV n          |+---------------|---------------+  .  +---------------|---------------+|               |               |  .  |               |               ||        ovn-controller         |  .  |        ovn-controller         ||         |          |          |  .  |         |          |          ||         |          |          |     |         |          |          ||  ovs-vswitchd   ovsdb-server  |     |  ovs-vswitchd   ovsdb-server  ||                               |     |                               |+-------------------------------+     +-------------------------------+

ovn根据功能可以把节点分为两类:
central: 可以看做中心节点,central节点组件包括OVN/CMS plugin、OVN Northbound DB、ovn-northd、OVN Southbound DB。
hypervisor(hv): 可以看做工作节点,hypervisor节点组件包括ovn-controller、ovs-vswitchd、ovsdb-server。
central节点相关组件和hypervisor组件运行在同一个物理节点上。
相关组件的功能如下:
1、CMS: 云管软件(Cloud Management Software),例如openstack(ovn最初就是设计给openstack用的)。
2、OVN/CMS plugin: 云管软件插件,例如openstack的neutron plugin。它的作用是将逻辑网络配置转换成OVN理解的数据,并写到北向数据库(OVN Northbound DB)中。
3、OVN Northbound DB: ovn北向数据库,保存CMS plugin下发的配置,它有两个客户端CMS plugin和ovn-northd。通过ovn-nbctl命令直接操作它。北向数据库保存逻辑网络信息(交换机和路由器等)
4、ovn-northd: 北向进程将OVN Northbound DB中的数据进行转换并保存到OVN Southbound DB。所有信息经过北向数据库通过ovn-northd北向进程和南向数据库互通。
5、OVN Southbound DB: ovn南向数据库,它也有两个客户端: 上面的ovn-northd和下面的运行在每个hypervisor上的ovn-controller。通过ovn-sbctl命令直接操作它。南向数据库保存各个节点的物理网络信息。
6、ovn-controller: 相当于OVN在每个hypervisor上的agent(代理)。北向它连接到OVN Southbound Database学习最新的配置转换成openflow流表,南向它连接到ovs-vswitchd下发转换后的流表,同时也连接到ovsdb-server获取它需要的配置信息。
7、ovs-vswitchd和ovs-dbserver: ovs用户态的两个进程。
每个节点都有个ovn-controller控制器,这个ovn-controller控制器是管理ovs(ovs-vswitchd、ovsdb-server)的,ovn-controller对接到南向数据库,经过ovn-northd北向进程和北向数据库互通,之后和openstack互通。
南向数据库保存物理网络状态信息,北向数据库保存逻辑网络状态信息。
在这里插入图片描述
克隆出两台虚拟机,安装ovs、ovn

CentOS Stream 8 版本systemctl stop firewalld.service 
systemctl disable firewalld.service
setenforce 0
sed -i 's/SELINUX=enforcing/SELINUX=disabled/g' /etc/selinux/config
mkdir /etc/yum.repos.d/bak
mv /etc/yum.repos.d/*.repo /etc/yum.repos.d/bak/cat <<EOF > /etc/yum.repos.d/cloudcs.repo
[ceph]
name=ceph
baseurl=https://mirrors.aliyun.com/ceph/rpm-18.1.1/el8/x86_64/
gpgkey=https://mirrors.aliyun.com/ceph/keys/release.asc
gpgcheck=1
enabled=1[ceph-noarch]
name=ceph-noarch
baseurl=https://mirrors.aliyun.com/ceph/rpm-18.1.1/el8/noarch/
gpgcheck=1
gpgkey=https://mirrors.aliyun.com/ceph/keys/release.asc
enabled=1[ceph-SRPMS]
name=SRPMS
baseurl=https://mirrors.aliyun.com/ceph/rpm-18.1.1/el8/SRPMS/
gpgcheck=1
gpgkey=https://mirrors.aliyun.com/ceph/keys/release.asc
enabled=1[highavailability]
name=CentOS Stream 8 - HighAvailability
baseurl=https://mirrors.aliyun.com/centos/8-stream/HighAvailability/x86_64/os/
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-centosofficial
gpgcheck=1
repo_gpgcheck=0
metadata_expire=6h
countme=1
enabled=1[nfv]
name=CentOS Stream 8 - NFV
baseurl=https://mirrors.aliyun.com/centos/8-stream/NFV/x86_64/os/
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-centosofficial
gpgcheck=1
repo_gpgcheck=0
metadata_expire=6h
countme=1
enabled=1[rt]
name=CentOS Stream 8 - RT
baseurl=https://mirrors.aliyun.com/centos/8-stream/RT/x86_64/os/
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-centosofficial
gpgcheck=1
repo_gpgcheck=0
metadata_expire=6h
countme=1
enabled=1[resilientstorage]
name=CentOS Stream 8 - ResilientStorage
baseurl=https://mirrors.aliyun.com/centos/8-stream/ResilientStorage/x86_64/os/
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-centosofficial
gpgcheck=1
repo_gpgcheck=0
metadata_expire=6h
countme=1
enabled=1[extras-common]
name=CentOS Stream 8 - Extras packages
baseurl=https://mirrors.aliyun.com/centos/8-stream/extras/x86_64/extras-common/
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-SIG-Extras-SHA512
gpgcheck=1
repo_gpgcheck=0
metadata_expire=6h
countme=1
enabled=1[extras]
name=CentOS Stream $releasever - Extras
mirrorlist=http://mirrorlist.centos.org/?release=$stream&arch=$basearch&repo=extras&infra=$infra
#baseurl=http://mirror.centos.org/$contentdir/$stream/extras/$basearch/os/
baseurl=https://mirrors.aliyun.com/centos/8-stream/extras/x86_64/os/
gpgcheck=1
enabled=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-centosofficial[centos-ceph-pacific]
name=CentOS - Ceph Pacific
baseurl=https://mirrors.aliyun.com/centos/8-stream/storage/x86_64/ceph-pacific/
gpgcheck=0
enabled=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-SIG-Storage[centos-rabbitmq-38]
name=CentOS-8 - RabbitMQ 38
baseurl=https://mirrors.aliyun.com/centos/8-stream/messaging/x86_64/rabbitmq-38/
gpgcheck=1
enabled=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-SIG-Messaging[centos-nfv-openvswitch]
name=CentOS Stream 8 - NFV OpenvSwitch
baseurl=https://mirrors.aliyun.com/centos/8-stream/nfv/x86_64/openvswitch-2/
gpgcheck=1
enabled=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-SIG-NFV
module_hotfixes=1[baseos]
name=CentOS Stream 8 - BaseOS
baseurl=https://mirrors.aliyun.com/centos/8-stream/BaseOS/x86_64/os/
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-centosofficial
gpgcheck=1
repo_gpgcheck=0
metadata_expire=6h
countme=1
enabled=1[appstream]
name=CentOS Stream 8 - AppStream
baseurl=https://mirrors.aliyun.com/centos/8-stream/AppStream/x86_64/os/
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-centosofficial
gpgcheck=1
repo_gpgcheck=0
metadata_expire=6h
countme=1
enabled=1[centos-openstack-victoria]
name=CentOS 8 - OpenStack victoria
baseurl=https://mirrors.aliyun.com/centos/8-stream/cloud/x86_64/openstack-victoria/
#baseurl=https://repo.huaweicloud.com/centos/8-stream/cloud/x86_64/openstack-yoga/
gpgcheck=1
enabled=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-SIG-Cloud
module_hotfixes=1[powertools]
name=CentOS Stream 8 - PowerTools
#mirrorlist=http://mirrorlist.centos.org/?release=$stream&arch=$basearch&repo=PowerTools&infra=$infra
baseurl=https://mirrors.aliyun.com/centos/8-stream/PowerTools/x86_64/os/
gpgcheck=1
enabled=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-centosofficial
EOFyum install -y vim net-tools bash-completion git tcpdump autoconf automake libtool make python3 centos-release-openstack-victoria.noarch
yum install -y openvswitch3.1*
yum install -y ovn22.12*
查看安装版本来检查ovn是否安装成功,# ovn-appctl --version
echo 'export PATH=$PATH:/usr/share/ovn/scripts:/usr/share/openvswitch/scripts' >> /etc/profile
source /etc/profile  重新读取配置文件让配置文件立即生效

在这里插入图片描述
central相关组件启动:把node1作为central节点,安装central必需的三个组件:OVN Northbound DB、ovn-northd、OVN Southbound DB。
在控制节点启动central,只用在一个控制节点上启动即可(node1或node2上开启都行,这里是在node1开启),central只需要一套即可。

ovn-ctl start_northd命令会自动启动北桥数据库、ovn-northd、南桥数据库三个服务
[root@node1 ~]# ovn-ctl start_northd
/etc/ovn/ovnnb_db.db does not exist ... (warning).
Creating empty database /etc/ovn/ovnnb_db.db               [  OK  ]
Starting ovsdb-nb                                          [  OK  ]
/etc/ovn/ovnsb_db.db does not exist ... (warning).
Creating empty database /etc/ovn/ovnsb_db.db               [  OK  ]
Starting ovsdb-sb                                          [  OK  ]
Starting ovn-northd                                        [  OK  ][root@node1 ~]# ps -ef | grep ovn
root       34102   34101  0 21:02 ?        00:00:00 ovsdb-server -vconsole:off -vfile:info --log-file=/var/log/ovn/ovsdb-server-nb.log --remote=punix:/var/run ovn/ovnnb_db.sock --pidfile=/var/run/ovn/ovnnb_db.pid --unixctl=/var/run/ovn/ovnnb_db.ctl --detach --monitor --remote=db:OVN_Northbound,NB_Global,connections --private-key=db:OVN_Northbound,SSL,private_key --certificate=db:OVN_Northbound,SSL,certificate --ca-cert=db:OVN_Northbound,SSL,ca_cert --ssl-protocols=db:OVN_Northbound,SSL,ssl_protocols --ssl-ciphers=db:OVN_Northbound,SSL,ssl_ciphers /etc/ovn/ovnnb_db.db
root       34118   34117  0 21:02 ?        00:00:00 ovsdb-server -vconsole:off -vfile:info --log-file=/var/log/ovn/ovsdb-server-sb.log --remote=punix:/var/run ovn/ovnsb_db.sock --pidfile=/var/run/ovn/ovnsb_db.pid --unixctl=/var/run/ovn/ovnsb_db.ctl --detach --monitor --remote=db:OVN_Southbound,SB_Global,connections --private-key=db:OVN_Southbound,SSL,private_key --certificate=db:OVN_Southbound,SSL,certificate --ca-cert=db:OVN_Southbound,SSL,ca_cert --ssl-protocols=db:OVN_Southbound,SSL,ssl_protocols --ssl-ciphers=db:OVN_Southbound,SSL,ssl_ciphers /etc/ovn/ovnsb_db.db
root       34128       1  0 21:02 ?        00:00:00 ovn-northd: monitoring pid 34129 (healthy)
root       34129   34128  0 21:02 ?        00:00:00 ovn-northd -vconsole:emer -vsyslog:err -vfile:info --ovnnb-db=unix:/var/run/ovn/ovnnb_db.sock --ovnsb-db=unix:/var/run/ovn/ovnsb_db.sock --no-chdir --log-file=/var/log/ovn/ovn-northd.log --pidfile=/var/run/ovn/ovn-northd.pid --detach --monitor
root       34302   34259  0 21:07 pts/0    00:00:00 grep --color=auto ovn

在这里插入图片描述
hypervisor相关组件启动:hypervisor节点包含三个组件:ovn-controller、ovs-vswitchd和ovsdb-server。
启动hypervisor(hv)相关组件:node1和node2两台节点上都要启动,首先启动两个节点上的 ovs-vswitchd 和 ovsdb-server

[root@node1 ~]# ovs-ctl start --system-id=random
/etc/openvswitch/conf.db does not exist ... (warning).
Creating empty database /etc/openvswitch/conf.db           [  OK  ]
Starting ovsdb-server                                      [  OK  ]
Configuring Open vSwitch system IDs                        [  OK  ]
Inserting openvswitch module                               [  OK  ]
Starting ovs-vswitchd                                      [  OK  ]
Enabling remote OVSDB managers                             [  OK  ][root@node2 ~]# ovs-ctl start --system-id=random
/etc/openvswitch/conf.db does not exist ... (warning).
Creating empty database /etc/openvswitch/conf.db           [  OK  ]
Starting ovsdb-server                                      [  OK  ]
Configuring Open vSwitch system IDs                        [  OK  ]
Inserting openvswitch module                               [  OK  ]
Starting ovs-vswitchd                                      [  OK  ]
Enabling remote OVSDB managers                             [  OK  ]

在这里插入图片描述
两个节点分别启动ovn-controller

[root@node1 ~]# ovn-ctl start_controller
Starting ovn-controller                                    [  OK  ]
[root@node1 ~]# ovs-vsctl show       ovn-controler启动后会自动创建br-int网桥
ed157e0c-cac3-46b9-830c-f2d710b475d5Bridge br-intfail_mode: securedatapath_type: systemPort br-intInterface br-inttype: internalovs_version: "3.1.3"[root@node2 ~]# ovn-ctl start_controller
Starting ovn-controller                                    [  OK  ]
[root@node2 ~]# ovs-vsctl show      ovn-controler启动后会自动创建br-int网桥
f6669675-b42d-47de-be95-b26bf6d1e069Bridge br-intfail_mode: securedatapath_type: systemPort br-intInterface br-inttype: internalovs_version: "3.1.3"

在这里插入图片描述
可以看出此时hypervisor并没有和central关联起来(也就是ovn-controller没有和南向数据库连接)。可以在node1上验证:[root@node1 ~]# ovn-nbctl show
hypervisor连接central,开放南北数据库端口:

ovn-northd之所以能连上南向数据和北向数据库,是因为它们部署在同一台机器上,通过unix sock连接
central节点开放北向数据库端口6441,该端口主要给CMS plugins连接使用
central节点开放南向数据库端口6442,该端口给ovn-controller连接
[root@node1 ~]# ovn-nbctl set-connection ptcp:6641:10.1.1.41
[root@node1 ~]# ovn-sbctl set-connection ptcp:6642:10.1.1.41
[root@node1 ~]# netstat -tulnp |grep 664
tcp        0      0 10.1.1.41:6641          0.0.0.0:*               LISTEN      34102/ovsdb-server
tcp        0      0 10.1.1.41:6642          0.0.0.0:*               LISTEN      34118/ovsdb-server
node1上ovn-controller连接南向数据库
ovn-remote:指定南向数据库连接地址
ovn-encap-ip:指定ovs/controller本地ip
ovn-encap-type:指定隧道协议,这里用的是geneve
system-id:节点标识
[root@node1 ~]# ovs-vsctl set Open_vSwitch . external-ids:ovn-remote="tcp:10.1.1.41:6642" external-ids:ovn-encap-ip="10.1.1.41" external-ids:ovn-encap-type=geneve external-ids:system-id=node1node2上ovn-controller连接南向数据库
[root@node1 ~]# ovs-vsctl set Open_vSwitch . external-ids:ovn-remote="tcp:10.1.1.41:6642" external-ids:ovn-encap-ip="10.1.1.42" external-ids:ovn-encap-type=geneve external-ids:system-id=node2在node1查看南向数据库信息
[root@node1 ~]# ovn-sbctl show
Chassis node2hostname: node2Encap geneveip: "10.1.1.42"options: {csum="true"}
Chassis node1hostname: node1Encap geneveip: "10.1.1.41"options: {csum="true"}

在这里插入图片描述
以上的逻辑架构是站在底层组件和服务的角度来看的。
接下来换一种角度,站在逻辑网络的角度来看。
在这里插入图片描述
geneve隧道:ovn-controller连接南向数据库时,指定了external-ids:ovn-encap-type=geneve参数,此时看看两个节点上的ovs信息如下,会发现两个节点上都有一个ovn创建的ovs交换机br-int,而且br-int交换机上添加的节点port/interface类型都为geneve

[root@node1 ~]# ovs-vsctl show    node1上查看ovs信息
ed157e0c-cac3-46b9-830c-f2d710b475d5Bridge br-intfail_mode: securedatapath_type: systemPort br-intInterface br-inttype: internalPort ovn-node2-0Interface ovn-node2-0type: geneveoptions: {csum="true", key=flow, remote_ip="10.1.1.42"}ovs_version: "3.1.3"[root@node2 ~]# ovs-vsctl show    node2上查看ovs信息
f6669675-b42d-47de-be95-b26bf6d1e069Bridge br-intfail_mode: securedatapath_type: systemPort ovn-node1-0Interface ovn-node1-0type: geneveoptions: {csum="true", key=flow, remote_ip="10.1.1.41"}Port br-intInterface br-inttype: internalovs_version: "3.1.3"
[root@node1 ~]# ip link | grep gene  查看geneve隧道link
5: genev_sys_6081: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 65000 qdisc noqueue master ovs-system state UNKNOWN mode DEFAULT group default qlen 1000
查看geneve隧道link详情,从dstport 6081可以看出geneve隧道udp端口是6081
[root@node1 ~]# ip -d link show genev_sys_6081  
5: genev_sys_6081: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 65000 qdisc noqueue master ovs-system state UNKNOWN mode DEFAULT group default qlen 1000link/ether 6a:e3:ff:a5:cc:d6 brd ff:ff:ff:ff:ff:ff promiscuity 1 minmtu 68 maxmtu 65465geneve external id 0 ttl auto dstport 6081 udp6zerocsumrxopenvswitch_slave addrgenmode eui64 numtxqueues 1 numrxqueues 1 gso_max_size 65536 gso_max_segs 65535
查看geneve隧道udp端口,最后一列为“-”表示这个端口是内核态程序监听
[root@node1 ~]# netstat -nulp|grep 6081
udp        0      0 0.0.0.0:6081            0.0.0.0:*                           -
udp6       0      0 :::6081                 :::*                                -[root@node2 ~]# ip link | grep gene
5: genev_sys_6081: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 65000 qdisc noqueue master ovs-system state UNKNOWN mode DEFAULT group default qlen 1000
[root@node2 ~]# ip -d link show genev_sys_6081
5: genev_sys_6081: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 65000 qdisc noqueue master ovs-system state UNKNOWN mode DEFAULT group default qlen 1000link/ether 4e:db:f1:e4:43:94 brd ff:ff:ff:ff:ff:ff promiscuity 1 minmtu 68 maxmtu 65465geneve external id 0 ttl auto dstport 6081 udp6zerocsumrxopenvswitch_slave addrgenmode eui64 numtxqueues 1 numrxqueues 1 gso_max_size 65536 gso_max_segs 65535
[root@node2 ~]# netstat -nulp|grep 6081
udp        0      0 0.0.0.0:6081            0.0.0.0:*                           -
udp6       0      0 :::6081                 :::*                                -

在这里插入图片描述

在做以下实验验证时需要注意MAC地址的合法性,不要误配置。MAC地址分为三类:
广播地址(全F)
FF:FF:FF:FF:FF:FF
主播地址(第一个字节为奇数)
X1:XX:XX:XX:XX:XX
X3:XX:XX:XX:XX:XX
X5:XX:XX:XX:XX:XX
X7:XX:XX:XX:XX:XX
X9:XX:XX:XX:XX:XX
XB:XX:XX:XX:XX:XX
XD:XX:XX:XX:XX:XX
XF:XX:XX:XX:XX:XX
可用MAC地址(第一个字节为偶数)
X0:XX:XX:XX:XX:XX
X2:XX:XX:XX:XX:XX
X4:XX:XX:XX:XX:XX
X6:XX:XX:XX:XX:XX
X8:XX:XX:XX:XX:XX
XA:XX:XX:XX:XX:XX
XC:XX:XX:XX:XX:XX
XE:XX:XX:XX:XX:XX

在每个节点上创建一个网络命名空间ns1(因为在两个节点上所以同名ns1不会冲突),网络命名空间可理解为虚拟机,并且在ovs交换机上创建一组port和interfacce,然后把interface放到网络命名空间下。veth pair:两个网络虚拟端口(设备),veth可理解为网卡端口,一个端口在虚拟机上,一个端口在br-int虚拟交换机上。

node1上执行
[root@node1 ~]# ip netns add ns1
[root@node1 ~]# ip link add veth11 type veth peer name veth12
[root@node1 ~]# ip link set veth12 netns ns1
[root@node1 ~]# ip link set veth11 up
[root@node1 ~]# ip netns exec ns1 ip link set veth12 address 00:00:00:00:00:01
[root@node1 ~]# ip netns exec ns1 ip link set veth12 up
[root@node1 ~]# ovs-vsctl add-port br-int veth11
[root@node1 ~]# ip netns exec ns1 ip addr add 192.168.1.10/24 dev veth12node2上执行,注意veth12的ip和和node1上veth12 ip在同一个子网
[root@node2 ~]# ip netns add ns1
[root@node2 ~]# ip link add veth11 type veth peer name veth12
[root@node2 ~]# ip link set veth12 netns ns1
[root@node2 ~]# ip link set veth11 up
[root@node2 ~]# ip netns exec ns1 ip link set veth12 address 00:00:00:00:00:02
[root@node2 ~]# ip netns exec ns1 ip link set veth12 up
[root@node2 ~]# ovs-vsctl add-port br-int veth11
[root@node2 ~]# ip netns exec ns1 ip addr add 192.168.1.20/24 dev veth12查看node1上br-int交换机信息
[root@node1 ~]# ovs-vsctl show
ed157e0c-cac3-46b9-830c-f2d710b475d5Bridge br-intfail_mode: securedatapath_type: systemPort br-intInterface br-inttype: internalPort veth11Interface veth11Port ovn-node2-0Interface ovn-node2-0type: geneveoptions: {csum="true", key=flow, remote_ip="10.1.1.42"}ovs_version: "3.1.3"
查看node2上br-int交换机信息
[root@node2 ~]# ovs-vsctl show
f6669675-b42d-47de-be95-b26bf6d1e069Bridge br-intfail_mode: securedatapath_type: systemPort veth11Interface veth11Port ovn-node1-0Interface ovn-node1-0type: geneveoptions: {csum="true", key=flow, remote_ip="10.1.1.41"}Port br-intInterface br-inttype: internalovs_version: "3.1.3"现在从node1上的ns1 ping node2上的ns1是不通的,因为它们是不同主机上的网络,二/三层广播域暂时还不可达。
[root@node1 ~]# ip netns exec ns1 ping -c 3 192.168.1.20
PING 192.168.1.20 (192.168.1.20) 56(84) bytes of data.--- 192.168.1.20 ping statistics ---
3 packets transmitted, 0 received, 100% packet loss, time 2047ms

在这里插入图片描述
查看openstack的控制节点发现,ovn的北向数据库中有逻辑交换机信息。
在openstack里面,创建一个网络,就相当于创建了一个逻辑虚拟交换机,这个逻辑交换机(网络)信息会被保存到北向数据库里面。一个网络就是一个逻辑交换机。
在这里插入图片描述
在node1中查看发现,ovn的北向数据库中没有逻辑交换机信息
在这里插入图片描述
在openstack不同节点的虚拟机ip互通,这两个虚拟机ip连的是同一个网络,是同一个逻辑交换机上的同一个子网不同ip所以互通。
这两个节点的虚拟机ns1的ip是手工配置的独立的、不互通,这两个虚拟机ip没有连到逻辑交换机上,加个逻辑交换机就能互通。
在这里插入图片描述
逻辑交换机(Logical Switch):为了使node1和node2上两个连接到ovs交换机的ns能正常通信,需借助ovn的逻辑交换机,注意逻辑交换机是北向数据库概念。

在node1上创建逻辑交换机
[root@node1 ~]# ovn-nbctl ls-add ls1
[root@node1 ~]#  ovn-nbctl show
switch 86349e35-cdb4-42f7-a702-4b4a9d5653ef (ls1)
在逻辑交换机上添加端口
添加并设置用于连接node1的端口,注意mac地址要和veth pair网络命名空间内的那端匹配起来
[root@node1 ~]# ovn-nbctl lsp-add ls1 ls1-node1-ns1
[root@node1 ~]# ovn-nbctl lsp-set-addresses ls1-node1-ns1 00:00:00:00:00:01
[root@node1 ~]# ovn-nbctl lsp-set-port-security ls1-node1-ns1 00:00:00:00:00:01
添加并设置用于连接node2的端口,注意mac地址要匹配起来
[root@node1 ~]# ovn-nbctl lsp-add ls1 ls1-node2-ns1
[root@node1 ~]# ovn-nbctl lsp-set-addresses ls1-node2-ns1 00:00:00:00:00:02
[root@node1 ~]# ovn-nbctl lsp-set-port-security ls1-node2-ns1 00:00:00:00:00:02
查看逻辑交换机信息
[root@node1 ~]# ovn-nbctl show
switch 86349e35-cdb4-42f7-a702-4b4a9d5653ef (ls1)port ls1-node1-ns1addresses: ["00:00:00:00:00:01"]port ls1-node2-ns1addresses: ["00:00:00:00:00:02"]node1上执行,veth11端口连接逻辑交换机端口
[root@node1 ~]# ovs-vsctl set interface veth11 external-ids:iface-id=ls1-node1-ns1
node2上执行,veth11端口连接逻辑交换机端口
[root@node2 ~]# ovs-vsctl set interface veth11 external-ids:iface-id=ls1-node2-ns1
再次查看南向数据库信息,发现端口已连接
[root@node1 ~]# ovn-sbctl show
Chassis node2hostname: node2Encap geneveip: "10.1.1.42"options: {csum="true"}Port_Binding ls1-node2-ns1
Chassis node1hostname: node1Encap geneveip: "10.1.1.41"options: {csum="true"}Port_Binding ls1-node1-ns1
node1上验证网络连通性
[root@node1 ~]# ip netns exec ns1 ping -c 3 192.168.1.20
PING 192.168.1.20 (192.168.1.20) 56(84) bytes of data.
64 bytes from 192.168.1.20: icmp_seq=1 ttl=64 time=4.68 ms
64 bytes from 192.168.1.20: icmp_seq=2 ttl=64 time=0.908 ms
64 bytes from 192.168.1.20: icmp_seq=3 ttl=64 time=0.756 ms--- 192.168.1.20 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2004ms
rtt min/avg/max/mdev = 0.756/2.115/4.682/1.816 ms
node2上验证网络连通性
[root@node2 ~]# ip netns exec ns1 ping -c 3 192.168.1.10
PING 192.168.1.10 (192.168.1.10) 56(84) bytes of data.
64 bytes from 192.168.1.10: icmp_seq=1 ttl=64 time=3.34 ms
64 bytes from 192.168.1.10: icmp_seq=2 ttl=64 time=0.863 ms
64 bytes from 192.168.1.10: icmp_seq=3 ttl=64 time=0.372 ms--- 192.168.1.10 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2003ms
rtt min/avg/max/mdev = 0.372/1.525/3.342/1.300 ms

现在node1和node2的ns1互通了,相当于创建了两个实例,这两个实例ip用的子网是连在同一个逻辑交换机上的,是同一个逻辑交换机上的同一个子网不同ip所以互通。
在这里插入图片描述
在这里插入图片描述
geneve隧道验证:从node1上的ns1 ping node2上的ns1的例子,抓包看看各个相关组件报文,验证geneve隧道封解包。通过抓包分析,可以看出geneve隧道在ovn/ovs跨主机通信的重要作用,同时也能看到ovn逻辑交换机可以把不同宿主机上的二层网络打通,或者说ovn逻辑交换机可以把ovs二层广播域扩展到跨主机。

// node1上ns1 ping node2上ns1
# ip netns exec ns1 ping -c 1 192.168.1.20
PING 192.168.1.20 (192.168.1.20) 56(84) bytes of data.
64 bytes from 192.168.1.20: icmp_seq=1 ttl=64 time=1.00 ms
--- 192.168.1.20 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 1.009/1.009/1.009/0.000 ms// node1上ns1中的veth12抓包
# ip netns exec ns1 tcpdump -i veth12 -n
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on veth12, link-type EN10MB (Ethernet), capture size 262144 bytes
22:23:11.364011 IP 192.168.1.10 > 192.168.1.20: ICMP echo request, id 24275, seq 1, length 64
22:23:11.365000 IP 192.168.1.20 > 192.168.1.10: ICMP echo reply, id 24275, seq 1, length 64
22:23:16.364932 ARP, Request who-has 192.168.1.20 tell 192.168.1.10, length 28
22:23:16.365826 ARP, Reply 192.168.1.20 is-at 00:00:00:00:00:02, length 28// node1上veth12的另一端veth11抓包
# tcpdump -i veth11 -n
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on veth11, link-type EN10MB (Ethernet), capture size 262144 bytes
22:25:11.225987 IP 192.168.1.10 > 192.168.1.20: ICMP echo request, id 25166, seq 1, length 64
22:25:11.226914 IP 192.168.1.20 > 192.168.1.10: ICMP echo reply, id 25166, seq 1, length 64
22:25:16.236933 ARP, Request who-has 192.168.1.20 tell 192.168.1.10, length 28
22:25:16.237563 ARP, Request who-has 192.168.1.10 tell 192.168.1.20, length 28
22:25:16.237627 ARP, Reply 192.168.1.10 is-at 00:00:00:00:00:01, length 28
22:25:16.237649 ARP, Reply 192.168.1.20 is-at 00:00:00:00:00:02, length 28// node1上genev_sys_6081网卡抓包
# tcpdump -i genev_sys_6081 -n
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on genev_sys_6081, link-type EN10MB (Ethernet), capture size 262144 bytes
22:28:15.872064 IP 192.168.1.10 > 192.168.1.20: ICMP echo request, id 26492, seq 1, length 64
22:28:15.872717 IP 192.168.1.20 > 192.168.1.10: ICMP echo reply, id 26492, seq 1, length 64
22:28:20.877100 ARP, Request who-has 192.168.1.20 tell 192.168.1.10, length 28
22:28:20.877640 ARP, Request who-has 192.168.1.10 tell 192.168.1.20, length 28
22:28:20.877654 ARP, Reply 192.168.1.20 is-at 00:00:00:00:00:02, length 28
22:28:20.877737 ARP, Reply 192.168.1.10 is-at 00:00:00:00:00:01, length 28// node1上eth0抓包,可以看出数据包经过genev_sys_6081后做了geneve封装
# tcpdump -i eth0 port 6081 -n
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes
22:30:23.446147 IP 10.0.12.7.51123 > 10.0.12.11.6081: Geneve, Flags [C], vni 0x1, options [8 bytes]: IP 192.168.1.10 > 192.168.1.20: ICMP echo request, id 27458, seq 1, length 64
22:30:23.446659 IP 10.0.12.11.50319 > 10.0.12.7.6081: Geneve, Flags [C], vni 0x1, options [8 bytes]: IP 192.168.1.20 > 192.168.1.10: ICMP echo reply, id 27458, seq 1, length 64
22:30:28.461137 IP 10.0.12.7.49958 > 10.0.12.11.6081: Geneve, Flags [C], vni 0x1, options [8 bytes]: ARP, Request who-has 192.168.1.20 tell 192.168.1.10, length 28
22:30:28.461554 IP 10.0.12.11.61016 > 10.0.12.7.6081: Geneve, Flags [C], vni 0x1, options [8 bytes]: ARP, Request who-has 192.168.1.10 tell 192.168.1.20, length 28
22:30:28.461571 IP 10.0.12.11.61016 > 10.0.12.7.6081: Geneve, Flags [C], vni 0x1, options [8 bytes]: ARP, Reply 192.168.1.20 is-at 00:00:00:00:00:02, length 28
22:30:28.461669 IP 10.0.12.7.49958 > 10.0.12.11.6081: Geneve, Flags [C], vni 0x1, options [8 bytes]: ARP, Reply 192.168.1.10 is-at 00:00:00:00:00:01, length 28===================跨主机===================// node2上eth0抓包
# tcpdump -i eth0 port 6081 -n
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes
22:23:11.364189 IP 10.0.12.7.51123 > 10.0.12.11.6081: Geneve, Flags [C], vni 0x1, options [8 bytes]: IP 192.168.1.10 > 192.168.1.20: ICMP echo request, id 24275, seq 1, length 64
22:23:11.364662 IP 10.0.12.11.50319 > 10.0.12.7.6081: Geneve, Flags [C], vni 0x1, options [8 bytes]: IP 192.168.1.20 > 192.168.1.10: ICMP echo reply, id 24275, seq 1, length 64
22:23:16.365086 IP 10.0.12.7.49958 > 10.0.12.11.6081: Geneve, Flags [C], vni 0x1, options [8 bytes]: ARP, Request who-has 192.168.1.20 tell 192.168.1.10, length 28
22:23:16.365487 IP 10.0.12.11.61016 > 10.0.12.7.6081: Geneve, Flags [C], vni 0x1, options [8 bytes]: ARP, Reply 192.168.1.20 is-at 00:00:00:00:00:02, length 28// node2上genev_sys_6081网卡抓包,可以看到数据包从genev_sys_6081出来后做了geneve解封
# tcpdump -i genev_sys_6081 -n
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on genev_sys_6081, link-type EN10MB (Ethernet), capture size 262144 bytes
22:25:11.226186 IP 192.168.1.10 > 192.168.1.20: ICMP echo request, id 25166, seq 1, length 64
22:25:11.226553 IP 192.168.1.20 > 192.168.1.10: ICMP echo reply, id 25166, seq 1, length 64
22:25:16.237070 ARP, Request who-has 192.168.1.20 tell 192.168.1.10, length 28
22:25:16.237162 ARP, Request who-has 192.168.1.10 tell 192.168.1.20, length 28
22:25:16.237203 ARP, Reply 192.168.1.20 is-at 00:00:00:00:00:02, length 28
22:25:16.237523 ARP, Reply 192.168.1.10 is-at 00:00:00:00:00:01, length 28// node2上veth11抓包
# tcpdump -i veth11 -n
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on veth11, link-type EN10MB (Ethernet), capture size 262144 bytes
22:28:15.872198 IP 192.168.1.10 > 192.168.1.20: ICMP echo request, id 26492, seq 1, length 64
22:28:15.872235 IP 192.168.1.20 > 192.168.1.10: ICMP echo reply, id 26492, seq 1, length 64
22:28:20.876913 ARP, Request who-has 192.168.1.10 tell 192.168.1.20, length 28
22:28:20.877274 ARP, Request who-has 192.168.1.20 tell 192.168.1.10, length 28
22:28:20.877287 ARP, Reply 192.168.1.20 is-at 00:00:00:00:00:02, length 28
22:28:20.877613 ARP, Reply 192.168.1.10 is-at 00:00:00:00:00:01, length 28// node2上ns1中的veth12抓包
# ip netns exec ns1 tcpdump -i veth12 -n
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on veth12, link-type EN10MB (Ethernet), capture size 262144 bytes
22:30:23.446212 IP 192.168.1.10 > 192.168.1.20: ICMP echo request, id 27458, seq 1, length 64
22:30:23.446242 IP 192.168.1.20 > 192.168.1.10: ICMP echo reply, id 27458, seq 1, length 64
22:30:28.460912 ARP, Request who-has 192.168.1.10 tell 192.168.1.20, length 28
22:30:28.461260 ARP, Request who-has 192.168.1.20 tell 192.168.1.10, length 28
22:30:28.461272 ARP, Reply 192.168.1.20 is-at 00:00:00:00:00:02, length 28
22:30:28.461530 ARP, Reply 192.168.1.10 is-at 00:00:00:00:00:01, length 28

逻辑路由器(Logical Router):
前面验证了ovn逻辑交换机跨主机同子网的通信,那不同子网间又该如何通信呢?这就要用到ovn的逻辑路由器了。
先在node2上再创建个网络命名空间ns2,ip设置为另外一个子网192.168.2.30/24,并且再增加一个逻辑交换机。
在这里插入图片描述

node2上执行
[root@node2 ~]# ip netns  查看网络命名空间
ns1 (id: 0)
[root@node2 ~]# ip netns add ns2
[root@node2 ~]# ip link add veth21 type veth peer name veth22
[root@node2 ~]# ip link set veth22 netns ns2
[root@node2 ~]# ip link set veth21 up
[root@node2 ~]# ip netns exec ns2 ip link set veth22 address 00:00:00:00:00:03
[root@node2 ~]# ip netns exec ns2 ip link set veth22 up
[root@node2 ~]# ovs-vsctl add-port br-int veth21
[root@node2 ~]# ip netns exec ns2 ip addr add 192.168.2.30/24 dev veth22
[root@node2 ~]# ip netns
ns2 (id: 1)
ns1 (id: 0)node1上用ovn命令新增一个逻辑交换机,并配置好端口
[root@node1 ~]# ovn-nbctl ls-add ls2
[root@node1 ~]# ovn-nbctl lsp-add ls2 ls2-node2-ns2
[root@node1 ~]# ovn-nbctl lsp-set-addresses ls2-node2-ns2 00:00:00:00:00:03
[root@node1 ~]# ovn-nbctl lsp-set-port-security ls2-node2-ns2 00:00:00:00:00:03node2上ovs交换机端口和ovn逻辑交换机端口匹配起来
[root@node2 ~]# ovs-vsctl set interface veth21 external-ids:iface-id=ls2-node2-ns2查看北向数据库和南向数据库信息
[root@node1 ~]# ovn-nbctl show
switch 484606e0-944d-4c6b-9807-502f05bebb18 (ls2)port ls2-node2-ns2addresses: ["00:00:00:00:00:03"]
switch 86349e35-cdb4-42f7-a702-4b4a9d5653ef (ls1)port ls1-node1-ns1addresses: ["00:00:00:00:00:01"]port ls1-node2-ns1addresses: ["00:00:00:00:00:02"]
[root@node1 ~]# ovn-sbctl show
Chassis node2hostname: node2Encap geneveip: "10.1.1.42"options: {csum="true"}Port_Binding ls2-node2-ns2Port_Binding ls1-node2-ns1
Chassis node1hostname: node1Encap geneveip: "10.1.1.41"options: {csum="true"}Port_Binding ls1-node1-ns1

创建ovn逻辑路由器连接两个逻辑交换机

添加逻辑路由器,路由信息保存在北向数据库
[root@node1 ~]# ovn-nbctl lr-add lr1
逻辑路由器添加连接交换机ls1的端口
[root@node1 ~]# ovn-nbctl lrp-add lr1 lr1-ls1 00:00:00:00:11:00 192.168.1.1/24
逻辑路由器添加连接交换机ls2的端口
[root@node1 ~]# ovn-nbctl lrp-add lr1 lr1-ls2 00:00:00:00:12:00 192.168.2.1/24逻辑路由器连接逻辑交换机ls1
[root@node1 ~]# ovn-nbctl lsp-add ls1 ls1-lr1
[root@node1 ~]# ovn-nbctl lsp-set-type ls1-lr1 router
[root@node1 ~]# ovn-nbctl lsp-set-addresses ls1-lr1 00:00:00:00:11:00
[root@node1 ~]# ovn-nbctl lsp-set-options ls1-lr1 router-port=lr1-ls1逻辑路由器连接逻辑交换机ls2
[root@node1 ~]# ovn-nbctl lsp-add ls2 ls2-lr1
[root@node1 ~]# ovn-nbctl lsp-set-type ls2-lr1 router
[root@node1 ~]# ovn-nbctl lsp-set-addresses ls2-lr1 00:00:00:00:12:00
[root@node1 ~]# ovn-nbctl lsp-set-options ls2-lr1 router-port=lr1-ls2查看北向数据库和南向数据库信息
[root@node1 ~]# ovn-nbctl show
switch 484606e0-944d-4c6b-9807-502f05bebb18 (ls2)port ls2-node2-ns2addresses: ["00:00:00:00:00:03"]port ls2-lr1type: routeraddresses: ["00:00:00:00:12:00"]router-port: lr1-ls2
switch 86349e35-cdb4-42f7-a702-4b4a9d5653ef (ls1)port ls1-node1-ns1addresses: ["00:00:00:00:00:01"]port ls1-node2-ns1addresses: ["00:00:00:00:00:02"]port ls1-lr1type: routeraddresses: ["00:00:00:00:11:00"]router-port: lr1-ls1
router e9c151a0-5db7-4af6-91bd-89049c4bbf9f (lr1)port lr1-ls2mac: "00:00:00:00:12:00"networks: ["192.168.2.1/24"]port lr1-ls1mac: "00:00:00:00:11:00"networks: ["192.168.1.1/24"]
[root@node1 ~]# ovn-sbctl show
Chassis node2hostname: node2Encap geneveip: "10.1.1.42"options: {csum="true"}Port_Binding ls2-node2-ns2Port_Binding ls1-node2-ns1
Chassis node1hostname: node1Encap geneveip: "10.1.1.41"options: {csum="true"}Port_Binding ls1-node1-ns1

在这里插入图片描述
从node1的ns1(192.168.1.10/24) ping node2的ns2(192.168.2.30),验证跨节点不同子网的连通性。

[root@node1 ~]# ip netns exec ns1 ping -c 1 192.168.2.30
connect: Network is unreachable        connect: 网络不可达
查看ns1上的路由配置,显然此时没有到192.168.2.0/24网段的路由
[root@node1 ~]# ip netns exec ns1 ip route show
192.168.1.0/24 dev veth12 proto kernel scope link src 192.168.1.10
[root@node1 ~]# ip netns exec ns1 route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
192.168.1.0     0.0.0.0         255.255.255.0   U     0      0        0 veth12

因为路由器是三层概念,要先给ovs的相关port配置上ip

[root@node1 ~]# ovn-nbctl lsp-set-addresses ls1-node1-ns1 00:00:00:00:00:01
[root@node1 ~]# ovn-nbctl lsp-set-addresses ls1-node2-ns1 00:00:00:00:00:02
[root@node1 ~]# ovn-nbctl lsp-set-addresses ls2-node2-ns2 00:00:00:00:00:03

再给三个网络命名空间添加默认路由,网关为ovn逻辑路由器对应的port ip

 node1上ns1[root@node1 ~]# ip netns exec ns1 ip route add default via 192.168.1.1 dev veth12node2上ns1[root@node2 ~]# ip netns exec ns1 ip route add default via 192.168.1.1 dev veth12node2上ns2[root@node2 ~]# ip netns exec ns2 ip route add default via 192.168.2.1 dev veth22

再次查看下南北向数据库信息

[root@node1 ~]# ovn-nbctl show
switch 484606e0-944d-4c6b-9807-502f05bebb18 (ls2)port ls2-node2-ns2addresses: ["00:00:00:00:00:03"]port ls2-lr1type: routeraddresses: ["00:00:00:00:12:00"]router-port: lr1-ls2
switch 86349e35-cdb4-42f7-a702-4b4a9d5653ef (ls1)port ls1-node1-ns1addresses: ["00:00:00:00:00:01"]port ls1-node2-ns1addresses: ["00:00:00:00:00:02"]port ls1-lr1type: routeraddresses: ["00:00:00:00:11:00"]router-port: lr1-ls1
router e9c151a0-5db7-4af6-91bd-89049c4bbf9f (lr1)port lr1-ls2mac: "00:00:00:00:12:00"networks: ["192.168.2.1/24"]port lr1-ls1mac: "00:00:00:00:11:00"networks: ["192.168.1.1/24"]
[root@node1 ~]# ovn-sbctl show
Chassis node2hostname: node2Encap geneveip: "10.1.1.42"options: {csum="true"}Port_Binding ls2-node2-ns2Port_Binding ls1-node2-ns1
Chassis node1hostname: node1Encap geneveip: "10.1.1.41"options: {csum="true"}Port_Binding ls1-node1-ns1

在这里插入图片描述
验证网络连通性

node1上ns1连通网关
[root@node1 ~]# ip netns exec ns1 ping -c 1 192.168.1.1
PING 192.168.1.1 (192.168.1.1) 56(84) bytes of data.
64 bytes from 192.168.1.1: icmp_seq=1 ttl=254 time=20.10 ms--- 192.168.1.1 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 20.950/20.950/20.950/0.000 msnode2上ns2连通网关
[root@node2 ~]# ip netns exec ns2 ping -c 1 192.168.2.1
PING 192.168.2.1 (192.168.2.1) 56(84) bytes of data.
64 bytes from 192.168.2.1: icmp_seq=1 ttl=254 time=38.5 ms--- 192.168.2.1 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 38.477/38.477/38.477/0.000 msnode1上ns1 ping node2上ns2
[root@node1 ~]# ip netns exec ns1 ping -c 1 192.168.2.30
PING 192.168.2.30 (192.168.2.30) 56(84) bytes of data.
64 bytes from 192.168.2.30: icmp_seq=1 ttl=63 time=1.23 ms--- 192.168.2.30 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 1.225/1.225/1.225/0.000 ms

注意:ovn逻辑交换机/逻辑路由器是北向数据库概念,这两个逻辑概念经过ovn-northd“翻译”到了南向数据库中,再通过hypervisor上的ovn-controller同步到ovs/ovsdb-server,最终形成ovs的port和流表等数据。
ovn逻辑交换机通过geneve隧道,把二层广播域扩展到了不同主机上的ovs;而ovn逻辑路由器则是把三层广播域扩展到了不同主机上的ovs,从而实现跨主机的网络通信。
ovn逻辑交换机和逻辑路由器都会在所有的hypervisor中生成对应的流表配置,这也是ovn网络高可用以及解决实例迁移等问题的原理。

相关文章:

HCIP-OpenStack组件之neutron

neutron&#xff08;ovs、ovn&#xff09; OVS OVS(Open vSwitch)是虚拟交换机&#xff0c;遵循SDN(Software Defined Network&#xff0c;软件定义网络)架构来管理的。 OVS介绍参考&#xff1a;https://mp.weixin.qq.com/s?__bizMzAwMDQyOTcwOA&mid2247485088&idx1…...

数学建模-常见算法(3)

KMP算法&#xff08;Knuth-Morris-Pratt算法&#xff09; KMP算法是一种用于字符串匹配的算法&#xff0c;它的时间复杂度为O(mn)。该算法的核心思想是在匹配失败时&#xff0c;利用已经匹配的信息&#xff0c;减少下一次匹配的起始位置。 def kmp(text, pattern): n len(…...

缓存的设计方式

问题情况&#xff1a; 当有大量的请求到内部系统时&#xff0c;若每一个请求都需要我们操作数据库&#xff0c;例如查询操作&#xff0c;那么对于那种数据基本不怎么变动的数据来说&#xff0c;每一次都去数据库里面查询&#xff0c;是很消耗我们的性能 尤其是对于在海量数据…...

CH02_重构的原则(什么是重构、为什么重构、何时重构)

什么是重构 重构&#xff08;名词&#xff09;&#xff1a;对软件内部结构的一种调整&#xff0c;目的是在不改变软件可观察行为的前提下&#xff0c;提高其可理解性&#xff0c;降低其修改成本。 重构&#xff08;动词&#xff09;&#xff1a;使用一系列重构手法&#xff0…...

26. 删除有序数组中的重复项(简单系列)

给你一个 升序排列 的数组 nums &#xff0c;请你 原地 删除重复出现的元素&#xff0c;使每个元素 只出现一次 &#xff0c;返回删除后数组的新长度。元素的 相对顺序 应该保持 一致 。然后返回 nums 中唯一元素的个数。 考虑 nums 的唯一元素的数量为 k &#xff0c;你需要做…...

【linux】基本指令(二)【man、echo、cat、cp】

目录 一、man指令二、echo指令三、cat指令二、cp指令一些常见快捷键 一、man指令 Linux的命令有很多参数&#xff0c;我们不可能全记住&#xff0c;可以通过查看联机手册获取帮助。访问Linux手册页的命令是 man 语法: man [选项] 命令 常用选项 1.-k 根据关键字搜索联机帮助 2…...

【视频】Python用LSTM长短期记忆神经网络对不稳定降雨量时间序列进行预测分析|数据分享...

全文下载链接&#xff1a;http://tecdat.cn/?p23544 在本文中&#xff0c;长短期记忆网络——通常称为“LSTM”——是一种特殊的RNN递归神经网络&#xff0c;能够学习长期依赖关系&#xff08;点击文末“阅读原文”获取完整代码数据&#xff09;。 本文使用降雨量数据&#xf…...

2023年7月京东空气净化器行业品牌销售排行榜(京东运营数据分析)

随着科技发展&#xff0c;智能家具在日常生活中出现的频率越来越高&#xff0c;许多曾经不被关注的家电也出现在其中&#xff0c;包括近年来逐渐兴起的空气净化器。伴随人们对自身健康的重视度越来越高&#xff0c;作为能够杀灭空气污染物、有效提高空气清洁度的产品&#xff0…...

原生小案例:如何使用HTML5 Canvas构建画板应用程序

使用HTML5 Canvas构建绘图应用是在Web浏览器中创建交互式和动态绘图体验的绝佳方式。HTML5 Canvas元素提供了一个绘图表面&#xff0c;允许您操作像素并以编程方式创建各种形状和图形。本文将为您提供使用HTML5 Canvas创建绘图应用的概述和指导。此外&#xff0c;它还将通过解释…...

Electron 报gpu_process_host.cc(951)] GPU process launch faile错误

解决方法&#xff0c;在入口js文件中&#xff0c;添加如下代码: app.commandLine.appendSwitch(no-sandbox)...

每天一分享#读up有感#

不知道开头怎么写&#xff0c;想了一下&#xff0c;要不&#xff0c;就这样吧&#xff0c;开头也就写完 今日分享 分享一博主的分享——https://blog.csdn.net/zhangay1998/article/details/121736687 全程高能&#xff0c;大佬就diao&#xff0c;一鸣惊人、才能卓越、名扬四…...

threejs贴图系列(一)canvas贴图

threejs不仅支持各种texture的导入生成贴图&#xff0c;还可以利用canvas绘制图片作为贴图。这就用到了CanvasTexture&#xff0c;它接受一个canas对象。只要我们绘制好canvas&#xff0c;就可以作为贴图了。这里我们利用一张图片来实现这个效果。 基础代码&#xff1a; impo…...

taro react/vue h5 中的上传input onchange 值得区别

<inputclassNamebase-input-file-h5typefileacceptimage/*capturecameraonChange{onChangeInput} />1、taro3react 2、taro3vue3...

(AcWing) 任务安排(I,II,III)

任务安排I: 有 N 个任务排成一个序列在一台机器上等待执行&#xff0c;它们的顺序不得改变。 机器会把这 N 个任务分成若干批&#xff0c;每一批包含连续的若干个任务。 从时刻 0 开始&#xff0c;任务被分批加工&#xff0c;执行第 i 个任务所需的时间是 Ti。 另外&#x…...

Excel筛选后复制粘贴不连续问题的解决

一直以来都没好好正视这个问题认真寻求解决办法 终于还是被需求逼出来了&#xff0c;懒人拯救世界[doge] 一共找到两个方法&#xff0c;个人比较喜欢第二种&#xff0c;用起来很方便 Way1&#xff1a;CtrlG定位可见单元格后使用vlookup解决&#xff08;感觉不定位直接公式向下…...

【SCSS变量】$ | | var | @for | @include | @function | @each 等常用方法使用

SCSS优点&#xff1a;编写清晰、无冗余、语义化的CSS&#xff0c;减少不必要的重复工作 1、变量声明&#xff08;$&#xff09;和使用2、使用 & 代替父元素3、在HTML中使用 :style{--name: 动态值}自定义属性&#xff0c;在SCSS中用var(--name)函数绑定动态变量值&#xff…...

iOS 17 及 Xcode 15.0 Beta7 问题记录

1、iOS 17 真机调试问题 iOS 17之后&#xff0c;真机调试Beta版本必须使用Beta版本的Xcode来调试&#xff0c;用以前复制DeviceSupport 方式无法调试&#xff0c;新的Beta版本Xcode中&#xff0c;已经不包含 iOS 17目录。如下图&#xff1a; 解决方案&#xff1a; 1&#x…...

docker-maven-plugin直接把镜像推到私有仓库

接着上篇 推送到本地docker 我们已经把服务做成镜像推到docker&#xff0c;也可以通过docker login 私有地址&#xff0c;去push。麻烦 直接上代码 1、pom改动 <properties><docker.registry>eco-registry.XXX.com</docker.repostory><docker.registry…...

2023年机器学习项目—布匹缺陷检测

2023年机器学习项目———布匹缺陷检测 测试环境: CPU : 12th Gen Intel Core™ i7-12700H 2.70 GHz GPU : NVIDIA RTX3070Ti RAM : 32GB Matlab R2020a (Deep Learning Tools) 注 :Data文件过大 未上传 一.神经网络概述 1. 卷积神经网络概念 人工神经网络(Artific…...

RabbitMQ---订阅模型分类

订阅模型分类 在之前的模式中&#xff0c;我们创建了一个工作队列。 工作队列背后的假设是&#xff1a;每个任务只被传递给一个工作人员。 在这一部分&#xff0c;我们将做一些完全不同的事情 - 我们将会传递一个信息给多个消费者。 这种模式被称为“发布/订阅”。 订阅模型示意…...

pycharm添加虚拟环境以及虚拟环境安装pytorch

file、settings、interpreter、add interpreter、add local interpreter 记住不要勾选inherit&#xff0c;不然会把主环境的东西继承到虚拟环境。 创建前可以先点existing看看有没有已经建好的虚拟环境 有的时候pycharm有问题&#xff0c;创建了虚拟环境没有显示。找一个.py文…...

Git企业开发控制理论和实操-从入门到深入(三)|分支管理

前言 那么这里博主先安利一些干货满满的专栏了&#xff01; 首先是博主的高质量博客的汇总&#xff0c;这个专栏里面的博客&#xff0c;都是博主最最用心写的一部分&#xff0c;干货满满&#xff0c;希望对大家有帮助。 高质量博客汇总 然后就是博主最近最花时间的一个专栏…...

【VsCode】SSH远程连接Linux服务器开发,搭配cpolar内网穿透实现公网访问(1)

文章目录 前言1、安装OpenSSH2、vscode配置ssh3. 局域网测试连接远程服务器4. 公网远程连接4.1 ubuntu安装cpolar内网穿透4.2 创建隧道映射4.3 测试公网远程连接 5. 配置固定TCP端口地址5.1 保留一个固定TCP端口地址5.2 配置固定TCP端口地址5.3 测试固定公网地址远程 前言 远程…...

LC-1267. 统计参与通信的服务器(枚举 + 计数)

1267. 统计参与通信的服务器 中等 这里有一幅服务器分布图&#xff0c;服务器的位置标识在 m * n 的整数矩阵网格 grid 中&#xff0c;1 表示单元格上有服务器&#xff0c;0 表示没有。 如果两台服务器位于同一行或者同一列&#xff0c;我们就认为它们之间可以进行通信。 请…...

Linux TCP协议——三次握手,四次挥手

一、TCP协议介绍 TCP协议是可靠的、面向连接的、基于字节流的传输层通信协议。 TCP的头部结构&#xff1a; 源/目的端口号: 表示数据是从哪个进程来, 到哪个进程去;&#xff08;tcp是传输层的协议&#xff0c;端与端之间的数据传输&#xff0c;在TCP和UDP协议当中不会体现出I…...

人机对抗智能-部分可观测异步智能体协同(POAC)

环境链接&#xff1a;数据中心-人机对抗智能 (ia.ac.cn)http://turingai.ia.ac.cn/data_center/show/10 1.环境配置 Ubuntu 20.04 Anaconda python版本3.6 1.1 安装torch0.4.1失败 参考文章&#xff1a; 安装torch0.4.1的神坑_torch0.4.1_DEMO_Tian的博客-CSDN博客 co…...

数学——七桥问题——图论

当涉及数学&#xff0c;有很多不同的话题可以讨论。你是否有特定的数学领域、概念或问题想要了解更多&#xff1f;以下是一些常见的数学领域和主题&#xff0c;你可以选择一个或者告诉我你感兴趣的具体内容&#xff0c;我将很乐意为你提供更多信息&#xff1a; 代数学&#xff…...

python 模块lxml 处理 XML 和 HTML 数据

xpath&#xff1a;https://blog.csdn.net/randy521520/article/details/132432903 一、安装 XPath (XML Path Language) 是一门在 HTML\XML 文档中查找信息的语言&#xff0c;可用来在 HTML\XML 文档中对元素和属性进行遍历。 pip install lxml二、使用案例 from lxml impo…...

SpringBoot 统⼀功能处理

统⼀功能处理 1. 拦截器2. 统⼀异常处理3. 统⼀数据返回格式 1. 拦截器 Spring 中提供了具体的实现拦截器&#xff1a;HandlerInterceptor&#xff0c;拦截器的实现分为以下两个步骤&#xff1a; 创建⾃定义拦截器&#xff0c;实现 HandlerInterceptor 接⼝的 preHandle&…...

hadoop 报错 java.io.IOException: Inconsistent checkpoint fields

背景: 使用了格式化,导致首重了新的集群ID org.apache.hadoop.hdfs.server.common.InconsistentFSStateException: Directory /work1/home/hadoop/dfs/data/current/BP-1873526852-172.16.21.30-1692769875005 is in an inconsistent state: namespaceID is incompatible with …...

大型网站故障/百度广告标识

1、背景 我所负责实时支付项目&#xff0c;生产环境出现几次重大问题&#xff0c;比如&#xff0c;网络硬件设备故障、银联方面问题、消息队列异常、网络阻塞等问题。对于稳定运行运行两年系统&#xff0c;对它关注度会习惯性松懈&#xff0c;往往出现问题由客户反馈到IT&#…...

江苏中小企业建站价格/seo服务哪家好

TCPDUMP中文手册最详细的手册&#xff08;转&#xff09; 名称(NAME) tcpdump-转储网络上的数据流 总览(SYNOPSIS) tcpdump[-adeflnNOpqStvx][-ccount][-Ffile] [-iinterface][-rfile][-ssnaplen] [-Ttype][-wfile][expression] 描述(DESCRIPTION) Tcpdump打印出在某个网络界面…...

江苏同邦建设有限公司网站/今日新闻摘抄50字

adobe acrobat reader安装教程 正版免费 首先进入adobe中国官网 点击官网主页上方的PDF解决方案&#xff0c;再点击Reader 点击立即下载 这里两个可选项看你自己咯&#xff0c;我选了chrome浏览器的扩展程序&#xff0c;这样浏览器也能打开某些必须用adobe才能打开的pdf文件…...

网站正在建设中自拍/广州seo网站优化培训

转载至&#xff1a; https://github.com/avislab/STM32F103/blob/master/Example_USART1/main.c 如有侵权&#xff0c;请联系删除&#xff01; 代码现象&#xff1a;从串口发一个数据&#xff0c;串口能够返回相应的值&#xff0c; #include "stm32f10x.h"#include…...

怎么注册网站卖东西/谈谈你对网络营销的看法

1065: 无向图的连通分量计算 题目描述 假设无向图G采用邻接矩阵存储&#xff0c;编写一个算法求连通分量的个数。 输入 第一行为一个整数n&#xff0c;表示顶点的个数&#xff08;顶点编号为0到n-1&#xff09;&#xff0c;接下来是为一个n*n大小的整数矩阵&#xff0c;表示图…...

企业名录免费 email/seo长尾关键词

最近在看东西的时候发现很多网络程序中都需要NAT穿越&#xff0c;特意在此总结一下。 先做一个约定&#xff1a; 内网A中有&#xff1a;A1&#xff08;192.168.0.8&#xff09;、A2&#xff08;192.168.0.9&#xff09;两用户 网关X1&#xff08;一个NAT设备&#xff09;有公网…...