赞
踩
控制节点 devstack-controller 192.168.104.10
计算节点 devstak-compute 192.168.104.11
参考:https://www.xjimmy.com/openstack-5min-17.html
keystone user-list
:openstack user list
命令代替:CMD <obj>-create [parm1] [parm2]…
CMD <obj>-delete [parm]
CMD <obj>-update [parm1] [parm2]…
CMD <obj>-list
CMD <obj>-show [parm]
glance image-create
glance image-delete
glance image-update
glance image-list
glance image-show
# 网络相关操作
neutron net-create
neutron net -delete
neutron net -update
neutron net -list
neutron net –show
# 子网相关操作
neutron subnet-create
neutron subnet -delete
neutron subnet -update
neutron subnet -list
neutron subnet–show
nova boot
nova delete
nova list
nova show
CMD help [SUB-CMD]
例如查看 glance 都有哪些 SUB-CMD:
查看 glance image-update 的用法:
root@devstack-controller:~# source devstack/openrc admin admin //切换用户
root@devstack-controller:~# openstack catalog list //查询服务的Endpoint
/etc/glance/glance-api.conf
中配置的,在我们的 devstack 环境中,image 存放在控制节点本地目录 /opt/stack/data/glance/images/ 中:glance image-list
:admin 登录后,Project -> Compute -> Images:
点击右上角“Create Image”按钮,为新 image 命名:
这里我们上传一个 image。 点击“浏览”,选择镜像文件 cirros-0.3.4-x86_64-disk.img。cirros 是一个很小的 linux 镜像,非常适合测试用。 可以到http://download.cirros-cloud.net/下载。
格式选择 QCOW2:
如果勾选“Public”,该 image 可以被其他 Project 使用;如果勾选“Protected”,该 image 不允许被删除。
点击“Create Image”,文件上传到 OpenStack 并创建新的 image:
点击 image 的“cirros链接”:
显示详细信息
glance image-create --name cirros --file /tmp/cirros-0.3.4-x86_64-disk.img --disk-format qcow2 --container-format bare --progress
在创建 image 的 CLI 参数中我们用 –progress 让其显示文件上传的百分比 %。在 /opt/stack/data/glance/images/ 下查看新的 Image:
glance image-delete 镜像ID
:ps -elf|grep nova
来查看运行的 nova 子服务:nova service-list
查看 nova-* 子服务都分布在哪些节点上:Nova-api 是整个 Nova 组件的门户,所有对 Nova 的请求都首先由 nova-api 处理。
Nova-api 向外界暴露若干 HTTP REST API 接口。在 keystone 中我们采用openstack endpoint show nova
命令查询 nova-api 的 endponits。客户端就可以将请求发送到 endponits 指定的地址,向 nova-api 请求操作。
当然,作为最终用户的我们不会直接发送 Rest AP I请求。OpenStack CLI,Dashboard 和其他需要跟 Nova 交换的组件会使用这些 API。
Nova-api 对接收到的 HTTP API 请求会做如下处理:
1)检查客户端传入的参数是否合法有效 ;
2)调用 Nova 其他子服务的处理客户端 HTTP 请求 ;
3)格式化 Nova 其他子服务返回的结果并返回给客户端。
nova-api 接收哪些请求?
简单的说,只要是跟虚拟机生命周期相关的操作,nova-api 都可以响应。大部分操作都可以在 Dashboard 上找到。打开Instance管理界面:
点击下拉箭头,列表中就是 nova-api 可执行的操作。
OpenStack 用术语 “Instance” 来表示虚拟机。
重点介绍 nova-scheduler 的调度机制和实现方法:即解决如何选择在哪个计算节点上启动 instance 的问题。
创建 Instance 时,用户会提出资源需求,例如 CPU、内存、磁盘各需要多少。OpenStack 将这些需求定义在 flavor(配额) 中,用户只需要指定用哪个 flavor 就可以了。
可用的 flavor 在 System->Flavors 中管理:
Flavor 主要定义了 VCPU,RAM,DISK 和 Metadata 这四类。 nova-scheduler 会按照 flavor 去选择合适的计算节点。VCPU,RAM,DISK 比较好理解,而 Metatdata 比较有意思,我们后面会具体讨论。下面介绍 nova-scheduler 是如何实现调度的
在 /etc/nova/nova.conf 中,nova 通过 scheduler_driver,scheduler_available_filters 和 scheduler_default_filters这三个参数来配置 nova-scheduler。
Filter scheduler: Filter scheduler 是 nova-scheduler 默认的调度器,调度过程分为两步。1)通过过滤器(filter)选择满足条件的计算节点(运行 nova-compute);2)通过权重计算(weighting)选择在最优(权重值最大)的计算节点上创建 Instance。
Nova 允许使用第三方 scheduler,配置 scheduler_driver 即可。这又一次体现了OpenStack的开放性。Scheduler 可以使用多个 filter 依次进行过滤,过滤之后的节点再通过计算权重选出最适合的节点。
上图是调度过程的一个示例:最开始有 6 个计算节点 Host1-Host6;通过多个 filter 层层过滤,Host2 和 Host4 没有通过,被刷掉了;Host1,Host3,Host5,Host6 计算权重,结果 Host5 得分最高,最终入选。
Filter: 当 Filter scheduler 需要执行调度操作时,会让 filter 对计算节点进行判断,filter 返回 True 或 False。Nova.conf 中的 scheduler_available_filters 选项用于配置 scheduler 可用的 filter,默认是所有 nova 自带的 filter 都可以用于过滤操作。
另外还有一个选项 scheduler_default_filters,用于指定 scheduler 真正使用的 filter,默认值如下 :
Filter scheduler 将按照列表中的顺序依次过滤。 下面依次介绍每个 filter。
1)RetryFilter:
RetryFilter 的作用是刷掉之前已经调度过的节点。举个例子方便大家理解: 假设 A,B,C 三个节点都通过了过滤,最终 A 因为权重值最大被选中执行操作。但由于某个原因,操作在 A 上失败了。 默认情况下,nova-scheduler 会重新执行过滤操作(重复次数由 scheduler_max_attempts 选项指定,默认是 3)。那么这时候 RetryFilter 就会将 A 直接刷掉,避免操作再次失败。RetryFilter 通常作为第一个 filter。
2)AvailabilityZoneFilter:
为提高容灾性和提供隔离服务,可以将计算节点划分到不同的Availability Zone中。例如把一个机架上的机器划分在一个 Availability Zone 中。OpenStack 默认有一个命名为 “Nova” 的 Availability Zone,所有的计算节点初始都是放在 “Nova” 中。用户可以根据需要创建自己的 Availability Zone。
创建 Instance 时,需要指定将 Instance 部署到在哪个 Availability Zone中。
nova-scheduler 在做 filtering 时,会使用 AvailabilityZoneFilter 将不属于指定 Availability Zone 的计算节点过滤掉。
3)RamFilter:
RamFilter 将不能满足 flavor 内存需求的计算节点过滤掉。对于内存有一点需要注意: 为了提高系统的资源使用率,OpenStack 在计算节点可用内存时允许 overcommit(超配),也就是可以超过实际内存大小。 超过的程度是通过 nova.conf 中 ram_allocation_ratio 这个参数来控制的,默认值为 1.5。
其含义是:如果计算节点的内存有 10GB,OpenStack 则会认为它有 15GB(10*1.5)的内存。
4)DiskFilter:
DiskFilter 将不能满足 flavor 磁盘需求的计算节点过滤掉。Disk 同样允许 overcommit,通过 nova.conf 中 disk_allocation_ratio 控制,默认值为 1。
5)CoreFilter:
CoreFilter 将不能满足 flavor vCPU 需求的计算节点过滤掉。vCPU 同样允许 overcommit,通过 nova.conf 中 cpu_allocation_ratio 控制,默认值为 16。
这意味着一个 8 vCPU 的计算节点,nova-scheduler 在调度时认为它有 128 个 vCPU。需要提醒的是: nova-scheduler 默认使用的 filter 并没有包含 CoreFilter。 如果要用,可以将 CoreFilter 添加到 nova.conf 的 scheduler_default_filters 配置选项中。
6)ComputeFilter:
ComputeFilter 保证只有 nova-compute 服务正常工作的计算节点才能够被 nova-scheduler调度。ComputeFilter 显然是必选的 filter。
7)ComputeCapabilitiesFilter:ComputeCapabilitiesFilter 根据计算节点的特性来筛选。这个比较高级,我们举例说明。例如我们的节点有 x86_64 和 ARM 架构的,如果想将 Instance 指定部署到 x86_64 架构的节点上,就可以利用到ComputeCapabilitiesFilter。还记得 flavor 中有个 Metadata 吗,Compute 的 Capabilities就在 Metadata中 指定。
“Compute Host Capabilities” 列出了所有可设置 Capabilities。
点击 “Architecture” 后面的 “+”,就可以在右边的列表中指定具体的架构。
配置好后,ComputeCapabilitiesFilter 在调度时只会筛选出 x86_64 的节点。如果没有设置 Metadata,ComputeCapabilitiesFilter 不会起作用,所有节点都会通过筛选。
8)ImagePropertiesFilter:
ImagePropertiesFilter 根据所选 image 的属性来筛选匹配的计算节点。 跟 flavor 类似,image 也有 metadata,用于指定其属性。
例如希望某个 image 只能运行在 kvm 的 hypervisor 上,可以通过 “Hypervisor Type” 属性来指定。
点击 “+”,然后在右边的列表中选择 “kvm”。
配置好后,ImagePropertiesFilter 在调度时只会筛选出 kvm 的节点。如果没有设置 Image 的Metadata,ImagePropertiesFilter 不会起作用,所有节点都会通过筛选。
9)ServerGroupAntiAffinityFilter:
ServerGroupAntiAffinityFilter 可以尽量将 Instance 分散部署到不同的节点上。例如有 inst1,inst2 和 inst3 三个 instance,计算节点有 A,B 和 C。为保证分散部署,进行如下操作:
创建一个 anti-affinity 策略的 server group “group-1” :
请注意,这里的 server group 其实是 instance group,并不是计算节点的 group。
依次创建 Instance,将inst1, inst2和inst3放到group-1中:
因为 group-1 的策略是 AntiAffinity,调度时 ServerGroupAntiAffinityFilter 会将inst1, inst2 和 inst3 部署到不同计算节点 A, B 和 C。目前只能在 CLI 中指定 server group 来创建 instance。创建 instance 时如果没有指定 server group,ServerGroupAntiAffinityFilter 会直接通过,不做任何过滤。
10)ServerGroupAffinityFilter:
与 ServerGroupAntiAffinityFilter 的作用相反,ServerGroupAffinityFilter 会尽量将 instance 部署到同一个计算节点上。方法类似:
创建一个 affinity 策略的 server group “group-2”:
依次创建 instance,将 inst1, inst2 和 inst3 放到 group-2 中:
因为 group-2 的策略是 Affinity,调度时 ServerGroupAffinityFilter 会将 inst1, inst2 和 inst3 部署到同一个计算节点。创建 instance 时如果没有指定 server group,ServerGroupAffinityFilter 会直接通过,不做任何过滤。
Weight:
经过前面一堆 filter 的过滤,nova-scheduler 选出了能够部署 instance 的计算节点。如果有多个计算节点通过了过滤,那么最终选择哪个节点呢?Scheduler 会对每个计算节点打分,得分最高的获胜。打分的过程就是 weight,翻译过来就是计算权重值,那么 scheduler 是根据什么来计算权重值呢?目前 nova-scheduler 的默认实现是根据计算节点空闲的内存量计算权重值:空闲内存越多,权重越大,instance 将被部署到当前空闲内存最多的计算节点上。
日志:
1)整个过程都被记录到 nova-scheduler 的日志中。比如当我们部署一个 instance 时,打开 nova-scheduler 的日志 /opt/stack/logs/n-sch.log(非 devstack 安装其日志在 /var/log/nova/scheduler.log):
日志显示初始有两个 host(在我们的实验环境中就是 devstack-controller 和 devstack-compute1),依次经过 9 个 filter 的过滤(RetryFilter,AvailabilityZoneFilter,RamFilter,DiskFilter,ComputeFilter,ComputeCapabilitiesFilter,ImagePropertiesFilter,ServerGroupAntiAffinityFilter, ServerGroupAffinityFilter),两个计算节点都通过了。
2)那么接下来就该 weight 了:
可以看到因为 devstack-controller 的空闲内存比 devstack-compute1 多(7466 > 3434),权重值更大(1.0 > 0.4599),最终选择 devstack-controller。
注:要显示 DEBUG 日志,需要在 /etc/nova/nova.conf
中打开 debug 选项:
virsh nodeinfo
、virsh dominfo
等命令。 /opt/stack/logs/n-cpu.log
记录了整个操作过程。nova-compute 创建 instance 的过程可以分为 4 步:为 instance 准备资源;创建 instance 的镜像文件;创建 instance 的 XML 定义文件 ;创建虚拟网络并启动虚拟机。instances_path = /opt/stack/data/nova/instances
base_dir_name = _base
2015-12-10 20:46:49.566 DEBUG nova.virt.libvirt.config [req-5c973fff-e9ba-4317-bfd9-76678cc96584 None None] Generated XML ('<cpu>\n <arch>x86_64</arch>\n <model>Westmere</model>\n
<vendor>Intel</vendor>\n <topology sockets="2" cores="3" threads="1"/>\n
<feature name="avx"/>\n <feature name="ds"/>\n <feature name="ht"/>\n
<feature name="hypervisor"/>\n <feature name="osxsave"/>\n <feature name="pclmuldq"/>\n
<feature name="rdtscp"/>\n <feature name="ss"/>\n <feature name="vme"/>\n
<feature name="xsave"/>\n</cpu>\n',) to_xml /opt/stack/nova/nova/virt/libvirt/config.py:82
这条日志我们可以得知:代码模块是 nova.virt.libvirt.config,由此可知应该是 Hypervisor Libvirt 相关的操作;日志内容是生成 XML;如果要跟踪源代码,可以到/opt/stack/nova/nova/virt/libvirt/config.py 的 82 行,方法是 to_xml。
2015-12-10 20:46:49.671 ERROR nova.compute.manager[req-5c973fff-e9ba-4317-bfd9-76678cc96584 None None]No compute node record for host devstack-controller
这条日志我们可以得知:这是一个 ERROR 日志;具体内容是 “No compute node record for host devstack-controller”;该日志没有指明源代码位置。
fdisk -l是以列表的形式列出磁盘分区情况
:Migrate 操作会先将 instance 停掉,也就是所谓的“冷迁移”。
而 Live Migrate 是“热迁移”,也叫“在线迁移”,instance不会停机。
Live Migrate 分两种:
1)源和目标节点没有共享存储,instance 在迁移的时候需要将其镜像文件从源节点传到目标节点,这叫做 Block Migration(块迁移);
2)源和目标节点共享存储,instance 的镜像文件不需要迁移,只需要将 instance 的状态迁移到目标节点。
源和目标节点需要满足一些条件才能支持 Live Migration:
1)源和目标节点的 CPU 类型要一致;
2)源和目标节点的 Libvirt 版本要一致;
3)源和目标节点能相互识别对方的主机名称,比如可以在 /etc/hosts 中加入对方的条目;
4)在源和目标节点的 /etc/nova/nova.conf 中指明在线迁移时使用 TCP 协议;
5)Instance 使用 config driver 保存其 metadata。在 Block Migration 过程中,该 config driver 也需要迁移到目标节点。由于目前 libvirt 只支持迁移 vfat 类型的 config driver,所以必须在 /etc/nova/nova.conf 中明确指明 launch instance 时创建 vfat 类型的 config driver;
6)源和目标节点的 Libvirt TCP 远程监听服务得打开,需要在下面两个配置文件中做一点配置;
非共享存储 Block Migration:
我们先讨论非共享存储的 Block Migration流程图如下:1)向 nova-api 发送请求;2)nova-api 发送消息;3)nova-compute 执行操作。
1)向nova-api发送请求 :
客户(可以是 OpenStack 最终用户,也可以是其他程序)向API(nova-api)发送请求:“帮我将这个 Instance 从节点 A Live Migrate 到节点 B”
这里源节点是 devstack-compute1,目标节点是 devstack-controller,因为是非共享存储,记得将“Block Migration”勾选上。这里还有一个“Disk Over Commit”选项,如果勾选了此选项,nova 在检查目标节点的磁盘空间是否足够时,是以 instance 磁盘镜像文件定义的最大容量为准;否则,以磁盘镜像文件当前的实际大小为准。
查看日志 /opt/stack/logs/n-api.log:
2)nova-api 发送消息 :
nova-api 向 Messaging(RabbitMQ)发送了一条消息:“Live Migrate 这个 Instance” ;源代码在/opt/stack/nova/nova/compute/api.py,方法是 live_migrate:
3)nova-compute 执行操作 :
源和目标节点执行 Live Migrate 的操作过程如下:目标节点执行迁移前的准备工作,首先将 instance 的数据迁移过来,主要包括镜像文件、虚拟网络等资源,日志在 devstack-controller:/opt/stack/logs/n-cpu.log:
源节点启动迁移操作,暂停 instance:
在目标节点上 Resume instance:
在源节点上执行迁移的后处理工作,删除 instance:
在目标节点上执行迁移的后处理工作,创建 XML,在 Hypervisor 中定义 instance,使之下次能够正常启动。
Instance 在 Live Migrate 的整个过程中不会停机,我们通过 Ping 操作来观察:
可见在迁移过程中,Ping 进程没有中断,只是有一个 ping 包的延迟增加了。
共享存储 Live Migration:
有多种方式可以实现共享存储,比如可以将 instance 的镜像文件放在 NFS 服务器上,或者使用 NAS 服务器,或者分布式文件系统。作为学习和实验,这里我们采用 NFS 方案。其他共享存储方案对于 Live Migration 本质上是一样的,只是在性能和高可用性上更好。
1)搭建 NFS 环境
将 devstack-controller 作为 NFS 服务器,共享其目录 /opt/stack/data/nova/instances。devstack-compute1 作为 NFS 客户端将此目录 mount 到本机,如下所示:
这样,OpenStack 的 instance 在 devstack-controller 和 devstack-compute1 上就实现共享存储了。共享存储的迁移过程与 Block Migrate 基本上一样,只是几个环节有点区别:向 nova-api 提交请求的时候,不能勾选“Block Migrate”:
因为源和目标节点都能直接访问 instance 的镜像,所以目标节点在准备阶段不需要传输镜像文件,源节点在迁移后处理阶段也无需删除 instance 的目录。只有 instance 的状态需要从源节点传输到的目标节点,整个迁移速递比 Block Migration 快很多。
如上图所示,我们把对 Instance 的管理按运维工作的场景分为两类:常规操作和故障处理。
本节讨论 cinder-volume 和 nova-compute 如何将 volume attach 到 Instance。
tgtadm –lld iscsi –op show –mode target
看到已经将 1GB(1074MB)的 LV /dev/stack-volumes-lvmdriver-1/volume-1e7f6bd7-ce11-4a73-b95e-aabd65a5b188 通过 Target 1 export 出来了。fdisk -l
查看到 volume 已经 attach 上来,设备为 vdb:tgt-admin –show –mode target
,会看到计算节点作为 initiator 已经连接到 target 1。cinder-volume 刚刚创建 target 的时候是没有 initiator 连接的,大家可以将下面的截图与之前的日志做个对比。tgt-admin
命令删除 volume 对应的 target;日志文件为 /opt/stack/logs/c-vol.log。cinder backup-create vol-1 --force
命令。–force
选项。cinder-api 接收到 backup volume 的请求。日志文件在 /opt/stack/logs/c-api.log。2)cinder-api 发送消息:
cinder-api 发送 backup 消息。cinder-api 没有打印发送消息的日志,只能通过源代码查看
/opt/stack/cinder/cinder/backup/api.py,方法为 create:
3)cinder-backup 执行 backup 操作:
cinder-backup 收到消息后,通过如下步骤完成 backup 操作,日志为 /opt/stack/logs/c-vol.log。
i)启动 backup 操作,mount NFS。
ii)创建 volume 的临时快照。
iii)创建存放 backup 的 container 目录。
iv)对临时快照数据进行压缩,并保存到 container 目录。
v)创建并保存 sha256(加密)文件和 metadata 文件。
vi)删除临时快照。
Backup 完成后,我们可以查看一下 container 目录的内容:里面有三个文件,根据前面的日志我们可以知道:backup-00001,压缩后的 backup 文件。backup_metadata,metadata 文件。backup_sha256file,加密文件。
可以通过 cinder backup-list
查看当前存在的 backup:
另外我们采用cinder help backup-create
命令可以查看一下 cinder backup-create 的用法:
这里有--incremental
选项,表示可以执行增量备份。如果之前做过普通(全量)备份,之后可以通过增量备份大大减少需要备份的数据量,是个很不错的功能。
cinder backup-list
命令查看backup,采用cinder backup-restore 备份volume的ID
命令进行恢复:/opt/stack/data/nova/instances/<Instance ID>/disk
,例如:cinder-volume 支持多种 volume provider,前面我们一直使用的是默认的 LVM,本节我们将增加 NFS volume provider。虽然 NFS 更多地应用在实验或小规模 cinder 环境,由于性能和缺乏高可用的原因在生产环境中不太可能使用。
但是学习 NFS volume provider 的意义在于:
1)理解 cinder-volume 如何支持多 backend;
2)更重要的,可以理解 cinder-volume,nova-compute 和 volume provider 是如何协同工作,共同为 instance 提供块存储;
3)举一反三,能够快速理解并接入其他生产级 backend ,比如 Ceph,商业存储等。
下图展示了 cinder、nova 是如何与 NFS volume provider 协调工作的:
1)NFS Volume Provider:就是我们通常说的 NFS Server,提供远程 NFS 目录,NFS Clinet 可以 mount 这些远程目录到本地,然后像使用本地目录一样创建、读写文件以及子目录。
2)cinder-volume:存储节点通过 NFS driver 管理 NFS volume provider 中的 volume,这些 volume 在 NFS 中实际上是一个个文件。
3)nova-compute:计算节点将 NFS volume provider 存放 volume 的目录 mount 到本地,然后将 volume 文件作为虚拟硬盘映射给 instance。
这里有几点需要强调
1)在 Cinder 的 driver 架构中,运行 cinder-volume 的存储节点和 Volume Provider 可以是完全独立的两个实体。cinder-volume 通过 driver 与 Volume Provider 通信,控制和管理 volume。
2)Instance 读写 volume 时,数据流不需要经过存储节点,而是直接对 Volume Provider 中的 volume 进行读写。 正如上图所示,存储节点与 NFS Volume Provider 的连接只用作 volume 的管理和控制(绿色连线);真正的数据读写,是通过计算节点和 NFS Volume Proiver 之间的连接完成的(紫色连线)。这种设计减少了中间环节,存储节点不直接参与数据传输,保证了读写效率。
3)其他 Volume Provider(例如 ceph,swift,商业存储等)均遵循这种控制流与数据流分离的设计。
配置 NFS Volume Provider:
在实验环境中,NFS volume provider 的 NFS 远程目录为 192.168.104.11:/storage,cinder-volume 服务节点上 mount point 为 /nfs_storage。在 /etc/cinder/cinder.conf 中添加 nfs backend:
配置enabled_backends = lvmdriver-1,nfs
是 让 cinder-volume 使用 nfs backend。[nfs]中详细配置 nfs backend。包括:
a) 使用nfs_mount_point_base = /nfs_storage
命令,指定存储节点上 /nfs_storage 为 nfs 的 mount point。
b) 查看 /etc/cinder/nfs_shares 活动 nfs 共享目录列表。 nfs_shares_config = /etc/cinder/nfs_shares
,其内容为:
列表中只有 192.168.104.11:/storage。如果希望有多个 nfs 共享目录存放 volume,则可以添加到该文件中。
c) nfs volume driver。
volume_driver=cinder.volume.drivers.nfs.NfsDriver
d) 设置 volume backend name。在 cinder 中需要根据这里的 volume_backend_name 创建对应的 volume type,这个非常重要,volume_backend_name = nfs
。
重启 cinder-volume,cinder service-list 确认 nfs cinder-volume 服务正常工作:
创建 nfs volume type
打开GUI页面Admin -> System -> Volumes -> Volume Types,点击 “Create Volume Type”:
命名 nfs,点击“Create Volume Type”:
选择 nfs volume type,点击下拉菜单“View Extra Specs”:
点击“Create”,Key 输入 volume_backend_name ;Value 输入 nfs:
NFS volume provider 准备就绪,下一节我们将创建 NFS 为 backend 的 volume。
创建volume
1)创建 NFS volume 操作方法与 LVM volume 一样,唯一区别是在 volume type 的下拉列表中选择“nfs”:
点击“Create Volume”,cinder-api,cinder-scheduler 和 cinder-volume 共同协作创建 volume “nfs-vol-1”。这个流程与 LVM volume 一样。
2)分析 cinder-volume 的日志:
看看 NFS volume provider 是如何创建 volume 的,日志在 /opt/stack/logs/c-vol.log。
i)cinder-volume 也会启动 Flow 来完成 volume 创建工作,Flow 的名称为 volume_create_manager:
volume_create_manager 首先执行 ExtractVolumeRefTask, OnFailureRescheduleTask, ExtractVolumeSpecTask, NotifyVolumeActionTask 为 volume创建做准备。
ii)然后由 CreateVolumeFromSpecTask 真正创建 volume:
iii)首先 mount 远程 NFS 目录:
iv)执行 stat、du 命令检查 NFS 目录:
v)执行 truncate 创建 volume 文件:
vi)采用chmod ugo+rw
命令设置 volume 文件为可读写:
vii)create 操作完成:
viii)Volume 在 NFS 上以文件存在,命名为“volume-”:
ix)GUI volume 列表中可以看到新创建的 volume:
GUI volume 列表中可以看到新创建的 volume。
nova-compute 如何将“nfs-vol-1” attach 到“c2” :
通过日志分析,nova-compute 会将存放 volume 文件的 NFS 目录 mount 到本地 /opt/stack/data/nova/mnt 目录下,然后修改 instance 的 XML 将 volume 文件配置为虚拟磁盘,日志为 /opt/stack/logs/n-cpu.log。
1)通过 findmnt 和 mkdir 测试和创建 mount point:
2)mount NFS 目录:
3)更新 instance 的XML,将 volume 文件映射给 instance:
4)我们也可以通过 virsh edit 查看更新后的XML:
5)GUI 界面也会更新相关 attach 信息:
Project 1 : m Network 1 : m Subnet 1 : m Port 1 : 1 VIF m : 1 Instance
,即一个租户有多个网络,一个网络有多个子网,一个子网有多个端口,一个端口有一个虚拟网卡,一个虚拟机有多个虚拟网卡。virsh list
和 brctl show
输出如下 cirros-vm2 对于的 tap 设备为 tapa5bd3746-3f。--dhcp-hostsfile
:存放 DHCP host 信息的文件,这里的 host 在我们这里实际上就是 instance。dnsmasq 从该文件获取 host 的 IP 与 MAC 的对应关系。每个 host 对应一个条目,信息来源于 Neutron 数据库。对于 flat_net,hostsfile 是 /opt/stack/data/neutron/dhcp/f153b42f-c3a1-4b6c-8865-c09b5b2aa274/host,记录了 DHCP,cirros-vm1 和 cirros-vm2 的 interface 信息。--interface
:指定提供 DHCP 服务的 interface。dnsmasq 会在该 interface 上监听 instance 的 DHCP 请求。对于 flat_net,interface 是 ns-19a0ed3d-fe。或许大家还记得,之前我们看到的 DHCP interface 叫 tap19a0ed3d-fe(如下图所示),并非 ns-19a0ed3d-fe。qdhcp-<network id>
,例如 flat_net,我们有:ip netns list
命令列出所有的 namespace。ip netns exec <network namespace name> <command>
管理 namespace:Routing 功能概述:
1)路由服务(Routing)提供跨 subnet 互联互通功能。例如前面我们搭建了实验环境:
cirros-vm1 172.16.100.3 vlan100
cirros-vm3 172.16.101.3 vlan101
这两个 instance 要通信必须借助 router。 可以是物理 router 或者虚拟 router。
2)物理路由:
接入的物理 router 有两个 interface ip:
172.16.100.1 对应 vlan100 的网关。
172.16.101.1 对应 vlan101 的网关。
当 cirros-vm1 要跟 cirros-vm3 通信时,数据包的流向是这样的:a)因为 cirros-vm1 的默认网关指向 172.16.100.1,cirros-vm1 发送到 cirros-vm3 的数据包首先通过 vlan100 的 interface 进入物理 router。b)router 发现目的地址 172.16.101.3 与 172.16.101.1 为同一个 vlan,则从 vlan101 的 interface 发出。c)数据包经过 brq1d7040b8-01 最终到达 cirros-vm3。
3)虚拟路由:
虚拟 router 的路由机制与物理 router 一样,只是由软件实现。Neutron 两种方案都支持。如果要使用虚拟 router,需要启用 L3 agent。L3 agent 会在控制节点或者网络节点上运行虚拟 router,为 subnet 提供路由服务。
配置 L3 Agent:
1)Neutron 的路由服务是由 l3 agent 提供的,除此之外,l3 agent 通过 iptables 提供 firewall 和 floating ip 服务。
2)l3 agent 需要正确配置才能工作,配置文件为 /etc/neutron/l3_agent.ini,位于控制节点或网络节点上:
interface_driver 是最重要的选项,如果 mechanism driver 是 linux bridge,则:
interface_driver = neutron.agent.linux.interface.BridgeInterfaceDriver
;如果选用 open vswitch,则:interface_driver = neutron.agent.linux.interface.OVSInterfaceDriver
。
3)l3 agent 运行在控制或网络节点上:
可以看到 l3 agnet 已经正常启动。
创建 Router 连通 Subnet:
1)创建虚拟路由器“router_100_101”,打通 vlan100 和 vlan101。打开操作菜单 Project -> Network -> Routers:
2)点击 “Create Router” 按钮:
3)router 命名为 “router_100_101”,点击 “Create Router” 按钮确认:
4)router_100_101 创建成功:
5)接下来需要将 vlan100 和 vlan101 连接到 router_100_101 。点击 “router_100_101” 链接进入 router 的配置页面,在 “Interfaces” 标签中点击 “Add Interface” 按钮
6)选择 vlan101 的 subnet_172_16_101_0,点击 “Add Interface” 确认:
7)用同样的方法添加 vlan100 的 subnet_172_16_100_0:
完成后,可以看到 router_100_101 有了两个 interface,其 IP 正好是 subnet 的 Gateway IP 172.16.100.1 和 172.16.101.1。
8)router_100_101 已经连接了 subnet_172_16_100_0 和 subnet_172_16_101_0。router_100_101 上已经设置好了两个 subnet 的 Gateway IP。cirros-vm1 和 cirros-vm3 应该可以通信了。通过 PING 测试一下:
9)查看 cirros-vm1 的路由表,默认网关为 172.16.100.1。同时 traceroute 告诉我们,cirros-vm1 确实是通过 router_100_101 访问到 cirros-vm3 的:
虚拟 Router 原理分析:
1)首先我们查看控制节点的 linux bridge 结构发生了什么变化:
vlan101 的 bridge 上多了一个 tape17162c5-00,从命名上可以推断该 TAP 设备对应 router_100_101 的 interface (e17162c5-00fa)。vlan100 的 bridge 上多了一个 tapd568ba1a-74,从命名上可以推断该 TAP 设备对应 router_100_101 的 interface (d568ba1a-740e)。
2)当前网络结构如图所示:
3)两个 TAP 设备上并没有配置相应的 Gateway IP:
4)如果没有 Gateway IP,router_100_101 是如何完成路由的呢?
答案是:l3 agent 会为每个 router 创建了一个 namespace,通过 veth pair 与 TAP 相连,然后将 Gateway IP 配置在位于 namespace 里面的 veth interface 上,这样就能提供路由了。
5)通过 ip netns
查看 namespace:router 对应的 namespace 命名为 qrouter-<router id>
。
6)通过 ip netns exec <namespace name> ip a
命令查看 router_100_101 namespace 中的 veth interface 配置:
namespace 中有两个 interface:qr-e17162c5-00 上设置了 Gateway IP 172.16.101.1,与 root namespace 中的 tape17162c5-00 组成 veth pair。qr-d568ba1a-74 上设置了 Gateway IP 172.16.100.1,与 root namespace 中的 tapd568ba1a-74 组成 veth pair。
7)网络结构如图所示:
8)namespace 中的路由表也保证了 subnet_172_16_100_0 和 subnet_172_16_101_0 之间是可以路由的,命令为ip nets exec <namespace name> IP routing table
:
为什么要使用Namespace:
1)为什么不直接在 tape17162c5-00 和 tapd568ba1a-74 上配置 Gateway IP,而是引入一个 namespace,在 namespace 里面配置 Gateway IP 呢?首先考虑另外一个问题:如果不用 namespace,直接 Gareway IP 配置到 tape17162c5-00 和 tapd568ba1a-74 上,能不能连通 subnet_172_16_100_0 和 subnet_172_16_101_0 呢?
答案是可以的,只要控制节点上配置了类似下面的路由:
既然不需要 namespace 也可以路由,为什么还要加一层 namespace 增加复杂性呢?其根本原因是:增加namespace是为了支持网络重叠。 云环境下,租户可以按照自己的规划创建网络,不同租户的网络是可能重叠的。 将路由功能放到 namespace 中,就能隔离不同租户的网络,从而支持网络重叠。
2)通过例子进一步解释:A,B 两个租户定义了完全相同的两个 subnet,网络完全重叠。如下图所示:
3)不使用namespace的场景:
其特征是网关 IP 配置在 TAP interface 上。因为没有 namespace 隔离,router_100_101 和 router_102_103 的路由条目都只能记录到控制节点操作系统(root namespace)的路由表中,内容如下:
这样的路由表是无法工作的。按照路由表优先匹配原则,Tenant B 的数据包总是错误地被 Tenant A 的 router 路由。例如 vlan102 上有数据包要发到 vlan103。选择路由时,会匹配路由表的第二个条目,结果数据被错误地发到了 vlan101。
4) 使用 namespace 的场景:如果使用 namespace,网络结构如下:
其特征是网关 IP 配置在 namespace 中的 veth interface 上。每个 namespace 拥有自己的路由表。router_100_101 的路由表内容如下:
router_102_103 的路由表内容如下:
这样的路由表是可以工作的。例如 vlan102 上有数据包要发到 vlan103。选择路由时,会查看 router_102_103 的路由表, 匹配第二个条目,数据通过 qr-4 被正确地发送到 vlan103。同样当 vlan100 上有数据包要发到 vlan101时,会匹配 router_100_101 路由表的第二个条目,数据通过 qr-2 被正确地发送到 vlan101。可见,namespace 使得每个 router 有自己的路由表,而且不会与其他 router 冲突,所以能很好地支持网络重叠。
instance访问外网 ML2 的配置:
1)这里的外部网络是指的租户网络以外的网络。租户网络是由 Neutron 创建和维护的网络。 外部网络不由 Neutron 创建。如果是私有云,外部网络通常指的是公司 intranet;如果是公有云,外部网络通常指的是 internet。具体到我们的实验网络环境: 计算节点和控制节点 eth1 提供的是租户网络,IP 段租户可以自由设置。 控制节点 eth2 连接的就是外部网络,IP 网段为 10.10.10.0/24。如下图所示:
2)配置准备:为了连接外部网络,需要在配置文件中告诉 Neutron 外部网络的类型以及对应的物理网卡
因为外部网络是已经存在的物理网络,一般都是 flat 或者 vlan 类型。这里我们将外部网络的 label 命名为 “external”。
如果类型为 flat,控制节点 /etc/neutron/plugins/ml2/ml2_conf.ini 配置如下:
如果类型为 vlan,配置如下
修改配置后,需要重启 neutron 的相关服务。在我们的网络环境中,外部网络是 flat 类型。
创建外网 Ext_net:
1)进入 Admin -> Networks 菜单,点击 “Create Network” 按钮:
2)显示创建页面,点击 “Create Network”,ext_net 创建成功,其中Provider Network Type 选择 “Flat”;Physical Network 填写 “external”,与 ml2_conf.ini 中 flat_networks 参数的设置保持一致;勾选 External Network 选择框。
3)点击 ext_net 链接,进入 network 配置页面:
4)目前还没有 subnet,点击 “Create Subnet” 按钮:
5)创建 subnet_10_10_10_0,IP 地址为 10.10.10.0/24,点击 “Next”。这里 Gateway 我们使用默认地址 10.10.10.1。
通常我们需要询问网络管理员外网 subnet 的 Gateway IP,然后填在这里:
6)因为我们不会直接为 instance 分配外网 IP,所以一般不需要 enable DHCP,点击 “Create”:
7)subnet 创建成功,网关为 10.10.10.1:
8)查看控制节点网络结构的变化,执行 brctl show:
增加了一个网桥 brqe496d3d2-53,物理网卡 eth2 已经连接到该 bridge。
外网访问原理分析:
1)将外网连接到 Neutron 的虚拟路由器,这样 instance 才能访问外网 。点击菜单 Project -> Network -> Routers 进入 router 列表,点击 router_100_101 的 “Set Gateway” 按钮:
2) “External Network” 下拉列表中选择 ext_net,点击 “Set Gateway” :
3)外网设置成功:
4) 我们需要看看 router 发生了什么变化 。点击 “router_100_101” 链接,打开 “Interfaces” 标签页:router 多了一个新的 interface,IP 为 10.10.10.2。 该 interface 用于连接外网 ext_net。
5)查看控制节点的网络结构,外网 bridge 上已经连接了 router 的 tap 设备 tapb8b32a88-03:
6)ip netns list
命令列出所有的 namespace。在 router 的 namespace 中查看 tapb8b32a88-03 的 veth pair 设备:
该 veth pair 命名为 qg-b8b32a88-03,上面配置了 IP 10.10.10.2。router 的每个 interface 在 namespace 中都有对应的 veth。如果 veth 用于连接租户网络,命名格式为 qr-xxx,比如 qr-d568ba1a-74 和 qr-e17162c5-00。如果 veth 用于连接外部网络,命名格式为 qg-xxx,比如 qg-b8b32a88-03。
7)查看 router 的路由表信息:
可以看到默认网关为 10.10.10.1。 意味着对于访问 vlan100 和 vlan101 租户网络以外的所有流量,router_100_101 都将转发给 ext_net 的网关 10.10.10.1。
8)现在 router_100_101 已经同时连接了 vlan100, vlan101 和 ext_net 三个网络,如下图所示:
9)下面我们在 cirros-vm3 上测试一下:irros-vm3 位于计算节点,现在已经可以 Ping 到 ext_net 网关 10.10.10.1 了。
10)通过 traceroute 查看一下 cirros-vm3 到 10.10.10.1 的路径 :
数据包经过两跳到达 10.10.10.1 网关。数据包首先发送到 router_100_101 连接 vlan101 的 interface(172.16.101.1)。然后通过连接 ext_net 的 interface(10.10.10.2) 转发出去,最后到达 10.10.10.1。
当数据包从 router 连接外网的接口 qg-b8b32a88-03 发出的时候,会做一次 Source NAT,即将包的源地址修改为 router 的接口地址 10.10.10.2,这样就能够保证目的端能够将应答的包发回给 router,然后再转发回源端 instance。
11)可以通过 iptables 命令查看 SNAT 的规则:
当 cirros-vm3(172.16.101.3) Ping 10.10.10.1 时,可用通过 tcpdump 分别观察 router 两个 interface 的icmp 数据包来验证 SNAT 的行为。
12)vlan101 interface qr-e17162c5-00 的 tcpdump 输出:
13)ext_net interface qg-b8b32a88-03 的 tcpdump 输出:
SNAT 让 instance 能够直接访问外网,但外网还不能直接访问 instance。因为 instance 没有外网 IP。这里 “直接访问 instance” 是指通信连接由外网发起,例如从外网 SSH cirros-vm3。 这个问题可以通过 floating IP 解决,下一节我们将讨论浮动 IP。
创建 Floating IP:
1)先复习一下前面我们讨论的知识:
当租户网络连接到 Neutron router,通常将 router 作为默认网关。当 router 接收到 instance 的数据包,并将其转发到外网时:a)router 会修改包的源地址为自己的外网地址,这样确保数据包转发到外网,并能够从外网返回。b)router 修改返回的数据包,并转发给真正的 instance。这个行为被称作 Source NAT。
如果需要从外网直接访问 instance,则可以利用 floating IP。下面是关于 floating IP 必须知道的事实:a)floating IP 提供静态 NAT 功能,建立外网 IP 与 instance 租户网络 IP 的一对一映射。b)floating IP 是配置在 router 提供网关的外网 interface 上的,而非 instance 中。c)router 会根据通信的方向修改数据包的源或者目的地址。
2)下面我们通过实验深入学习 floating IP 。点击 Project -> Compute -> Access & Security 菜单,打开 Floating IPs 标签页点击 “Allocate IP To Project” 按钮:
3)floating IP Pool 为 ext_net,点击 “Allocate IP” 按钮:
从 Pool 中成功分配了一个 IP 10.10.10.3。
4)下面我们将它分配给 cirror-vm3,点击 “Associate” 按钮:
5)在下拉列表中选择 cirror-vm3,点击 “Associate” 按钮:
6)分配成功,floating IP 10.10.10.3 已经对应到 cirros-vm3 的租户 IP 172.16.101.3:
7)执行ip netns exec <namespace> ip a
首先查看 router 的 interface 配置:
可以看到,floating IP 已经配置到 router 的外网 interface qg-b8b32a88-03 上。
8)执行ip netns exec <namespace> iptables -t nat -S
查看 router 的 NAT 规则:
iptables 增加了两条处理 floating IP 的规则: a)当 router 接收到从外网发来的包,如果目的地址是 floating IP 10.10.10.3,将目的地址修改为 cirros-vm3 的 IP 172.16.101.3。这样外网的包就能送达到 cirros-vm3。b)当 cirros-vm3 发送数据到外网,源地址 172.16.101.3 将被修改为 floating IP 10.10.10.3。
9)在我的实验环境中,10.10.10.1 是外网中的物理交换机,现在让它 PING cirros-vm3,能PING通:
10)ext_net interface qg-b8b32a88-03 的 tcpdump 输出:
可见,在外网接口 qg-b8b32a88-03 上,始终是通过 floating IP 10.10.10.3 与外网通信。
11)vlan101 interface qr-e17162c5-00 的 tcpdump 输出:
当数据转发到租户网络,地址已经变为 cirros-vm3 的租户 IP 172.16.101.3 了。
12)小结:
a)floating IP 能够让外网直接访问租户网络中的 instance。这是通过在 router 上应用 iptalbes 的 NAT 规则实现的。
b)floating IP 是配置在 router 的外网 interface 上的,而非 instance,这一点需要特别注意。
至此,我们已经完成了 Neutron L3 服务连接不同 subnet,访问外网,以及 floating IP 的学习。
brctl show
,查看当前的网络结构:ip -d link show dev vxlan-100
查看 vxlan interface 的详细配置ip -d link show dev vxlan-100
命令,发现创建的 vxlan-100 会多一个 Proxy ARP 功能:bridge fdb show dev vxlan-100
命令查看控制节点上的 forwarding database,可以看到 VTEP 保存了 cirros-vm2 的 port 信息:bridge fdb show dev vxlan-100
命令查看计算节点上的 forwarding database:Manage Rules
按钮,查看 “default” 安全组的规则:iptables-save
命令查看相关规则。iptables 的规则较多,这里我们节选了 cirros-vm1 相关的规则。这些规则是 Neutron 根据安全组自动生成的。cirros-vm1 的 TAP interface 为 tap8bca5b86-23,可以看到:Manage Group
按钮,查看 “allow ping & ssh” 的规则:Add Rule
按钮,添加允许 ping 的规则,“Rule” 选择 “All ICMP”,“Direction” 选择 “Ingress”,然后点击 “Add” 按钮:
6)同样的方式添加 ssh 规则:
7)在列表中查看添加成功的规则:
8)接下来设置 cirros-vm1,使用新的安全组 。进入 instance 列表页面,点击 cirros-vm1 下拉操作列表中的 “Edit Security Groups”:
9)可以看到 cirros-vm1 当前使用的安全组为 “default”,可选安全组为 “allow ping & ssh”。点击安全组 “allow ping & ssh” 后面的 “+” 按钮:
10)点击 “Save” 保存:
11)iptables 会立即更新,下面通过 vimdiff 查看 iptables 前后的变化:
12)“allow ping & ssh” 安全组引入了下面两条 iptables 规则。作用是运行 ingress 的 ssh 和 ping 流量:
13)测试一下,现在能够 ping 和 ssh cirros-vm1 了:
Add Policy
显示Policy创建页面,将 Policy 命名为 “test_policy”,直接点击 “Add” 按钮:ssh-keygen -t rsa -f cloud.key
生成 Key Pair:ssh -i cloud.key ubuntu@172.16.100.9
指定私钥,并以 ubuntu 用户 ssh “Web1” 和 “Web2”。sudo python -m SimpleHTTPServer 80
)。web server 的 index.html 显示当前访问的是哪个 member。ip netns
,我们发现 Neutron 创建了新的 namespace qlbaas-xxx:neutron agent-list
命令查看到 neutron-openvswitch-agent 已经在两个节点上运行:ovs-vsctl show
查看,如下图所示:ovs-vsctl show
查看当前 Open vSwitch 的状态:ovs-vsctl show
查看 bridge 的配置:brctl show
查看一下 linux bridge 的配置:virsh edit
查看 cirros-vm1 的配置:ethtool -S
分别查看 qvbfc1c6ebb-71 和 qvofc1c6ebb-71 的 statistics:ip a
命令找到 index 12 和 13 的设备:ovs-vsctl show
的输出如下:ovs-vsctl add-br br-eth1
和ovs-vsctl add-port br-eth1 eth1
命令创建 br-eth1。将物理网卡 eth1 桥接在 br-eth1 上。ovs-vsctl show
检视一下当前的网络结构:ovs-vsctl show
:ovs-ovctl
命令创建 br-eth1,并将物理网卡 eth1 桥接在 br-eth1 上。 ovs-vsctl show
,查看网络结构:ovs-ofctl dump-flow <bridge>
:ovs-ofctl show <bridge>
查看 port 编号。ovs-vsctl show
的输出:neutron agent-list
命令查询:
route_101_101 上配置了 vlan100 和 vlan101 的网关,两个网络在三层上就通了。
ovs-vsctl show
命令: traceroute <IP Address>
命令 查看一下 cirros-vm3 到 10.10.10.1 的路径:ovs-vsctl show
查看网络配置: ovs-vsctl show
: ovs-vsctl show
:Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。