本文为看雪论坛优秀文章
看雪论坛作者ID:jmpcall
ESXi/KVM
虚拟化系统,提供虚假化能力和接口,支持安装在物理机中,使得可以在物理机中创建设备,也支持嵌套,安装到虚拟机中,使得虚拟宿主机中可以进一步创建虚拟机。
vCenter
一套封装ESXi主机接口和资源的平台,它可以添加多台ESXi主机,然后间接提供给用户,比如用户通过vCenter创建VM,实际上在某台ESXi主机中创建了VM。
NSX-t
一套封装ESXi/KVM主机接口和资源的平台,它侧重于封装通信虚拟设备的操作接口,比如交换机和路由器的创建、连接、删除等,使主机中创建的VM,可以相互通信。并且,它支持和vCenter结合使用,vCenter注册到NSX-t之后,其中添加的ESXi主机就会对NSX-t也可见,由于vCenter不支持添加KVM主机,所以KVM主机必须直接添加到NSX-t。
虚拟交换机
ESXi系统安装后,默认会创建一台VSS(虚拟标准交换机),因为将ESXi主机添加到vCenter的过程中,vCenter会在其中安插几台VM,从而可以对它进行管理,而这几台VM就是通过VSS接入管理网段,和vCenter进行通信的。另外,通过vCenter,可以创建VDS(vSphere分布式交换机),通过NSX-t,可以创建NVDS(NSX-t虚拟分布式交换机)。
虚拟路由器
通过NSX-t,可以创建T1(东西向路由器)和T0(南北向路由器)。
上行口(Uplink)
物理世界中,通信设备之间是通过物理介质相连,比如网线,然而虚拟通信设备上是没有办法插网线的,只能通过软件模拟连接。在每个宿主机内部,VM要能和交换机连接,所以要实现进程间的数据共享,另外,宿主机中的任何通信程序,都要借助宿主机网卡收发流量,虚拟交换机组件也不例外,所以要实现交换机组件的网卡读写功能,使其逻辑上存在一个端口,即“上行口”,可以借助宿主机网卡跟外部通信。
理解了以上概念,就很容易理解NSX-t二层网络的配置的过程了:
创建IP地址池
创建IP地址池
|- NSX-t manager->Networking->IP Management->IP Address Pools->ADD
|- Name: VTEP-IP-Pool
|- Set Subnets
|- IP Ranges: 172.20.11.151-172.20.11.170
|- CIDR: 172.20.11.0/24
|- Gateway IP: 172.20.11.10
目的:后续操作,在每台主机中创建PROD-Overlay-NVDS交换机(TN)时,需要从VTEP-IP-Pool地址池,为交换机的TEP口分配ip地址。
创建TZ
创建PROD-Overlay-TZ
|- NSX-t manager->System->Fabric->Transport Zones->ADD
|- Name: PROD-Overlay-TZ
|- Switch Name: PROD-Overlay-NVDS
|- Traffic Type: Overlay
创建PROD-VLAN-TZ
|- NSX-t manager->System->Fabric->Transport Zones->ADD
|- Name: PROD-VLAN-TZ
|- Switch Name: PROD-VLAN-NVDS
|- Traffic Type: VLAN
目的:描述TZ(多台TN的级联交换机),包括:TZ名称、加入该TZ需要创建的TN名称及Traffic Type。
Overlay主要优势:
(1) 相比vlan-id最大值只有4094,VNI接近16M个,极大的增加了一个二层区域可以容纳的设备数;
(2) 只要主机之间能三层通信,就可以将其中创建的VM放在同一个二层区域,二层区域不再限制于一个机房的范围,极大的提高了VM部署和迁移的灵活性。
实验环境中,如果所有ESXi/KVM主机,都在同一个二层区域,创建TZ的时候,无论选择哪种Traffic Type,其实都可以满足VM之间二层通信,但是如果不满足这个条件,那就必须选择Overlay,本文实验中,选择的是PROD-Overlay-TZ。而这里同时还创建了PROD-VLAN-TZ,是为了后续实现南北向三层通信时,将T0路由器和物理路由器接入同一个网段。
将ESXi/KVM主机加入TZ
主机加入TZ
|- NSX-t manager->System->Fabric->Nodes->Host Transport Nodes->ADD
|- 选择主机
| |- sa-vcsa-01.vclass.local # 由vCenter管理的主机
| | |- ESXi04
| | |- ESXi05
| |- None: Standalone Hosts
| |- kvm-01
| | |- Name: sa-kvm-01.vclass.local
| | |- IP Address: 172.20.10.151
| | |- Username: *****
| | |- Password: *****
| |- kvm-02
| |- Name: sa-kvm-02.vclass.local
| |- IP Address: 172.20.10.152
| |- Username: *****
| |- Password: *****
|- CONFIGURE NSX
|- 选择Transport Node Profile (没有先创建)
|- Name: ESXi-TN-Profile
|- New Node Switch
|- Type: N-VDS # N-VDS, VDS, VSS
|- Mode: Standard # Enhanced Datapath需要uplink物理网卡支持,可以加速报文接收发送
|- Name: PROD-Overlay-NVDS
|- Transport Zone: PROD-Overlay-TZ
|- Uplink Profile: nsx-default-uplink-hostswitch-profile # Active-Standby
|- IP Assignment: Use IP Pool
|- IP Pool: VTEP-IP-Pool
|- Teaming Policy Switch Mapping
|- uplink-1 (active): vmnic4 / eth1
目的:在主机中创建TN,并级联到现有的TZ中。
根据目的就不难理解,配置中除了指定TZ,为什么还要指定一堆TN描述信息,包括:Name、Type(N-VDS)、Mode、IP Pool(为PROD-Overlay-TZ的TEP口提供ip地址)、Uplink Profile(uplink策略,后续如果为TN设置2个上行口,则为主备模式)、uplink-1(由于是实验环境,对高可用性要求不高,不配uplink-2可以理解为备用上行口天然就是坏的,主备只要有一个是好的,就不会影响通信)。
PROD-Overlay-TZ添加segment
添加Web-Segment
|- NSX-t manager->Networking->Segments->ADD
|- Segment Name: Web-Segment
|- Connectivity: 暂时不选 (将来选择T1-GW-01|Tier1)
|- Transport Zone: PROD-Overlay-TZ
|- subnets: 暂时不填 (将来填: 172.16.10.1/24)
添加App-segment
|- NSX-t manager->Networking->Segments->ADD
|- Segment Name: App-Segment
|- Connectivity: 暂时不选 (将来选择T1-GW-01|Tier1)
|- Transport Zone: PROD-Overlay-TZ
|- subnets: 暂时不填 (将来填: 172.16.20.1/24)
添加DB-segment
|- NSX-t manager->Networking->Segments->ADD
|- Segment Name: DB-Segment
|- Connectivity: 暂时不选 (将来选择T1-GW-01|Tier1)
|- Transport Zone: PROD-Overlay-TZ
|- subnets: 暂时不填 (将来填: 172.16.30.1/24)
目的:相当于在PROD-Overlay-TZ级联交换机上,划分了3个vlan:Web-Segment、App-Segment、DB-Segment。
VM接入segment
# vCenter支持添加ESXi主机,所以ESXi主机中的VM,可以通过vCenter接入Segment
ESXi主机中的vm连接到segment (vcenter: 右键vm->Edit Settings)
|- Network adapter: Web-Segment / App-Segment / DB-Segment
# vCenter不支持添加KVM主机,KVM主机中的VM,通过以下方式接入Segment
KVM主机中的vm连接到segment
|- ssh连接KVM主机
| |- virsh list --all
| |- virsh start T1-DB-01 # 如果vm为断电状态 (比如显示: T1-DB-01 (shut off))
| |- virsh dumpxml T1-DB-01 | grep interfaceid # 查看vm网卡的uuid并复制
|- NSX-t manager->..->SEGMENTS
|- 编译Web-Segment / App-Segment / DB-Segment ->点击Ports列中的Set
|- ID: vm网卡的uuid
目的:将VM接入不同的Segment,不过以上只是描述了接入的方法,实验环境中,具体连接见2.2.3节逻辑拓扑和物理拓扑:
(1) ESXi04主机中的T1-web-01(172.16.10.11/24)、ESXi05主机中的T1-web-02(172.16.10.12/24)、kvm-02主机中的T1-web-03(172.16.10.13/24),3台VM接入Web-Segment;
(2) ESXi04主机中的T1-App-01(172.16.20.11/24),1台VM接入App-Segment;
(3) kvm-01主机中的T1-DB-01(172.16.30.11/24),1台VM接入DB-Segment。
物理拓扑
报文传送过程
比如:Web-Segment网段中,W1访问W3,过程如下:
Step1:W1构造“W1 mac : W1 ip -> W3 mac : W3 ip”报文(忽略ARP获取W3 mac地址的过程),发送到Overlay交换机;
Step1.5:交换机查询“mac-VM ip-TEP ip”表(由NSX-t Controller集中收集、同步给每台PROD-Overlay-TZ),确定W3所在Overlay交换机的TEP地址,即tep4地址;
Step2:Overlay交换机对W1构造的原始报文,进行geneve封装(外层:”tep1 mac : tep1 ip -> tep4 mac : tep4 ip” + Geneve报头(VNI: 5000) + udp报头(目的端口6081),内层/udp负载:W1原始报文);
Step3:封装报文经过隧道,发送到tep4;
Step4:目标Overlay交换机对报文进行解封装,将W1原始报文发送给W3,通信完成。
实验环境中,即使tep1与tep4在同一个网段,那也需要在两端封装和解封装,因为它们虽然物理上在同一个网段,但是既然是通过ip地址访问,逻辑上使用的就是三层通信。
T1和T0,都是指路由器,区别在于T1用于转发单个租户的内部流量(东西向),就是说,它的端口仅仅会跟单个租户的不同segment相连,T0用于租户内部跟外部网络之间的流量(南北向),它一方面连接着多个租户的T1,另一方面与通往外部网络的物理路由器,连接在同一个网段。
比如,公司A的web服务器,要对外开放就必须跟T0路由器之间有连接,而DB服务器不希望暴露到外网,只要能与web服务器内部通信即可,那么它们之间仅用T1路由器连接即可。同理,假设公司B的2个部门使用不同的网段,仅通过T1路由器连接,就可以实现内部通信,如果还希望他们都能访问公司A的web服务,就必须还要将T1接到T0上。
虚拟路由器和虚拟交换机一样,也是由软件实现,其中,T1与TN是一一对应存在的,但不同的是,交换机是级联的关系,而路由器是重复的关系,理论上,在任意一台TN所在主机中安装T1路由器,就可以满足单个租户的东西向流量转发。
比如,如下物理拓扑中,仅ESXi04主机中安装了T1路由器,则:
(1) ESXi04内部,任意2个网段之间可以路由;
(2) ESXi04与ESXi05中的任意2个网段,也可以路由(ESXi04内部的Web-Segment网段与DB-Segment网段之间,可以通过T1路由器转发,剩下的就是Overlay二层转发过程,这已经在2.2.3节详细介绍过);
(3) SXi05内部,任意2个网段之间,也可以路由。
但是,对于情况(3),即使W2和D2两台虚拟机在同一宿主机,相互发给对方的报文,却要从外部绕一个大圈子,为此,在创建T1路由器时,NSX-t会在所有TN所在主机中安装(路由表会由NSX-t Controller集中同步),一方面避免了绕圈的情况,另一方面也起到容错的效果(比如情况(3), ESXi05主机会优先使用自己内部的T1,如果自己的T1出现故障,利用ESXi04中的T1,仍然可以路由)。
Edge Node
上述内容已经提到过,T0路由器需要连接的对象有2种:一是不同租户希望连接到外网的T1路由器,二是通往外部网络的物理路由器。根据这样的连接需求,NSX-t要求,必须将T0安装在一台独立的主机中,这种主机就是“Edge Node”,也就是说,“Edge Node”实际上就是一台主机,通常也是某台ESXi/KVM主机中的一台VM,只不过它专门用于安装T0路由器。
个人认为,这样是为了将T0路由器及其需要连接的网段,与宿主机系统中的业务资源隔离开,否则,原本要在Edge Node中添加的物理路由器所在网段,就得直接在宿主机中添加,直接暴露给T1路由器。
DR(分布式路由器)/ SR(服务路由器)
T1/T0路由器,都可以再继续细分为DR/SR路由器。
以上对T1的介绍,实际上只是T1-DR,NSX-t会为每台TN对应创建一个T1-DR,每台TN优先使用与自己在同一主机的T1-DR,进行三层转发,这样就不能对东西向流量进行集中的控制,比如像情况(2)那样,可以让所有东西向流量,只经过一台路由器。因此,NSX-t还可以创建T1-SR,从而可以为租户内部流量,提供负载均衡等服务,这也正是“服务路由器”这个名称的由来,不过,它和情况(2)对应的拓扑不同,首先,T1-SR不直接接入网段,而是和T1-DR相连,另外,它也不是直接在ESXi/KVM主机中创建,而是在Edge Node中创建。
T1-DR、T1-SR(可选)、T0-DR、T0-SR的安装位置:
建议对照这个规则,提前看一下2.3.5节中的物理拓扑图,了解一下两种实例场景中,4种路由器的具体安装位置。
根据拓扑可以看出,T0-DR是T1与T0-SR之间的桥梁,如果没有创建T1-SR,NSX-t会为每台T1-DR对应创建一台T0-DR,否则为每台T1-SR对应创建一台T0-DR,并且通过内部网段,建立它们到T0-SR的通信链路(我目前还没理解T0-DR存在的意义,总觉得它是多余的,不知道T1直接跟T0-SR接在同一个网段,会有什么问题)。而T0-SR很好理解,就是一边可以跟业务网段通信,一边可以跟外部网络通信。
最后需要特别了解的一点是,多台实际的DR,逻辑上相当于一台DR,所有端口的mac地址相同,每份路由表也是一样的。
创建T1网关 (分布式的,直接存在于ESXi/KVM/Edge等主机中)
|- NSX-t manager->Networking->Connectivity->Tier-1 Gateways->ADD TIER-1 GATEWAY
|- Tier-1 Gateway Name: T1-GW-01
|- Linked Tier-0 Gateway: 暂时不选 (将来选择T0-GW-01)
目的:用于东西向流量转发。
T1路由器接入segment
T1路由器接入Web-Segment
|- NSX-t manager->Networking->Connectivity->Segment
|- Web-Segment->Edit
|- Connectivity: T1-GW-01|Tier1
|- subnets: 172.16.10.1/24
T1路由器接入App-segment
|- NSX-t manager->Networking->Connectivity->Segment
|- App-Segment->Edit
|- Connectivity: T1-GW-01|Tier1
|- subnets: 172.16.20.1/24
T1路由器接入DB-segment
|- NSX-t manager->Networking->Connectivity->Segment
|- DB-Segment->Edit
|- Connectivity: T1-GW-01|Tier1
|- subnets: 172.16.30.1/24
目的:使Web-Segment、App-Segment、DB-Segment网段上的VM,可以跟T1二层通信。
物理拓扑
报文传送过程
比如:Web-Segment网段中的W1,访问App_Segment网段中的A1
Step1:W1发现A1和自己不在一个网段,所以构造“W1 mac : W1 ip -> T1 mac : A1 ip”报文(忽略ARP获取T1 mac地址的过程),通过交换机发送到T1路由器;
Step1.5:T1路由器查找路由表,确定下一跳出口;
Step2:由于下一跳出口已经和A1在一个网段,所以路由器构造“T1 mac : W1 ip -> A1 mac : A1 ip”报文(忽略ARP获取A1 mac地址的过程),通过交换机发送到A1。
理解了W1->A1(同一主机内部),再理解W1->W3(不同主机内部),就不难了:ESXi04主机内部,报文从Web-Segment网段,发送到App_Segment网段的过程,在两种情况中是没有区别的,报文最终再通过Overlay二层转发到W3,这已经在2.2.3节详细介绍过。
创建Edge虚机
|- NSX-t manager->System->Fabric->Nodes->Edge Transport Nodes->ADD EDGE VM
|- Name and Description
| |- Name: sa-nsxedge-01, sa-nsxedge-02
| |- Host name/FQDN: sa-nsxedge-01.vclass.local
| |- Form Factor: Medium
|- Credentials
| |- CLI User Name: *****
| |- CLI Password: *****
| |- System Root Password: *****
|- Configure Deployment
| |- Compute Manager: 选择sa-vcsa-01.vclass.local
| |- Cluster: 选择SA-Management-Edge
| |- Datastore: 选择SA-Shared-02-Remote
|- Configure Node Settings
| |- IP Assignment: static
| |- Management IP: 172.20.10.61/24
| |- Default Gateway: 172.20.10.10
| |- Select Interface
| | |- pg-SA-Management
| |- Search Domain Names: vclass.local
| |- DNS Servers: 172.20.10.10
| |- NTP Servers: 172.20.10.10
|- Configure NSX
|- New Node Switch
| |- Edge Switch Name: PROD-Overlay-NVDS
| |- Transport Zone: 选择PROD-Overlay-TZ
| |- Uplink Profile: 选择nsx-edge-single-nic-uplink-profile
| |- IP Assignment: 选择Use IP Pool
| |- IP Pool: 选择VTEP-IP-Pool
| |- Teaming Policy Switch Mapping
| |- uplink-1 (active): 选择pg-SA-Edge-Overlay
|- New Node Switch (点击ADD SWITCH)
|- Edge Switch Name: PROD-VLAN-NVDS
|- Transport Zone: 选择PROD-VLAN-TZ
|- Uplink Profile: 选择nsx-edge-single-nic-uplink-profile
|- Teaming Policy Switch Mapping
|- uplink-1 (active): 选择pg-SA-Edge-Uplinks
目的:为T0-SR提供安装场所(T1-SR、T0-DR也有可能安装在Edge Node中)。
创建Edge Node集群
创建Edge集群
|- NSX-t manager->System->Fabric->Nodes->Edge Cluster->ADD
|- Name: Edge-Cluster-01
|- Edge Cluster Profile: 选择nsx-default-edge-high-availability-profile # 定义2个Edge之间的心跳监测信息
|- 选择要添加到集群中的Edge
|- sa-nsxedge-01
|- sa-nsxedge-02
目的:相当于将多个Edge Node“打包”在一起(实验环境不考虑高可用,创建一个Edge Node即可,所以可以跳过这步操作)。
PROD-VLAN-TZ添加segment
添加T0-GW-01-Uplink-1
|- NSX-t manager->Networking->Segments->ADD
|- Segment Name: T0-GW-01-Uplink-1
|- Connectivity: 不填
|- Transport Zone: 选择PROD-VLAN-TZ
|- subnets: 不填
|- VLAN: 0
添加T0-GW-01-Uplink-2
|- NSX-t manager->Networking->Segments->ADD
|- Segment Name: T0-GW-01-Uplink-2
|- Connectivity: 不填
|- Transport Zone: 选择PROD-VLAN-TZ
|- subnets: 不填
|- VLAN: 0
目的:相当于在PROD-VLAN-TZ交换机上,划分了2个vlan:T0-GW-01-Uplink-1、T0-GW-01-Uplink-2(这两个网段,最终会和物理路由器所在网段级联,T0接入后,就可以和物理路由器二层通信)。
创建T0网关
创建T0网关 (集中式的,需要先创建Edge虚拟机)
|- NSX-t manager->Networking->Connectivity->Tier-0 Gateways->ADD GATEWAY->Tier-0
|- Tier-0 Gateway Name: T0-GW-01
|- HA Mode: 选择Active-Active
|- Edge Cluster: 选择Edge-Cluster-01 # 指定T0-GW-01路由器在哪个Edge虚拟机中创建
目的:用于南北向流量转发。
连接T1路由器与T0路由器
T1路由器连接到T0路由器
|- NSX-t manager->Networking->Connectivity->Tier-1 Gateways->Edit(T1-GW-01)
|- Linked Tier-0 Gateway: T0-GW-01
目的:以T0路由器为桥梁,间接连接到物理路由器,或者其它T1路由器(T0与T1之间的接口连接、ip配置,由NSX-t自动完成)。
T0-SR路由器添加接口,并与物理路由器接入同一网段
给T0-SR添加int1接口
|- NSX-t manager->Networking->Connectivity->Tier-1 Gateways->Edit (T1-GW-01)
|- INTERFACES->External and Service Interfaces->Set->ADD INTERFACES
|- Name: int1
|- IP Address / Mask: 192.168.100.2/24 # 配置ip
|- Connected To(Segment): T0-GW-01-Uplink-1 # 跟物理路由器接入同一网段
|- Edge Node: sa-nsxedge-01
给T0-SR添加int2接口
|- NSX-t manager->Networking->Connectivity->Tier-1 Gateways->Edit (T1-GW-01)
|- INTERFACES->External and Service Interfaces->Set->ADD INTERFACES
|- Name: int2
|- IP Address / Mask: 192.168.110.2/24 # 配置ip
|- Connected To(Segment): T0-GW-01-Uplink-2 # 跟物理路由器接入同一网段
|- Edge Node: sa-nsxedge-02
目的:使T0路由器,可以跟物理路由器二层通信。
同步路由表
将T1内部直连的业务网段路由通告给T0
|- NSX-t manager->Networking->Connectivity->Tier-1 Gateways->Edit (T1-GW-01)
|- Route advertisement
|- All Connected Segment & Service Ports: 开启
T1路由器添加int1/int2接口设置邻居
|- NSX-t manager->Networking->Connectivity->Tier-0 Gateways->Edit (T0-GW-01)
|- BGP
|- Local AS: 100
|- BGP Neighbors->Set
|- ADD BGP NEIGHBOR
| |- IP Address: 192.168.100.1
| |- Remote AS number: 200
| |- Source Addresses: 192.168.100.2
|- ADD BGP NEIGHBOR
|- IP Address: 192.168.110.1
|- Remote AS number: 200
|- Source Addresses: 192.168.110.2
将T1内部的业务网段路由通告给物理路由器
|- NSX-t manager->Networking->Connectivity->Tier-0 Gateways->Edit (T0-GW-01)
|- ROUTE RE-DISTRIBUTION->Set->ADD ROUTE RE-DISTRIBUTION
|- Nmae: 123
|- Set
|- Connected Interfaces & Segment: 选中
目的:更新T1、T0、物理路由器中的路由表。
AA:active-active
AS:active-standby
T1-DR与T1-SR、T1-DR与T0-DR、T1-SR与T0-DR、T0-DR与T0-SR之间,路由接口的创建、连接、ip分配,由NSX-t自动完成。
物理拓扑
2.3.4节的配置过程,没有包含:
(1) Edge-Overlay和Edge-uplink网段的创建(参照2.2.2节:PROD-Overlay-TZ添加segment);
(2) Edge Node的pg-SA-Edge-Overlay和pg-SA-Edge-Uplinks网卡的创建(Edge Node也是VM,右键选择“编辑虚拟机”,即可设置);
(3) pg-SA-Edge-Overlay和pg-SA-Edge-Uplinks网卡,分别连接到Edge-Overlay和Edge-uplink网段(参考2.2.2节:VM接入segment)。
实例1:T1-DR + T0-DR + T0-SR
实例2:T1-DR + T1-SR + T0-DR + T0-SR
路由表
实例1中各个路由器中的路由表如下(实例2略):
假设:W1(172.16.10.11)-> PC(172.20.10.80)
这里仅以实例1拓扑举例,实例2相比实例1,仅仅是三层转发过程中,多经过一下T1-SR(active-standby)路由器。
Step1:W1发现PC和自己不在一个网段,所以构造“W1 mac : 172.16.10.11 -> T1-DR mac : 172.20.10.80”报文(忽略ARP获取T1-DR mac地址的过程),通过交换机发送到T1-DR;
Step1.5:T1-DR查找路由表,命中“0.0.0.0/0 -> 100.64.32.1”,并根据ARP表或发送ARP请求,查询100.64.32.1的mac(AA);
Step2:T1-DR构造“T1-DR mac : 172.16.10.11 -> AA : 172.20.10.80”报文,发送到T0-DR;
Step2.5:T0-DR查找路由表,命中“0.0.0.0/0 -> 169.254.0.2 / 169.254.0.3”等价路径,假设本次选择169.254.0.2,并根据ARP表或发送ARP请求,查询其mac(BB);
Step3:T0-DR构造“AA : 172.16.10.11 -> BB : 172.20.10.80”报文;
Step4:T0-DR构造的报文穿过Overlay隧道,转发Edge Node中的交换机;
Step5:“AA : 172.16.10.11 -> BB : 172.20.10.80”报文,到达T0-SR1路由器;
Step5.5:T0-SR1查找路由表,命中“172.20.10.0/24 -> 192.168.100.1”,并根据ARP表或发送ARP请求,查询192.168.100.1的mac为CC;
Step6:T0-SR1构造“BB : 172.16.10.11 -> CC : 172.20.10.80”报文,发送到物理路由器;
Step7:物理路由器转发给外部PC。
https://space.bilibili.com/405480256?spm_id_from=333.905.b_7570496e666f.3
https://space.bilibili.com/618114154/?spm_id_from=333.999.0.0
看雪ID:jmpcall
https://bbs.pediy.com/user-home-815036.htm
# 往期推荐
球分享
球点赞
球在看
点击“阅读原文”,了解更多!