云计算是一种采用按量付费的模式,基于虚拟化技术,将相应计算资源(如网络、存储等)池化后,提供便捷的、高可用的、高扩展性的、按需的服务(如计算、存储、应用程序和其他 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网络与后,会创建一个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:
核心思想是解耦
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”.cookie(“csrftoken”)}
如果不想使用csrf防护,前端取消这个模板语法,后端在对应视图函数签名添加一个装饰器@csrf_execpt
即可。如果只删除前者不修改后者,访问会报错403未授权。
如果需要对整个网站取消CSRF,settings.py里面删除这个中间件即可。
在POST请求中设置请求参数csrfmiddlewaretoken
,否则会认为是恶意请求,需要获取这个控件的值。
如下
function submitForm(){
var csrf=$('input[name="csrfmiddlewaretoken"]').val();
...
$.ajax({
...
data:{
'csrfmiddlewaretoken':csrf,
...
}
...
})
}
k8s是为容器而生的一个可以指容器的编排管理工具,主要应用于云原生领域。
主要提供了以下几种功能:
集群主要由Master节点和Node节点组成。
Master节点是集群控制节点,接收控制命令进行具体执行,主要包括kube-controller-manager和kube-scheduler和etcd
,前者负责管理所有资源对象、维护集群状态(故障检测和自动扩展等);后者负责资源调度,按照相应策略将Pod调度到对应的机器上,主要包括kube-proxy代理pod网络定期从etcd获取service信息相应执行、kubelet作为agent接受分配pods任务和管理容器定期获取容器数据传给kube-apiserver
;etcd则负责保存整个集群的状态。
是自动化容器操作的开源平台,主要包括:部署、调度和节点集群间扩展
具体功能:
什么是容器编排
可以使用某种工具配置完成一组容器以及相应的资源如网络、CPU等资源的定义、配置、创建、删除等管理工作。
服务配置
Master节点部署
Node节点部署
Pod是k8s最基本的操作单元,包含一个或多个相关的容器,是最小部署单元,其实代表一个集群中运行的一个进程。
一个Pod可以被一个容器化的环境看成应用层的逻辑宿主机,一个Pod内的多个容器通常紧密耦合,在Node上被创建、启动或者销毁,每个Pod还运行一个特殊的Volume挂载卷,使得容器间数据通信比较方便。
同一个Pod的使用localhost就可以通信,共享一下五种资源:
kubernetes的控制器
称为工作负载,用于实现管理Pod的中间层,确保Pod的运行时符合预期的,以及出现故障后应该采取什么策略措施,比如重启或者重建。
Controller在集群上运行和管理各个Pod
Pod控制器实现Pod的运维,伸缩等
控制器类型
Replica Set和Replica Controller的区别
功能都差不多,都是保证一定数量的Pod的运行,不同之处在于两者对于Pods的复制策略不同。
前者使用基于集合的选择器,后者使用基于权限的选择器。
后者允许通过标签键值进行选择。
Set是更好的,可以对多个标签进行选择匹配
云控制器的理解
最初目的是使得云服务商的代码和k8s的核心代码独立解耦,使得云控制器可以和k8s的组件(controller manager或者api等)一起使用,也可以作为插件在k8s中使用。其设计是基于插件机制的,所以很容易和k8s集成
支持四种服务类型
什么是Headless Service
又叫无头服务,是一种特殊的服务类型。
ClusterIP是None,运行时不会给分配IP,可以通过查询Server的DNS获得所有Server和Pod的地址信息,可以根据自己的需求决定使用哪个Server
一般结合StatefulSet来部署有状态的应用,比如kafka集群,mysql集群,zk集群等
服务发现
k8s使用两种方式进行服务发现:
CNI
Container Network Interface,容器网络接口式Linux容器网络配置的一组标准和库,可以根据这些开发自己的容器网络插件。只专注于容器网络连接和容器销毁时的资源释放,支持大量不同的网络模式。
kuryr-libnetwork
四层、七层负载均衡
网络模型
每个Pod都有一个独立IP,不管是否运行在一个Node上的容器都可以通过IP直接访问
由docker0实际分配IP;内部看到的IP与端口和外部一致;同一个Pod内不同容器共享网络可以通过localhost通信,相当于一个虚拟机中的多个进程。
一些参考
Docker 核心技术与实现原理
Docker进阶之Cgroup介绍
CSDN的云原生入门技能树/容器(docker)/安装docker
这个在linux知识点章节有
当一个容器运行时,会创建一系列namespace,使用命名空间将容器间进行隔离。
命名空间的缺点:
隔离不彻底,因为还是共享宿主机的操作系统和内核,有可能通过容器的某些操作可以直接影响到宿主机(给应用暴露的攻击面太大)
有的资源没法进行命名空间隔离,比如修改容器的时间宿主机的时间也会修改。
可以对程序使用的资源进行限制。可以限制CPU、内存、磁盘读写速率、网络带宽等系统资源。Linux使用文件系统来实现Cgroups,cgroup是内核提供的分组化管理的功能和接口。
有如下几个特点:
cgroups是内核附加在程序上的一系列钩子,通过程序运行时对资源的调度触发相应的钩子以达到资源追踪和限制的目的。
提供以下几个功能:
有几个概念:
有几个规则关系:
子系统
有如下
比如对于cpu子系统,/sys/fs/cgroup/cpu
里面有一些控制组的文件,创建一个控制组文件夹以后,会出现一些文件。
限制一个指定进程的cpu使用配额
先添加进程PID,然后添加具体配置
echo 18828 >> /sys/fs/cgroup/cpu/cg1/tasks
//设置使用20%cpu
echo 20000 >> /sys/fs/cgroup/cpu/cg1/cpu.cfs_quato_us
在创建容器时,daemon会在单独挂载的子系统控制目录下创建一个对应的docker控制组,然后再创建一个容器控制组名为Docker ID,容器的所有进程好都会写在这个的tasks里面,在对应的控制文件里写相应的资源配额信息。
对于内存如果超过cgroup最大限制以后,如果设置了OOM Control(内存超限控制),进程就会收到OOM信号然后结束,否则会一直挂起,直到其他进程释放对应的内存资源。
cgroup.procs可以对线程进行配置,写入线程组中的第一个进程的PID,也就是把相关线程都加到cgroup里面
docker的daemon进程通过接收相应的API请求,然后将去转为使用相应的系统调用,从而创建和管理容器。docker将这些系统调用抽象为了一些操作接口方便调用,包括:容器执行驱动、volume存储驱动以及镜像存储驱动三种。
execdriver
对namesapce、cgroups等进行了二次封装,是默认的libcontainer库
volumedriver
负责volume的增删改查,屏蔽不同驱动带来的差异,为上层提供一个统一的接口调用。
graphdriver
和镜像有关,维护一个一组与镜像曾对应的目录,以及相应的元数据,用户对镜像的操作会对应位对这些目录文件以及元数据的增删改查,屏蔽不同文件存储实现带来的差异。
docker daemon的主要启动步骤如下三步
从client 到 daemon,docker run
举例
最后创建容器的时候会使用到libcontainer。
在准备好配置文件以后,会创建一个container对象,这里面存储的是配置信息的对象,然后才是有Container逻辑容器对象,libcontainer会根据信息创建相应的namespace,以及cgroups,然后创建docker。
Docker是一个容器化平台,以容器的形式将应用程序和其环境依赖打包,可以在任何Docker环境中无缝衔接运行
Docker不是虚拟化,依赖于实际实现基于容器的虚拟话或者操作系统级虚拟化的其他工具,最初使用LXC驱动,后来移动到libcontainer重命名为runc。
专注于应用程序容器内自动部署应用程序,应用程序指打包和运行一个应用程序,操作系统容器则设计为运行多个进程,如虚拟机。
特点:
资源管理通过cgroup实现,不允许容器消耗比cgroup规定还多的资源
虚拟机底层是需要使用hypervisor来模拟硬件虚拟化的,可以虚拟出一个操作系统所需的各种硬件资源比如cpu、ram、disk,在其上安装目标操作系统。
当一个程序代码被编译为二进制文件,然后这个文件被加载到内存然后得到cpu的使用权时,这个程序就变成了一个正在运行的进程,会去对寄存器进行操作,对堆栈进行操作以实现相应功能。
而容器则是通过约束和修改进程的动态表现,给其创造一个边界。cgroups主要用来进行约束,而namespace则主要用来创造边界
镜像就是容器的源代码,用于创建容器。
Docker容器包含了应用程序和其所需的以来,作为操作系统的一个独立进程运行的。
镜像保存在/var/lib/docker/
是基于UnionFs(联合文件系统),这是一种分层的、轻量级的而且高性能的文件系统,支持对文件系统的修改作为一次提交来一层一层提交,而且可以把不同目录挂载到同一个虚拟文件系统下。
实际上一次会加载多个文件系统,但是使用上只能看到一个文件系统,联合加载会把每层文件系统叠加起来,最终的文件系统就会包含所有的底层文件和目录。
实质上就是一层一层的文件系统。
所有docker都初始于一个基础镜像层,增加或者修改内容的时候,会在这个基础上新增一层。
举个例子
如果需要基于ubuntu18.04配置新镜像,第一层就是ubuntu18.04
我们需要安装python,第二层就是python包
我们需要安装一个安全补丁,这个补丁就是第三层
Docker镜像是只读的,在启动容器的时候,会把一个可写层加到镜像顶部,就是容器层,容器层。下面都是镜像层。
boot file system。有一个bootloader和kernel,loader负责加载kernel,linux刚系统的时候就会加载bootfs,docker的底层就是bootfs,bootfs加载完成以后,内核就在内存里了,内存的使用权就由bootfs交给内核了,然后就可以卸载bootfs了。
rootfs,root file system在bootfs之上,包含有linux中的/dev、/proc、/bin、/etc等标准目录和文件
,这个其实就是各种linux发行版。
对于精简os,rootfs只需要包含最基本的命令、工具和程序库,因为可以直接使用底层kernel,所以只需要rootfs,而对于不同的发行版,bootfs都是差不多的,所以可以公用
容器和镜像的区别其实就是容器会在最顶层有一个可写层,对于容器的所有写操作都会记录在这里面,容器删除的话这个可写层就删除了。
每个容器都有着自己的可写层,所以多个容器可以共享一个镜像
对于多个镜像来说,镜像的分层会出现公用的情况,所以不能单纯看docker images列出来的大小。
多个容器之间可以共享镜像,在启动容器的时候不必单独复制一份,而是把所有镜像层以只读的形式挂载到一个挂载点上,在最上层加一个可读写的容器层,在没有更改的时候所有容器共享一份数据,只有对文件系统进行修改的时候,会把相应的内容写到可读写层里,并且隐藏只读层里的老版本文件,用心的覆盖,减少了镜像对磁盘空间的占用和容器的启动时间。
Dockerfile 是一个用来构建镜像的文本文件,文本内容包含了一条条构建镜像所需的指令和说明。
FROM
:指定基础镜像,基于什么镜像LABEL
:指定镜像的标签RUN
:运行指定命令CMD
:启动容器的时候执行什么命令,类似自启动,如果有多个指令,只执行最后一条ENTRYPOINT
:类似于CMD指令,但是不会被覆盖掉, docker build -t {name}:{tag} .
最后的点就表示上下文路径。
docker在构造的时候会使用到本机文件,比如复制进去,他会在这个上下文路径中去寻找,把里面的文件都打包进去,不写就默认Dockerfile所在的目录。
步骤时:
COPY指的是从上下文目录中复制文件到容器里的指定路径。
ADD也是复制文件。
COPY的SRC只能是本地文件。
而且ADD会自动解压一些格式的文件gzip等,不解压的时候tar就不能复制进去,会使得构建失败。
ADD还可以给容器里添加远程文件。但是建议用curl或者wget命令下载文件,因为ADD的话会给镜像加一层,导致体积变大臃肿。
运行、退出、已暂停、重新启动
docker的网络部分已经被独立为libnetwork了。使用的CNM(容器网络芈姓)提供了多种网络接口可以使用。
daemon通过调用libnetwork对外提供的API完成网络的创建和管理,libcontainer则使用CNM。libcontainer里面提供了五种网络驱动可以使用,有三个核心组件。
驱动:
docker0本质上就是网桥,而且这里的网桥概念可以相当于时交换机,可以为连接在其上的设备进行数据帧的转发,容器的网卡eth0通过veth连接到docker0网桥上,不需要配置IP地址就可以进行数据帧的转发。
有4种类型,bridge、host、container以及none
bridge:默认情况创建容器是使用网桥bridge去连接,docker0,容器之间通过网桥通信。对外通信的话网桥会与宿主机进行一个IP转换。这里的虚拟连接也是使用类似与虚拟网线的那样,就虚拟机里面的eth0连接到网桥对应的veth。如果需要外部访问进来,得通过端口映射,然后使用宿主机的端口和这个映射的端口进行访问
host:会默认使用宿主机的网络,不会有自己的命名空间虚拟机网卡之类的,在网络上是没办法隔离的。使用了host就只能指定端口了,访问进来的话用宿主机的IP和这个映射的端口
container:指定新创建的容器和已有的容器共享namespace,同样不会自己创建网卡和IP地址,和这个特定容器一起共享,进程间通过lo通信。
none:会创建一个命名空间 ,但是ip、虚拟网卡之类的都得自己配置,很不好用不方便。但是隔离安全性非常好
docker images
:查看镜像docker rm / rmi
:删除容器/镜像docker pull / push
:拉取/上传镜像docker ps -a
:列出所有镜像,不带参数只列出开机镜像docker cp {path} {docker_id}:{docker_path}
:复制文件到指定容器的路径下,也可以返回来复制出文件docker run -d --name container cirros -p 5000:5050
:启动容器openstack server create --flaver {name} --nic net-id={network-id} --security-group {id} {name}
opensatck image create --disk-format qcow2 --container-format bare --public --file {local-path} {name}
glance image-download --file {id} {local-path}
deleting
状态一直卡住,这个操作可以使其变为活动状态,然后他大概会进入error
,然后就可以正常删除了。nova restet-state --active {server-id}
–availiable-zone {region}:{host}
,指定在哪个集群的哪个节点创建openstack console log {id}和openstack console url show {id}
在计算节点的/var/lib/nova/instances目录。
控制节点的/var/lib/glance/images目录。
对通过实例的流量进行标记和取消标记的操作,VLAN网络。
隧道桥(br-tun)根据 OpenFlow 规则将 VLAN 标记的流量从集成网桥转换为隧道 ID。
隧道桥允许不同网络的实例彼此进行通信。隧道有利于封装在非安全网络上传输的流量,它支持两层网络,即 GRE 和 VXLAN。
用于转发来往的网络流量,允许实例与外部网络进行通信
OpenStack是一个成熟的完整的云资源管理的平台。可以统一管理平台中的计算、存储以及网络等资源,提供对于虚拟机的调度管理。底层默认使用kvm和qemu去管理虚拟机,但是同样可以管理容器。
而docker则是负责管理计算机中需要与其他进程相互隔离的容器,容器的开销相比于虚拟机更少,本质上就是一个操作系统进程,可以将自己的环境或者应用程序部署在容器里,然后打包分发之类的,可以实现快速部署。
docker应该和虚拟机是一个类别的。
OpenStack本质只是一个云管理平台,不具备比如虚拟化这种功能。虚拟化是通过系统底层实现的hypervisior(kvm、qemu和Xen、virtual box等)实现的。
如果没有OpenStack同样可以使用其他工具来管理kvm,比如libvirt提供的vish-manager。
kvm是一个内核提供的轻量级虚拟化管理解决方案,需要虚拟化支持(Intel-VT或者AMD-V)。
Xen是运行支持的Xen内核,可以在系统上使用qemu模拟多个虚拟机。
kvm可以使用通常的linux调度和内存管理
Xen更新以后需要重新编译内核,而kvm只需要重新安装模块即可,更加精简,避免出错的几率。
vlan的vni是12位:1-4096,vxlan是24位,最大可以一一千六百多万个vni。
vxlan是基于隧道技术在屋里三层网络中模拟二层网络,对二层数据包的一个封装,使用UDP在三层网络进行一个转发。
vlan只能用于广播域的隔离,但是解决不了IP地址和MAC的重叠问题,vxlan可以做到不同租户独立组网,通信地址分配以及多租户的地址冲突问题可以解决。
交换机一个端口对应一个物理设备以及一个MAC地址,但是现在虽然一个端口还是连接一个物理机,但是可能会连接到多个虚拟机,传统交换机收到一个数据帧以后,根据vlan和目的MAC找到相应端口,将数据包转发出去。同时交换机会记住学习这个MAC记录,但是交换机内存是有限的,随着虚拟化的实现,网络中的MAC地址非常多的,交换机如果不足以支持的话,可能会移除,然后就不能正常工作,如果找不到MAC会进行flood,增加其他网络设备的负担和网络拥塞。
使用VxLAN,以太帧会被VTEP封装在UDP里面,一个VTEP可以被一个物理及的所有虚拟机使用,对于交换机,他看到的只是VTEP之间传递信息,并看不到实际虚拟机传递信息。所以交换机只需要记录VTEP的信息即主机信息即可。