赞
踩
云计算是一种采用按量付费的模式,基于虚拟化技术,将相应计算资源(如网络、存储等)池化后,提供便捷的、高可用的、高扩展性的、按需的服务(如计算、存储、应用程序和其他 IT 资源)。
云计算基本特征:
常见的部署模式
三种服务模式
云计算和虚拟化
云计算:IT能力服务化,按需使用,按量计费,多租户隔离,是一个系统的轻量级管理控制面。
虚拟化:环境隔离,资源复用,降低隔离损耗,提升运行性能,提供高级虚拟化特性。
虚拟化是实现云计算的技术支撑之一,但并非云计算的核心关注点。
IT架构的三个发展阶段
一个开源云操作系统内核,用于构建云平台,主要实现以下五个主要特点:
组件间交互是消息队列,组件内部交互是restful api。
Ⅰ型虚拟化是:hypervisor直接安装在物理机,就像是vmware的EXSi,底下是基于硬件层的
Ⅱ型虚拟化是:在物理机的正常操作系统,hypersivor作为一个程序模块运行管理虚拟机,如kvm,virtual box,vmware woerkstation。对硬件虚拟化特别优化,性能好,灵活性高。
基于linux内核实现的。有一个kvm.so,只需好管理虚拟cpu和内存等;IO外设交给linux内核和Qemu。
Libvirt是一个kvm管理工具,除了能管理kvm还可以xen,virtualBox,openstack底层也是libvirt。
libvirt:
kvm虚拟机是需要CPU硬件支持的,一个kvm虚拟机实质上就是一个qemu-kvm进程,一个vcpu对应一个进程里的一个线程。一个cpu可以调度进程里的多个线程,也就是cvpu数量实际上可以超过cpu,叫CPU超配。可以充分利用宿主机的资源。
通过内存虚拟化共享物理系统内存,动态分配给虚拟机。实现虚拟内存->物理内存->机器内存的映射。虚拟机系统只能实现虚拟内存到物理内存,最后一步无法真正访问机器内存,因此需要kvm进行一个映射。
存储虚拟化通过存储池和卷实现的,卷在虚拟机里就是一块硬盘。
Linex Bridge
是Linux上的TCP/IP二层协议交换设备,二层交换机,多个网络设备连接到同一个bridge时,有数据包传来beidge会转发给其他设备。
br-ctl show
查看当前网桥配置。
比如在eth0网卡上配置一个网桥br0,然后虚拟机的网卡可以选择br0,启动以后,br0底下会挂载一个inet0的设备,这就是虚拟机的虚拟网卡,但是在虚拟机内部来说虚拟网卡时eth0,inet0是在宿主机的时候标识的名称。
virbr0是kvm默认创建的一个Bridge,作用是给连接的虚拟网卡提供NAT访问外网的功能,默认192.168.122.1
,如果网络选择默认,就会挂载在这个上面。
virbr和br的区别:
VLAN
LAN是本地局域网,通产使用hub或者switch连接其中的主机。一个LAN是一个广播域,所有成员都能收到其他成员的广播包。
VLAN是Virtual LAN,一个带有VLAN功能的switch可以将端口划分出很多个LAN。可以将一个交换机划分为多个交换机,在二层进行隔离,隔离到不同VLAN中。
一般交换机端口有两种配置方式
总结:
是一个高性能分布式内存对象缓存系统,在OpenStack中用于缓存认证系统的令牌,减少高并发下对于数据库的访问压力,提高访问速度。
将需要存取的数据或对象缓存在内存中,内存中缓存数据可以通过API进行操作,数据经过Hash操作以后存在一个Hash表中,是K-V形式存储。
memcached没有访问控制和安全管理,因此需要使用防火墙等安全功能进行相应防护
使用最近最少使用算法LRU对最近不活跃的数据进行清理,从而得到新的内存空间。
对于大规模数据缓存有着较为明显的优势而且通过开放API多种语言可以直接操作memcached。OpenStack的keystone就是用memcached缓存租户的身份等信息、从而在租户登录验证的时候无需重复访问数据库即可查询得到相应数据。Horizon和Swift也用到了这个来进行数据的缓存以提高客户端的访问请求速率。
操作的过程
功能特点
缺点
是一个go语言开发的开源的高可用的K-V存储系统,用于配置共享和服务的注册和发现。
集群部署一般使用奇数个服务器配置,因为Raft决策时候需要多节点投票。
有几个特点:
应用场景
相比荣誉zookeeper和doozer,有如下特点:
rabbitmq属于AMQP(高级消息队列协议)的一种实现,应用层的一个开放标准。
特点:
AMQP的三大组件:
优点:
有几个概念关键词
log.#
,那么可以匹配log.
开头的routingkey系统可用性降低,rabbitmq挂了以后系统就崩了。
如何解决消息重复投递或者丢失的问题
如何解决消息按顺序发送的问题
给每一个消息设置一个类似唯一标识的一个ID,接收者去除消息以后先在数据库中对比一下是否存在,如果不存在,就正常消费。
还是使用一个ID,一般这个会出现在比如说订单的场景,生成订单,制作订单,订单号都是一样的,把这些消息投递到一个订单队列里面,取出的时候就是顺序的了。
restful api是一种软件架构设计的风格,不是标准,提供了一组设计的原则和约束条件,是一套编写接口的协议,协议规定如何编写,返回值和状态码等,主要用于客户端和服务器端的交互。
最显著的特点就是一个url可以通过不同的HTTP方法实现不同的功能,而no rest则需要使用多个url分别实现多个功能。
django中的erest框架叫django rest framework
能够生成符合restful规范的api
传统的URL需要在链接里加上操作的动作等;
而restful api则用URI统一资源标识符唯一标识服务器的一个资源,并且使用HTTP方法对其进行操作
提供一个Web前端控制台,从而实现通过web管理云平台,建云主机,分配网络,配安全组等。
Region(区域):地理上的概念可以理解为是两个不同区域的数据中心,是完全隔离的,但是可以共享同一套keystone和horizon了用户可以选择距离自己更近的域使用服务
端口
创建一个虚拟机大概的流程:
这里的消息发送全部都是通过消息队列实现的,进行异步调用,不会阻塞服务;解耦各个子模块功能;提高可扩展性;提高性能,可以处理多个请求,提高吞吐量
使用API的好处:
OpenStack的开放性,一个重要方面就是基于Driver的框架。比如说nov-acompute
中为hypervisor定义了统一的接口,支持多种Hypervisor,如Xen、VirtualBox、Hyper-V、Docker等
对外暴露若干个Restful API,用户可以发送请求到指定Endpoint
和虚拟机生命周期的指定请求nova-api都可以收到并处理。
在创建虚拟机的时候需要指定一个flavor也就是规格,其中规定了vcpu、ram、disk等参数,随后将falvor信息传入到noca-scheduler中,会根据flavor选择一个合适的节点创建虚拟机。
Filer scheduler是默认调度器,过程分为两步,第一是通过过滤器计算出满足条件的计算节点,通过权重计算,在权重最大(最优)的节点创建虚拟机。
同样可以使用第三方的scheduler,只需要配置一个scheduler_driver即可,再次体现出OpenStack开放性。
nova可以配置默认使用全部过滤器acheduler_availiable_filters
,但是真正使用到的是这个参数scheduler_default_filters
ram_allocation_ratio=1.5
,如果某个计算节点有10G内存,OpenStack会认为其有15G内存hypervisor_type=kvm
,那么使用这个镜像过滤就只能筛选出kvm的节点compute和hypervisor一起共同管理虚拟机生命周期。
定义了很多统一的接口,hypervisor实现这些接口就可以在openstack里面了。
一个计算节点只能指定一种虚拟类型。
主要有两种功能:
需要实时报告计算节点可用内存、vcpu等数量,scheduler才可有进行过滤调度的依据,通过hypervisor api获取虚虚拟机的资源信息。
管理生命周期包括如下:
在下载镜像的时候,如果存在就直接使用,会很快,不存在会先下载。比如是qcow2格式的镜像,由qemu-img转为raw格式然后进行backing file,这个不能是qcow2格式。
常用的5000端口,以及没怎么用过的35357端口
为OpenStack其他服务提供身份验证、服务规则和服务令牌的功能,管理Domains、Projects、Users、Groups、Roles。
/etc{service_name}/policy.json
监听端口:
传统的安装一个系统可能需要从CD或者ghost工具进行安装,非常繁琐。二运计算环境中有一个更高效地解决方案,就是Image。
每个Image中装有操作系统以及相应的配套软件环境,用户可以直接使用安装即可快速创建一个虚拟机。
比如云计算中可以有这么一个场景:当我们需要有一个新的系统需求的时候,我们可以先手动创建一个虚拟机然后安装好相应的操作系统和需要的软件环境,然后创建一个snapshot保存在云中,后续如果有用户需要使用可以直接使用这个snapshot快速创建虚拟机,这都是可以自动完成了。
为云主机提供不同系统镜像,支持多种虚拟机镜像格式(AKI、AMI、ARI、ISO、QCOW2、Raw、VDI、VHD、VMDK),有创建上传镜像、删除镜像、编辑镜像基本信息的功能。
glance-api对外提供restful api接口调用,当有请求来以后,api不会自己主动处理,而是会调用glance-registry处理有关元数据的操作,调用store backend处理有关镜像的操作。
Image默认存储在/var/lib/glance/images
。
glance-registry负责处理有关metadata的操作,如存取。比如image的大小或者类型,支持多种格式:QCOW2、RAW、vmdk、ISO等,元数据默认保存到mysql
store-backend:glance自己不保存镜像,而是使用backend存储,glance支持多种backend,如默认的local filesystem本地文件系统、ceph、swift、cinder、EXSI等
端口9292
提供云计算的网络虚拟化技术,为OpenStack其他服务提供网络连接服务。为用户提供接口,可以定义Network、Subnet、Router,配置DHCP、DNS、负载均衡、L3服务,网络支持GRE、VLAN。插件架构支持许多主流的网络厂家和技术,如OpenvSwitch。
根据网络类型的不同有以下几种网络:
网络转发
一般架构是控制节点、计算节点和网络节点。
网络节点就dhcp服务之类的,计算节点是各种agent,控制节点是neutron-server一个组件。
然后如果跨子网通信的话,流量需要从计算节点到网络节点,通过router路由一下,转发到对应的计算节点的实例上。而如果需要配置NAT的话是需要在router上面配置的,也就是网路节点,如果有需要流量转发出去的话,都需要通过网络节点。
但是这样的话网络节点的压力就比较大,一旦网络节点崩溃了,整个网络就崩了;还有一个就是即便两个实例在同一个计算节点上,如果不在一个网络中,还需要经过网络节点路由一下才能回来,很麻烦。
那么就有一个东西DVR(Distributed Virtual Routing),部署在计算节点,可以直接使用浮动IP访问外网,不需要经过网络节点了。是通过openflow规则进行判断的。
Neutron功能:
一些概念
Veth pair
Veth是linux系统虚拟出来的一个网络设备,总是成对出现的,功能类似虚拟网线的功能,在创建两个Veth设备,假设放在两个namespace里面,那么通过这个Veth设备可以实现相互通信,默认情况下是不通的。
通常链接网络的namespace,也链接linuxbridge,一般用于连接两个linuxbridge或者一个linuxbridge和ovs,两个ovs一般不太用这个,一般用patch连接两个ovs bridge,效率更好。
实际操作
在这里创建一个新的namespace,然后创建一对Veth pair试一下,单纯记录,我没有操作过。
#创建namespace ip netns add tns(tempnamespace) #创建Veth设备 ip link add tns-0 type veth peer name tns-1 #生效网卡 ipconfig tns-0 up或者ip link setet tns-0 up ipconfig tns-1 up #将一段veth pair 1放入namespace,并重命名为eth0,添加新的网络网卡接口 ip linhk set tns-1 netns tns ip netns exec tns-1 name eth0 #生效一下网卡 ip netns exec tns ip link set eth0 up ip netns exec tns ip link set lo up #设置一下新的Veth网卡设备的IP地址,随便写吧 ip netns tns ip addt add 10.254.1.1/24 dev eth0 ip addr add 10.254.1.2/24 dev tns-0 #现在可以验证连通性了验证 ip netns exec tns ping 10.254.1.1
TUN、TAP
Veth是两端都一样的虚拟网线,而这个就是两端都不一样的虚拟网先,相当于一边是水晶头,另一端是USB接口,是用户空间和内核空间传输报文使用到的“网线”,一边是普通的网卡比如eth0,另一端是文件描述符,用户空间使用的。
实例的本质是qemu进程,因此TUN、TAP网线一般是给VM用的,所以这个文件描述符一般是VM,另一端则是虚拟出来的TAP设备,这也就是为什么Neutron几种网络模型里面的VM或者linuxbridge连接router的时候都是通过TAP设备的
Bridge
是一种虚拟集线器的实现方式,多个网卡连接到这个上面,一个发送报文其他都能接收到。
把TUN/TAP或者Veth pair放在Bridge上面,就可以实现相互通信。Docker就是用linuxbridge将所有的容器连接在一起,bridge模式,就是docekr0网卡
Neutron主要有以下几个部分:
架构这么多层次有两个原因
plugin有一个功能时需要维护数据库中的网络状态信息,如果有多个插件的话,每一个provider的plugin都要写一套类似的数据库操作代码,会很繁琐,因此现有版本使用了ML2 plugin
,对plugin进行了抽象。只需要实现响应driver就行了,不需要具体实现plugin了。
plugin主要分为两种(均有对应的agent):
物理架构
有两种。
第一种:控制节点+计算节点
控制节点配置neutron server、core plugin、service plugin和两个对应的agent
计算节点配置core plugin的agrnt,负责二层网络功能。
通过agent实现控制节点和计算节点之间的二层网络通信,可以部署多个控制节点和计算节点
第二种:控制节点+网络节点+计算节点
控制节点配置neutron server
网络节点配置core plugin、service plugin和对应的agent
计算节点配置core plugin,负责二层网络功能
由上而下分别是
但是提出了两个问题
主要解决上面说的两个问题
允许网络中使用多种二层网络技术,不同节点直接按可以使用不同的网络实现机制。
可以在不同节点上使用不同的agent了,而且不用重新开发core plugin,实现mechanism driver就可以了。
ML2对二层网络进行了抽象解耦,type driver和mechanism driver
使得其具有非常好的弹性,能够灵活支持多种agent(type或者mechanism)
每一种网络都有这么两种driver
Type Driver
负责管理网络状态、创建网络等。
有这么集中网络类型:local、flat、vlan、vxlan、gre
mechanism driver
获取由type维护的网络状态,并且确保其在物理或者虚拟设备上的实现
比如创建一个VLAN100,VLAN的type driver负责将数据保存在数据库里,然后linux bridge的mechanism driver负责在各个节点上调用agent创建相应的vlan设备和bridge。
Mechanism Driver有三种:
local网络不会和任何物理网卡连接,也不会有VLAN ID。
对于每一个local网络都会创建一个网桥,将实例的tap设备绑定到网桥上。
同一网桥上的实例可以相互通信。每个local网络都有自己的网桥,互不影响,因此同一个节点上不同往前的实例不能通信。
其实只有admin创建网络可以选择type driver,普通用户在自己租户里创建网络的时候默认使用/etc/neutron/plugins/mk2/ml2_conf.ini
里面的一个参数tenant_networks_type=local
,默认是local,需要修改一下,可以指定多个,如vxlan,local
,会从左到右按照顺序依次创建,如果vxlan的id用完了,就会创建local。
命名
brqxxxxxx
对应的是网络,表明这是网络id为xxxxx创建的一个网桥
tapyyyyy
,其实就是虚拟机的一个虚拟网卡,对应的是port,说明这是id为yyyy的port的tap接口设备,tap将连接到brq上
在创建实例的时候,neutron-linubgridge-agent
根据port信息创建一个tap设备,连接到local网络所在的bridge网桥上。这个tap设备就会映射为实例的虚拟网卡。
不带tag的,要求和物理网卡连接,所以需要在ml2的配置文件里写physical_interface_mappings=default:thh0
,前面式一个label,用来标识flat,可以是任意字符粗汉,就是表明和物理网卡的对应关系,因为可能每个节点使用的物理网卡不一样,因此这里的default就映射为配置好的物理网卡。
如果不同节点的实例连接到同一个网络,他们所处的网桥名称一致,通过provider network通信。
vlan是带tag的网络。
如下所示,多个tap连接到brq网桥上。eth1网卡上创建了一个eth1.100的vlan interface接口,可以连接到这个brq上,然后通过eth1.100到eth1的数据包就会被标记一个100的vlan tag。
如果有多个eth1.xxx接口连载eth1网卡上,就可以通过这个tag标签相互隔离不同的vlan。
如果需要这么设置的话,物理机连接的交换机端口需要设置为trunk,不能是access,因为需要流过多个tag数据包
OpenStack支持VxLAN和GRE这两种overlay网络,overlay网络指建立在其他网络之上的网络。
linuxbridge只支持vxlan,ovs两个都支持。
优点
缺点
其实也是有一些缺点的
VxLAN是将二层建立在三层上的网络,把二层数据封装在UDP数据包里扩展二层网络。IP+UDP
通过DHCP agent实现DHCP服务。运行在网络节点,dnsmasq
当 创建一个网络的子网开启dhcp功能后,agent会启动一个dnsmasq进程提供服务,其实dnsmasq和network是对应的,一个进程可以给所有的子网提供dhcp服务。
通过dnsmasq
获取IP信息。
在创建实例的时候,实例会绑定一个port,有MAC和IP信息,dnsmasq会把这个记录在一个host文件里。
实例启动以后,会发送DHCPDISCOVER
广播,然后广播消息会在flat网络里传播,通过veth paur到达另一个namesapce里面,dhsmasq监听到了,然后返回对应的IP信息,DHCPOFFER
,包含IP地址、租期时间等给实例
最后实例返回一个DHCPREQUEST
消息接收DNSOFFER
。
二层网络上可以通过VLAN将物理交换机分割为多个虚拟交换机。
而namespace可以将物理的三层网络划分为多个隔离的虚拟三层网络,有这几个字的网络栈、防火墙规则、路由表等。
Neutron就是通过namespace为每个network提供DHCP服务和路由,让租户之间的网络可以重叠不冲突,提高了灵活性。
每个namesapce里有各自的dnsmasq,ip nets list
可以查看。
管理员可以将brq或者tap添加到某个namesapce里面。
如何让两个namespace相互通信呢
默认是不能通信的,Neutron里面使用了 veth pair
,相当于虚拟网线,连接两个namespace,这边输入另一边接收。
路由提供了跨子网的通信。这里有两个实例
vm1 - 172.16.100.3 - vlan100
vm3 - 172.16.101.3 - vlan101
这两个实例是两个不同vlan的,他们之间不能通过二层交换进行通信,必须借助router。
虚拟router由L3 Agent在控制节点或者网络节点运行。
通过配置一个router,vm1和vm3就可以进行通信了。
首先vlan101的bridge网桥上多了一个tap设备,这个设备就是路由器的interface接口
同样vlan100所在的网桥也有这么个接口设备。
L3 Agent会给每个router配置一个namespace,使用veth pair和tap设备连起来。对应的gateway ip在namesapce内的veth interface上。叫qr-…
其中namespace里的qr-xxxx
和tap-xxxx组成veth pair进行通信。
如下图所示
引入namespace而不直接使用网关的作用
为了使得租户之间的网络可以重叠提高灵活性。
不然如果A和B都有相同子网,只用网关的话需要在控制节点的路由表上加两项,而且目的IP可能一致,无法区分了。
给router配置好一个外部网络(一般是flat或者vlan类型)的网关以后,router多一个接口,通过这个接口可以连接到外网,ip比如是10.10.10.2。
然后连接外部网络的bridge的tap-xxxx设备,通过veth pair和路由器namesapce内的qg-xxxx接口连接
冷知识,router的内部网络的接口叫qr-xxxxx,外部网络叫qg-yyyyy
此时看ip nets exec qrouter-xxxx route
,会看到10.10.10.1有一个qg的接口。说明如果是外网流量的话,router会通过这个接口将流量转发到这个网关,然后到linuxbrige的brq网桥上转发到网卡上。。
从qg-xxxxx出去的话会进行一个SNAT的转换,将源IP修改为router的源IP 10.10.10.2,以便回来的时候可以找到路由器
SNAT可以让实例访问外网,但是还不能让外网访问实例,使用浮动IP可以解决这个。
floating ip可以提供一个一对一映射的静态NAT。
创建好一个floating ip以后,会配置到router的外网的qg接口,然后iptables会添加两个规则
让用户可以创建和管理防火墙,在子网的边界进行流量过滤。传统的防火墙是在网关上的,隔离子网,而这个是在router上配置的,控制租户网络进出的流量。
分为:
安全组的对象是虚拟网卡,L2 Agent实现,对通过iptables实现对实例虚拟网卡流量的过滤。而fwaas是配置在虚拟路由器上的,在到达安全组之前可以先过滤一下,但是同一个subnet内部的虚拟网卡间不会过滤,因为不通过router。
fwaas没有单独的agent,是在L3 Agent中配置的,driver为IP tables,要在service plugins启用fwaas。
FWaaS v2
上面说的是v1,Stein版本以后,v1废弃了,是v2了。
Firewall概念变为Firewall Group了,而且不像v1是唯一绑定一个路由器,v2需要指定路由器的某个接口。
可以同时管理ingress和egress进口和出口两种流量。v1则不区分,对双向流量进行过滤,安全组区分流量。
ovs是除了linuxbridge外的另一种虚拟化交换机技术。
安装ovs agent,修改ml2的mechanism_drivers
。
初始状态有三个网桥:
br-int
:连接所有虚拟机的虚拟网卡或和其他虚拟网络设备br-ex
:连接外部网络的网桥br-tun
:隧道技术用这个,比如VxLAN或者GRE计算节点没有br-ex,因为计算节点的外网流量是通过网络节点的虚拟路由器转发的,所以br-ex在网络节点上。
同样的local网络不会和网卡连接,流量被限制在宿主机内,只有同一个网桥上的才可以通信。
创建了一个local网络以后,br-int网桥上有一个tap设备,是dhcp的接口,tap设备是在这个命名空间里的。
创建一个实例以后,Neutron在子网subnet中创建一个port,分配IP和MAC,绑定在实例上,会创建一个tap-xxxx
设备作为实例的虚拟网卡。
然后在linuxbridge上创建一个qbr-xxxx
网桥,和tap设备相连。
然后通过veth pair连接到br-int,即qvb-xxxx与qvo-xxxx
。
为什么需要使用一个linuxbridge中转不能直接使用tap设备连接到br-int呢
因为ovs不支持将iptables规则放在与其相连的tap设备上,因此为了实现security group安全组的功能,需要引入linuxbridge作为一个中转
如下图所示
一个实例的网络设备连接情况如下(以次连接):
flat网络的话是不带tag的,而且一个flat网路需要和一个物理网卡相连。
这里在修改配置文件的bridge_mappings
的时候,不是标签:物理网卡了,而是标签:连接网卡的网桥名。
因此需要先创建一个br-eth1网桥,连接到物理网卡eth1。
此时在br-int和br-eth1会分别多出一个接口int-br-eth1和phy-br-eth1
,是patch类型的,用来连接br-int和br-eth1,可以访问外网。
如下所示
在linuxbridge里面用veth pair连接br-int和linuxbridge,而这里使用patch连接br-int和br-eth1。
veth pair 和 patch
两者都可以作为一个类似虚拟网线的功能连接网桥。
底层实现
创建一个flat网络与后,会创建一个dhcp的接口,tap-xxxx连接到br-int网桥。
创建一个虚拟机后,同样的,先创建一个tap设备作为虚拟机的虚拟网卡,然后连接到linuxbridge的qbr网桥上,然后qbr通过一对veth pair连接到br-int网桥。
ovs中是所有虚拟网卡都连接到br-int网桥,而linuxbridge里面则是不同VLAN连接到不同网卡的VLAN网桥。因此物理交换机连接eth1的口也要设置为trunk。
ovs通过flow rule对流过br-int的数据包进行转发处理,比如打上tag或者去掉tag等。
ovs-ofctl dump-flow
查看流规则。
比如br-eth1网桥的流规则如下,这里的in_port编号可以在ovs-ofctl show
查看到。
这里就是说从br-eth1网桥的phy-br-eth1(port=2)端口进来的vlan为1的数据包,修改vlan id为100然后发送出去
br-int网桥的规则同理
这里的tag和VLAN其实是不一样的,tag是ovs内部进行网络隔离使用的,在接收到数据包的时候,需要进行vlan的一个映射,Neutron维护VLAN ID的映射关系。
两个子网之间的实例通信需要使用路由器进行通信。
创建一个路由器以后,将 子网可以添加到路由器的接口上,接口的IP分别为子网的网关。
br-int网桥上多了两个接口port,叫qr-xxxx
。router也是运行在自己的namesapce里面。
如果路由器需要连接外网,需要绑定一个外部网关,然后router就多了一个接口10.10.10.2,用于连接外网。也就是路由器的qg-xxxx
接口。
可以设置VxLAN 的vni也就是tag,需要在配置文件的[ovs]
配置tunnel_bridge
。
br-int和br-tun是通过patch port连接的,其中patch-tun在br-int
上,patch-int在br-tun
上。
底层实现
创建网络以后,dhcp也会通过tap设备连接到br-int上。
实例的虚拟网卡tap设备还是连接到linuxbridge的网桥qbr上,通过veth pair(qvb和qvo)连接到br-int上。
而br-tun上则多了一个vxlan-xxxx
的东西,比如用于连接控制节点和计算节点的,制定了VTEP的IP。
此时br-int充当了一个二层交换机,查看flow rule以后可以看到是通过vlan和mac转发数据包的。
而br-tun的flow-rule才是进行真正转发数据包的。
为运行实例提供稳定持久化的数据块存储服务,如创建卷、删除卷,在实例上挂载和卸载卷。
cinder-api:接收http请求调用cinder-volume
cinder-volume:管理volume服务,管理卷的生命周期
cinder-schedule:通过算法为卷调度一个合适的节点
openstack租户管理_OpenStack容器服务Zun初探与原理分析
Keystone、Neutron以及Kuryr-libnetwork是运行Zun必备的服务。分别提供了身份认证以及网络的功能支持。
zun-api
负责接收api请求进行处理。
zun-compute
服务调用container driver
进行docker的创建,目前只实现了Docker Driver
。
流程步骤
zun/api/controllers/v1/containers.py
进行参数校验,如用户是否具有policy权限,网络、安全组、配额等是否符合。
zun/compute/api.py
先schedule调度一个合适的计算节点,返回host对象,这个功能集成在zun-api里面了。
检查镜像是否存在,远程调用zun-compute的image search
方法,其实就是调用了docker search
,为了实现快速失败,避免到计算节点才发现错误。
然后远程调用zun-compute进行后续工作
zun/compute/manager.py
创建卷或者挂载硬盘,然后下载镜像,创建端口,调用docker启动容器。
其中调用docker启动容器的操作的代码位于zun/container/docker/driver.py
,这个部分其实就是对于Docker SDK for python
的一个封装。
如import docker
这个项目的目的是将容器网络与neutron进行融合,提供接口南向连接neutron,北向连接容器网络。
开始目的是为了提供Docker与Neutron的连接。将Neutron的网络服务带给Docker。随着容器的发展,容器网络的发展也出现了分歧。主要分为两派,一个是Docker原生的CNM(Container Network Model),另一个是兼容性更好的CNI(Container Network Interface)。Kuryr相应的也出现了两个分支,一个是kuryr-libnetwork(CNM),另一个是kuryr-kubernetes(CNI)。
kuryr-libnetwork是运行在Libnetwork框架下的一个plugin,替换了原有的docker engine,成为一个kuryr就是libnetwork的一个remote-driver,现在是docker的推荐remote-driver。
其实实际上kuryr起了一个http服务,23750端口,提供了libnetwork的所有接口,docker找到以后通过这个与kuryr通信。
kuryr借用了neutron的subnetpool,保证了子网间ip的不重复
实现原理
在上面zun调用docker模块创建容器的时候,也会进行网络的配置,就在这里。
先检查docker网络是否存在,不存在就创建,创建的docker网络name就是neutron的uuid,会调用neutron创建一个port,即容器的port是zun创建的,不是kuryr创建的。
然后对于虚拟网卡,会虚拟出一个tap设备,其中容器内部命名空间有一个t_cxxxx的设备,两个通过veth pair连接起来。然后tap设备会连接到qbr的linuxbridge网桥,随后网桥通过qvb和qvo的veth连接到br-int集成网桥。
其实哦在那个接一下kuryr的作用就是把neutron的port绑定在容器上。
软件定义网络,是网络虚拟化的一种实现方式。
主要体现在如下三个方面:
OpenFlow是一种网上通信协议,属于数据链路层,允许控制器直接访问和操作网络设备的转发平面,借此改变数据包的走向。这些设备可以是物理设备也可以是虚拟交换机。
转发平面基于流的方式转发。
网络设备会维护若干个流表,数据流只按照流表进行转发,而流表的生成与维护都是控制器做的事。
这里的流表不仅仅是IP五元组,而是还有这一些关键词和执行动作等。在实际使用中可以根据需要的粒度进行一个限制,比如如果想要粗粒度,只需要设置IP就好了,不需要设置其他的参数比如端口之类的。
一个流表包含一个流表项的集合(包头域)、活动计数器以及一个操作集。
所有流过交换机的数据包都需要进行流表的匹配,如果匹配成功,执行相应的操作,如果没有匹配上,将其转发到控制器,由控制器决定如何处理这个数据包。
这个包头域会根据数据包的信息进行相应的匹配,使用的是12元组
活动计数器包含有多个计数器,会根据匹配的数据包进行一个更新。
操作集规定了对匹配成功数据包进行什么操作,可以有0到多个操作,如果没有相应操作,丢弃数据包。
一些基本的操作有:
还有一些可选的
主要添加了多级流表(流水线),增加了一些多控制器的支持,增加了对数据包处理的动作
一个流表项的组成
将原来的动作变更为指令,然后允许数据包在流表之间跳转。
不同于1.0的十二元组,这里其实有四十多个字段,但是一般大多数用不到,主要也就是那么些。
有一个指令是go-to-table:转向另一个流表
如果没有这个,会有以下几个动作
同时 还需要支持table-miss,就是说如果没有匹配成功,进行什么样的动作,转给控制器还是丢弃。
Django是一个开放源代码的web应用框架,使用python写成。本身是基于MVC模型的,实际采用了MTV的框架模式,即模型(Model)、模(Templates)板和视图(Views)。其中:
简单流程:
用户通过浏览器向我们的服务器发起一个请求(request),这个请求会去访问视图函数:
a.如果不涉及到数据调用,那么这个时候视图函数直接返回一个模板也就是一个网页给用户。
b.如果涉及到数据调用,那么视图函数调用模型,模型去数据库查找数据,然后逐级返回。
视图函数把返回的数据填充到模板中空格中,最后返回网页给用户。
Django的主要目的是简单快捷的开发数据驱动的网站,强调代码复用,多个组件可以很方便的以插件形式服务与整个框架。
有以下几个特点:
MVC:
核心思想是解耦
MVT:
views里处理业务逻辑比如登录验证、数据处理等
model里面不需要编写一句sql,ORM会自动转为sql去执行。
数据库里每一行数据就是一个对象,每一个表是一个集合,python用列表表示这个集合
template呈现页面,用css和js渲染html等
还需要一个 URL 分发器,它的作用是将一个个 URL 的页面请求分发给不同的 View 处理,View 再调用相应的 Model 和 Template,MTV 的响应模式如下所示
Django提供了更多的组件支持,让开发变得更加方便。
比如
Flask轻量级轻在它本身是一个内核,其他功能都需要扩展实现。比如可以引入其他模块实现ORM,也没有默认数据库,但是可以自行配置使用mysq或者nosql,性能比Django好。依赖于Werkzurg WSGI路由模块和jinja2模板。
对于路由的匹配
Tornado
功能少而精,非阻塞式异步设计方式。
Tornado是一个使用python开发的全栈式的web框架和一部网络库,使用非阻塞式IO,可以处理数以万计的开放链接,常用于long polling、web sockets和其他需要维护长连接应用的选择。
主要分为四个部分
tornado的性能比django和flask好就是因为其底层io处理机制是根本不同。
浏览器输入网址,发送请求到服务器
匹配路由
url经过uWSGI->WSGI,然后经过中间件的处理,在urls.py路由映射中找到一个匹配的路由,从上到下依次匹配,匹配一个就可以停了
视图处理
匹配到url以后,跳转到对应的视图函数进行相应的业务处理,比如操作数据库等
返回响应
先经过中间件对返回的数据再进行处理,然后返回相应的页面文件,由浏览器渲染以后显示给用户,同时将模板内容填充到html空白处。
一些额外的
在匹配路由的时候,有两种方式,是CBV、FBV
CBV,url匹配成功后会自动去找dispatch方法,然后Django会通过dispatch反射的方式找到类中对应的方法并执行,类方法执行完成以后,返回的结果回传给dispatch()
对应类的话如下所示
#urls.py
urlpatterns = [
url(r'^fbv/',views.fbv),
url(r'^cbv/',views.CBV.as_view()),
]
#views.py
form django.views import Views
class CBV(Views):
def get(self,request):
return render(request,'cbv/xx/html',context)
def post(self,request):
return HttpResponse('...')
面向资源是REST最明显的特征,资源是一种看待服务器的方式,将服务器看作是由很多离散的资源组成。每个资源是服务器上一个可命名的抽象概念。因为资源是一个抽象的概念,所以它不仅仅能代表服务器文件系统中的一个文件、数据库中的一张表等等具体的东西,可以将资源设计的要多抽象有多抽象,只要想象力允许而且客户端应用开发者能够理解。
可以使用URI统一资源标识符标记一个服务器的资源,通过不同的http方法对资源进行相应的操作。这里的资源可以是一个文本文件、视频、图片等。
符合REST架构设计的API就是restful api。
继承APIView
@api_view([‘POST’],[‘GET’])
在这个类中,传入的参数是rest framework的request实例
,不是django的httprequest
。
可以返回rest framework的resonse
,而不是HttpResponse
。
传入的请求可以进行一些认证
可以指定解析器Parser对传入的数据进行解析,如JSON、Form
等解析。
一些功能模块
认证、权限和频率
dispatch()方法中进行一个判定。
认证和权限需要检查request.user和request.auth
是否合法,是否允许请求。
网站访问量过大的时候,响应速度可能会大大降低,出现卡死的状况,可以使用缓存解决这类问题。
缓存是将一个请求的响应内容保存到内存、数据库、文件或者高速缓存系统(memcached),如果接下来一段时间再次来同一个请求,就不需要执行相应过程,只需要读取内存或者高速缓存系统就可以了。
Django提供5种缓存方式:
WSGI
是python定义实现的一个web服务器和web应用程序之间交互的一个接口,是一种规范,描述定义了服务器和应用程序之间通信的规范。
WSGI包括server和applicatioon两部分。
其中server负责接收客户端请求,把request转发给application,接收application的response返回给客户端。
WSGI其实是一种server和application解耦的规范,有多个实现server的服务器,也有多个可以实现WSGI application的框架,可以自由组合。比如uWSGI、Gunicorn就是实现了WSGI server,而Django和Flask则实现了WSGI application的框架,可以自由组合,比如uWSGI+Django。
WSGI除了监听端口进行解析http,还有流量转发和管理application进程。一般WSGI内置的WSGI server都是单进程,一次只能处理一个请求,而通用的比如gunicorn或者uwsgi都是pre fork模型,会有一个master进行监听,启动多个slave(一个slave就是一个WSGI application)处理请求。
uwsgi
也是一种协议,用于定义传输信息的类型,可以和nginx等代理服务器通信
uWSGI
是一个web服务器,实现了WSGI协议、uwsgi和HTTP协议,把接收到的HTTP协议转为支持的网络协议,比如可以转为WSGI协议,然后python可以直接使用。
比如可以使用nginx处理静态内容,使用uWSGI处理动态内容。
对于Django和Flask其实自己本身带有一个简单的WSGI server,一般用于服务器调试,生产环境下建议使用其他的,比如manage.py runserver
就是启动一个WSGI,只用于本地开发,生产环境建议nginx+uwsgi+django
介于request和response中间对数据处理的一个流程,用于全局范围改变django的输入和输出,中间件就是在视图函数执行之前或者之后可以执行额外的操作。
比如
中间件的五个方法:
process_request
:请求进来,进行认证等process_view
:路由匹配后得到视图函数process_exception
:异常的时候执行process_template_responseprocess
:渲染模板的时候执行process_response
:请求有响应的时候执行这五个方法分别大概以下功能
中间件
process_request(request)
:收到request以后,按照settings.py
文件中的中间件顺序依次执行,如果返回None,则继续,如果返回HttpResponse,就返回不继续了,也就是报错了process_view(request, view_func, view_args, view_kwargs)
:执行完上一步的方法以后,在url里面找到对应的视图函数,然后获取到相应参数,在执行视图函数之前执行这一步。如果返回为None,则继续执行这个方法剩下的操作,如果返回HttpResponse,不执行这个方法和视图函数,继续后面的函数process_exception(request, exception)
:如果执行视图函数出错,按照settings.py中的中间件顺序,倒序执行这个方法,如果返回None,就继续上一个方法的process_exception
方法,如果返回HttpResponse,则不会被调用。也就是说,如果没有响应,就说明报错,倒序一级一级报错,如果有返回值说明还是正常的,就继续往下执行后面两个函数process_template_response(request, response)
:response是视图或者某一中间件的返回,只有response实现了render才能执行,所有中间件的这个函数执行完了,调用render()方法process_response(request, response)
:在视图函数执行完以后执行,必须有响应HttpResponse有几个默认配置的中间件,主要功能如下
django.middleware.security.SecurityMiddleware
:防止xss脚本过滤的安全改进django.contrib.sessions.middleware.SessionMiddleware
:开始session会话支持,可以使用session,不开启就不能session保存数据django.contrib.messages.middleware.MessageMiddleware
:提供cookie的功能支持django.middleware.common.CommonMiddleware
:用来重写URL。如果APPEND_SLASH为True,那么URL末尾没有斜杠或者没有找到对应匹配的时候,会自动添加末尾斜杠;PREPEND_WWW为True则会将没有www.开头的URL重定向到同样的www.开头的URL路由django.middleware.csrf.CsrfViewMiddleware
:跨站请求伪造就不说了django.contrib.auth.middleware.AuthenticationMiddleware
:收到request后,可以对user对象添加相应的HttpRequest属性,表示当前用户身份呢CSRF跨站请求伪造,是一种对网站的恶意利用、窃取网站用户信息制造恶意请求。
为了防护这类攻击,在用户提交表单的时候,表单中会自动加入一个叫csrfmiddlewaretoken
的隐藏控件,后台也保存有这个控件的值,当请求到达后端时,服务器会检查这个值,如果匹配则进行后续处理,否则不处理。
原理:
csrfmiddlewaretoken
的隐藏控件,并设置一个值,然后同时保存在后台,这是一个随机生成的但是XSRF防护一般只适用于POST请求,不能防护GET,因为GET一般是制度性是访问网页资源,不会涉及资源的更新和修改等操作。
在前端的form表单中添加{% csrf_token %}
即可
data:{
csrfmiddlewaretoken:'{{csrf_token}}'
}
headers:{ “X-CSRFtoken”声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/不正经/article/detail/157867
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。