目录
一、OpenStack 架构
二、控制台 Dashboard
三、身份认证服务 Keystone
1)用户(user)
2)项目(project)
3)角色(role)
4)服务(service)
5)令牌(token)
6)端点(endpoint)
四、镜像模块 Glance
4.1、Glance 主要组件
1)glance-api
2)glance-registry
3)database
4)storage repository for image files
4.2、镜像的格式
1)RAW
2)QCOW2
3)VHD
4)VMDK
5)VDI
6)ISO
7)AKI、ARI、AMI
五、计算模块 Nova
1)Nova-api 服务
2)Nova-api-metadata 服务
3)Nova-Compute 服务
4)Nova-placement-api 服务
5)Nova-Conductor 模块
6)Nova-Scheduler 服务
六、网络模块 Neutron
1)网络
2)子网
3)端口
4)路由器
6.1、Linux 虚拟网络
1)虚拟交换机/网桥
2)虚拟路由器
3)namespace
4)DHCP Server
5)浮动 IP 地址
6.2、组网模型
1)Local 网络
2)Flat 网络
3)vlan 网络
4)VXLAN 网络
七、块存储 Cinder
1)Cinder-Api
2)Cinder-Volume
3)Cinder-Scheduler
4)Cinder-Backup 守护进程
5)消息队列
6)Database
八、对象存储 swift
1)Swift 的主要特性
2)Swift 和 HDFS 的对比
3)一致性哈希算法
4)Swift 组件
5)Swift 存储结构
一、OpenStack 架构
下图体现了 OpenStack 中各个服务之间的相互关系,图中的箭头体现了提供服务方和接受服务方的相对关系。
云计算概念图
OpenStack 由多种服务组成,每种服务具有独立的命名。在整个 OpenStack 架 构中,Keystone 提供认证服务,接收来自用户和服务的认证请求,并对身份进行认证。各个服务之间通过公用的 API 接口进行交互。大部分服务均包含一个 API 进程, 用于侦听 API 请求,根据服务的性质选择处理请求或转发请求。服务进程之间的通讯通过消息队列实现,如 AMQP。
在部署完成的云系统平台上,用户通过 Dashboard 或 RestAPI 方式在经 KeyStone 模块认证授权后,可以执行创建虚拟机服务。通过 Nova 模块创建虚拟机实例,Nova 调用 Glance 模块提供的镜像服务,然后调用 Neutron 模块提供网络服务。根据需要可以选择给虚拟机增加存储卷,卷功能由 Cinder 模块提供服务。整个过程在 Ceilometer 模块的资源监控下完成。同时 Cinder 提供的 Volume 和 Glance提供的镜像可以通过 Swift 对象存储机制进行保存。
通过以上解析可以看到 OpenStack 云平台服务的提供主要是依靠 Nova、Glance、 Cinder 和 Neutron 四个核心模块完成的,四个辅助模块 Horizen、 Ceilometer、 Keystone、Swift 提供的访问、监控、权限和对象存储功能。
二、控制台 Dashboard
Dashboard(项目名称为 horizon)是一个 Web 接口,使得云平台管理员以及用户可以管理不同的 OpenStack 资源以及服务。Dashboard 通过 Apache 的 mod_wsgi 搭建,并通过 python 模块实现和不同的 OpenStack API 进行交互,从而实现管理目的。Dashboard 是一个用以管理、控制 OpenStack 服务的 Web 控制面板,通过它可以实现绝大多数 OpenStack 的管理任务。如实例、镜像、密匙对,卷等。在上一章节中基于 OpenStack 入门体验的大部分操作,都是基于 Dashboard 操作。通过 Dashboard,管理员无需记忆繁琐复杂的 OpenStack 命令。除此之外,用户还可以在控制面板中使用终端或 VNC 直接访问实例控制台。Dashboard 可以实现以下管理任务。
- 实例管理:创建、删除实例,查看终端日志,远程连接实例,管理卷等;
- 访问与安全管理:创建安全组,管理密匙对,设置浮动 IP 地址等;
- 偏好设定:对虚拟硬件模板可以进行不同程度的偏好设定;
- 镜像管理:导入、编辑或删除镜像;
- 用户管理:创建用户、管理用户、设置配额、查看服务目录等;
- 卷管理:管理卷和快照;
- 对象存储处理:创建、删除容器和对象。
三、身份认证服务 Keystone
Keystone (OpenStack Identity Service)中主要涉及到如下几个概念。
1)用户(user)
在 OpenStack 中,用户是使用 OpenStack 云服务的人、系统或服务。用户可以登录或使用指定的 token 访问云中的资源,并可以被指派到指定的项目或角色。认证服务通过对用户身份的确认,来判断一个请求是否被允许。用户通过认证信息如密码、API Keys 等进行验证。
2)项目(project)
项目是各个服务中的一些可以访问的资源集合,用来分组或隔离资源或身份对象。不同服务中,项目所涉及的资源不同。在 Nova 服务中项目可以是云主机,在 Swift 和 Glance 中项目可以是镜像存储,在 Neutron 中项目可以是网络资源。默认情况下,用户总是被绑定到项目中。一个项目中可以有多个用户,一个用户可以属于一个或多个项目。
3)角色(role)
角色是一组用户可以访问的资源权限集合,这些资源包含虚拟机、镜像、存储资源等。 用户既可以被添加到全局的角色,也可以被添加到指定项目内的角色中。其区别是,全局的角色适用于所有项目中的资源权限,而项目内的角色只适用于某个项目内的资源权限。
4)服务(service)
用户使用云中的资源是通过访问服务的方式实现,OpenStack 中包含许多服务,如提供计算服务的 Nova、提供镜像服务的 Glance 以及提供对象存储服务的 Swift。一个服务可以确认当前用户是否具有访问其资源的权限。但是当一个用户尝试访问其项目内的 service 时,该用户必须知道这个服务是否存在以及如何访问这个服务。
5)令牌(token)
令牌是一串数字字符串,用于访问 OpenStack 服务的 API 以及资源。一个令牌可以在特定的时间内生效,并可以在任意时间释放。在 keystone 中主要是引入令牌机制来保护用户对资源的访问。
6)端点(endpoint)
所谓端点,是指用于访问某个服务的网络地址或 URL。如果需要访问一个服务,则必须知道该服务的端点。在 keystone 中包含一个端点模板,这个模板提供了所有已存在的服务的端点信息。一个端点模板包含一个 URL 列表,列表中的每个 URL 都对应一个服务实例的访问地址,并且具有 public、private 和 admin 这三种权限。其中 public 类型的端点可以被全局访问,private 类型的端点只能被 OpenStack 内部服务访问,admin 类型的端点只能被管理员访问。
OpenStack 身份认证服务将管理认证、授权以及服务目录整合为一个访问点,同时也是用户需要和 OpenStack 进行交互的第一个服务。一旦认证通过,终端用户就可以使用其身份访问 OpenStack 其他服务。同样的,其他服务也将利用身份认证服务确认来访用户身份是否合法以及是否具备相应的权限。此外,OpenStack 身份认证服务可以集成其他的身份认证管理系统,如 LDAP 等。
身份认证服务为其他 OpenStack 服务提供验证和授权服务,为所有服务提供终端目录。 此外,提供用户信息但是不在 OpenStack 项目中的服务(如 LDAP 服务)可被整合进先前存在的基础设施中。
为了从身份认证服务中获益,其他的 OpenStack 服务需要身份认证服务合作完成某个任务。当某个 OpenStack 服务收到来自用户的请求时,该服务发送请求到身份认证服务, 以验证该用户是否具有权限进行此次请求。当安装 OpenStack 身份服务时,用户必须将之注册到其 OpenStack 安装环境的每个服务。身份服务才可以追踪到已经安装哪些 OpenStack 服务,并在网络中定位它们。
Keystone 是 OpenStack 框架中负责管理身份验证、服务规则和服务令牌功能的模块。 用户访问资源需要验证用户的身份与权限,服务执行操作也需要进行权限检测,这些都需要通过 Keystone 来处理。Keystone 类似一个服务总线, 或者说是整个 Openstack 框架的注册表,其他服务通过 keystone 来注册其服务的 Endpoint,任何服务之间相互的调用,需要经过 Keystone 的身份验证,并获得目标服务的 Endpoint,从而找到目标服务。以创建一 个云主机为例,下图是 keystone 的工作流程图。
Keystone 工作流程图
身份认证服务包含以下组件。
- 服务器:一个中心化的服务器使用 RESTful 接口来提供认证和授权服务。
- 驱动:驱动或服务后端被整合到集中式服务器中。它们被用来访问 OpenStack 外部仓库的身份信息,并且它们可能已经存在于 OpenStack 被部署在的基础设施(如 SQL 数据库或 LDAP 服务器)中。
- 模块:模块运行于使用身份认证服务的 OpenStack 组件的地址空间中,这些模块拦截服务请求,获取用户凭据,并将它们送入中央服务器以寻求授权。使用 Python Web 服务器网关接口,可以实现中间件模块和 OpenStack 组件间的整合。
四、镜像模块 Glance
镜像服务允许用户发现、注册和获取虚拟机镜像。它提供了一个 REST API,允许查询虚拟机镜像的元数据,并获取一个现存的镜像。可以将虚拟机镜像存放到各种位置,从简单的文件系统到对象存储系统,如 OpenStack Swift 项目,默认是存储在本地文件系统上的。 其实在生产环境中这个模块本身不存储大量的数据,需要挂载后台存储 swift 来存放实际的镜像数据。
在 OpenStack 环境中,镜像是用于在计算节点生成虚拟机。脱离了镜像服务,就无法创建虚拟机,所以镜像服务是 OpenStack 的一个核心服务。
4.1、Glance 主要组件
Glance 镜像服务主要涉及到以下组件。
1)glance-api
glance-api 用于接收镜像 API 的调用,诸如镜像发现、恢复以及存储等。作为一个后台进程,glance-api 对外提供 REST API 接口,响应用户发起的镜像查询、获取和存储的调用。
2)glance-registry
glance-registry 用于存储、处理和恢复镜像的元数据,元数据包括镜像的大小和类型等属性,registry 是一个内部服务接口,不建议暴露给普通用户。
3)database
database 用于存放镜像的元数据,可以根据需要选择数据库,如 MySQL、SQLite 等。
4)storage repository for image files
一般情况下,glance 并不需要存储任何镜像,而是将镜像存储在后端仓库中。Glance 支持多种 repository。主要包括对象存储 Swift、块存储 Cinder、VMware 的 ESX/ESXi 或 者 vCenter、亚马逊的 S3、HTTP 可用服务器、Ceph 等。
4.2、镜像的格式
Glance 支持多种镜像格式,包括磁盘格式和容器格式。OpenStack 中可以支持多种虚拟化的技术,如 KVM、XenServer、Hyper-V 和 VMware 等。用户在上传镜像时,需要指定上传镜像文件的格式。除了磁盘格式,在 Glance 中还有容器的格式。一般在上传镜像时只需指定容器格式为 bare,即为空。因为 Glance 中并没有真正使用到容器格式。容器格式用来表示虚拟机镜像文件是否包含了元数据,例如 OVF 格式。下面列出了 Glance 中常用的几种镜像文件格式。
1)RAW
RAW 是一种没有格式或裸格式的磁盘文件类型,RAW 对数据不做任何修饰和处理,直接保存最原始的状态,所以在性能方面非常出色。由于 RAW 格式保存原始数据,因此更容易和其他镜像格式进行转换。
2)QCOW2
QCOW2 是 QCOW 的升级版本,其主要特性是磁盘文件大小可以动态按需增长,并且不会占用所有的实际磁盘空间大小。例如创建了 100GB 的 QCOW2 格式的磁盘,而实际只保存了 2GB 数据,那么将只占用了实际物理磁盘的 2GB 空间。与 RAW 相比,使用这种格式可以节省磁盘容量。
3)VHD
VHD 是微软公司产品使用的磁盘格式。Virtual PC(微软早期虚拟化产品)和 Hyper-V 使用的就是 VHD 格式。VirtualBox 也提供了对 VHD 的支持。如需在 OpenStack 上使用 Hyper-V 类型的虚拟化,就应上传 VHD 格式的镜像文件。
4)VMDK
VMDK 是 VMware 公司产品使用的磁盘格式。目前也是一个开放的通用格式,除了 VMware 自家的产品外,QEMU 和 VirtualBox 也提供了对 VMDK 格式的支持。
5)VDI
VDI 是 Oracle 公司的 VirtualBox 虚拟软件所使用的格式。
6)ISO
ISO 是指一种存档数据文件在光盘上的格式。
7)AKI、ARI、AMI
Amazon 公司的 AWS 所使用的镜像格式。
五、计算模块 Nova
Nova 是负责提供计算资源的模块,也是 OpenStack 中的核心模块,其主要功能是负责虚拟机实例的生命周期管理、网络管理、存储卷管理、用户管理以及其他的相关云平台管理功能。OpenStack 使用计算服务来托管和管理云计算系统。OpenStack 计算服务是基础设施服务(IaaS)系统的主要组成部分,模块主要由 Python 实现。
OpenStack 计算组件请求 OpenStack Identity 服务进行认证,请求 OpenStack Image 服务提供磁盘镜像,为 OpenStack Dashboard 提供用户和管理员接口。磁盘镜像访问限制在项目与用户上;配额以每个项目进行设定,例如,每个项目下可以创 建多少实例。OpenStack 组件可以在标准硬件上横向大规模扩展,并且下载磁盘镜像启动虚拟机实例。OpenStack 计算服务的主要组件如下。
1)Nova-api 服务
接收和响应来自最终用户的计算 API 请求,对外提供一个与云基础设施交互的接口,也是外部可用于管理基础设施的唯一组件。nova-api 是整个 Nova 组件的门户, 所有对 Nova 的请求都首先由 nova-api 处理。nova-api 向外界暴露若干 HTTP REST API 接口。OpenStack CLI,Dashboard 和其他需要跟 Nova 交互的组件会使用这些 API。在 keystone 中可以查询 nova-api 的 endponits。客户端就可以将请求 发送到 endponits 指定的地址,向 nova-api 请求操作。
nova-api 对接收到的 HTTP API 请求会做如下处理:
- 检查客户端传入的参数是否合法有效。
- 调用 Nova 其他子服务处理客户端 HTTP 请求。
- 格式化 Nova 其他子服务返回的结果并返回给客户端。
只要是跟虚拟机生命周期相关的操作,nova-api 都可以响应。
2)Nova-api-metadata 服务
接收来自虚拟机发送的元数据请求。Nova-api-metadata 服务一般在安装 Nova-Network 服务的多主机模式下使用。
3)Nova-Compute 服务
Nova-compute 服务运行在计算节点上,主要负责管理节点上的实例。OpenStack 对实例的操作都是交给 nova-compute 来完成的。它是一个持续工作的守护进程,通过 Hypervisor 的 API 来创建和销毁虚拟机实例。Nova-compute 支持如下 Driver 架 构。
- XenServer/XCP 的 XenAPI
- KVM 或 QEMU 的 libvirt
- Vmware 的 VMwareAPI
守护进程同意了来自队列的动作请求,转换为一系列的系统命令,如启动一个 KVM 实例,然后到数据库中更新它们的状态。Nova-compute 的功能可以分为两类。
- 定时向 OpenStack 报告计算节点的状态
- 实现实例生命周期的管理
4)Nova-placement-api 服务
Nova-placement-api 用于追踪记录资源提供者目录和资源使用情况,这些资源包括计算、存储以及 IP 地址池等。
5)Nova-Conductor 模块
Nova-Conductor 模块作用于 Nova-Compute 服务与数据库之间,避免了由 Nova-Compute 服务对云数据库的直接访问。它可以横向扩展。但是,不要将它部署在运行 Nova-Compute 服务的主机节点上。通过 Nova-conductor 实现对数据库的连接操作,可以实现更高的系统安全性以及更好的系统伸缩性。
6)Nova-Scheduler 服务
Nova-Scheduler 接收到一个来自队列的运行虚拟机实例请求,然后决定在哪台计算服务器主机来运行该虚拟机。通过恰当的调度算法从可用资源池获得一个计算服务。Nova-Scheduler 服务将根据负载、内存、可用域的物理距离、CPU 构架等信息, 并运行调度算法,最终做出调度决策。
最终 OpenStack 计算模块 Nova 中的各个组件是以数据库和队列为中心进行通信的。
六、网络模块 Neutron
OpenStack 早期的网络模块是 Nova-Network,而 Neutron 则是 Nova-Network 的更新换代产品,也是目前 OpenStack 重要组件之一。在正式介绍之前,首先了解 一些网络概念。
1)网络
类似于实际的物理环境中的网络,OpenStack 网络用于连接云主机或路由器。除此之外,还包含子网、网关以及 DHCP 服务等。OpenStack 网络分为内部网络和外部网络,内部网络一般用于连接虚拟机,而外部网络一般用于连接宿主机外面的网络。
2)子网
OpenStack 中的子网是一个 IP 地址段,用于定义实际的 IP 地址范围。
3)端口
端口类似于实际网络中的网络接口,用于连接终端设备或另外一个网络。不同的是,OpenStack 中端口连接的一般都是虚拟设备接口,如虚拟机的虚拟网卡或者路由器的虚拟接口等。端口还描述了相关的网络配置,例如可以在端口上配置 MAC 地址 和 IP 地址。
4)路由器
路由器用于连接 OpenStack 的内部网络和外部网络。类似实际路由器功能,支持 NAT 功能,通过绑定浮动 IP
Neutron 分别提供了二层(L2)交换和三层(L3)路由抽象的功能,对应于物理网络环境中的交换机和路由器。
6.1、Linux 虚拟网络
Neutron 中最为核心的工作便是对网络的抽象与管理。在 OpenStack 环境中对网络的抽象主要有以下几种形式。
1)虚拟交换机/网桥
OpenStack 网络中,对于二层交换机有两种的抽象方式,一种是通过 Linux bridge 实现,另外一种是通过 OpenvSwitch 实现。两种方式都可以实现二层网路的抽象。 从功能上来说 OpenvSwitch 更加强大,但是 Linux bridge 实现比较简单,更加适合初学者。
虚拟交换机/网桥主要实现以下功能。
- 连接虚拟机;
- 通过 vlan 功能隔离虚拟机网络;
- 连接虚拟网络到宿主机外部网络。
- Linux bridge
Linux bridge 由 Linux 内核实现,是工作在二层的虚拟网络设备,功能类似于物理的交换机。
一个典型的通过 Linux-bridge 实现二层网络连接的网络结构如下图所示。
虚拟交换机网络连接
在上图中,分别通过虚拟交换机 1、虚拟交换机 2、虚拟交换机 3 连接 vm1、 vm2、vm3。每个虚拟交换机代表一个 OpenStack 网络,通过 vlan 功能隔离不同的 虚拟机。虚拟交换机 4 通过绑定物理网卡实现虚拟网络和外部真实网络的通信。
- Open vSwitch
类似于 Linux bridge,Open vSwitch 也可以实现对二层网络的抽象,对虚拟网络提供分布式交换机功能。它支持各种组网类型,功能全面,支持基本的 vlan 功能, 也支持 QOS 以及 NetFlow、sFlow 标准的管理接口和协议。从而通过这些接口可以实现 VM 流量监控的任务。
运行在云环境中各种或相同虚拟化平台上的多个 vSwitch 实现了分布式架构的虚拟交换机。一个物理服务器上的 vSwitch 可以透明的与其他服务器上的 vSwitch 连接通信。
2)虚拟路由器
OpenStack 中的虚拟路由器是对网络设备的一种抽象,实现了租户间多网络构建以及内部网络和外部网络之间的通信问题。其实现原理和真实路由器一致,根据路由表转发数据包,同时还支持 NAT 地址转换以及浮动 IP 地址设置。
3)namespace
二层网络通过 vlan 对租户网络进行隔离,而三层网络是通过 namespace 进行隔离,每个 namespace 都有自己的独立网络栈,包括路由表、防火墙规则、网络接口等。 同时,Neutron 为每个 namespace 提供 DHCP 和路由服务。所以各个租户之间的网络地址允许重叠,因为它们在不同的 namespace 中进行抽象。如下图所示。
namespace 隔离三层网络
三个租户分别规划了相同的 IP 地址网段 192.168.100.0/24。这样的设计在真实环境中是不可行的,因为路由器不允许在不同的接口配置相同的 IP 地址网段。但是在 OpenStack 网络中,路由器通过不同的 namespace 进行隔离。所以 R1 犹如开启三个相互独立的进程。在每个 namespace 空间内,只有一个 192.168.100.0 网段。 通过 namespace,OpenStack 可以让租户创建任意网络,而不必担心和其他网络产生冲突。
4)DHCP Server
Neutron 提供 DHCP 服务的组件是 DHCPagent,默认通过 dnsmasq 实现 DHCP 功能。dnsmasq 是一个提供 DHCP 与 DNS 服务的开源软件。在 OpenStack 网络中, DHCP 服务同样被隔离在 namespace 中 , 并通过 Linux Bridge 连接 DHCP namespace 中的接口。
一个 DHCP Server 只为指定的网络提供服务,即 dnsmasq 与网络是一一对应的关系, 一个 dnsmasq 进程可以为同一个 Network 中所有使能 DHCP 的子网提供服务。管理员可以选择启用或禁用 DHCP Server,但是一旦启用 DHCP Server,并且配置相应的地址池,网络节点上的 DHCP agent 会启动一个 dnsmasq 进程为该网络提供 DHCP 服务,该网络将自动获取网络地址以及其他选项。
5)浮动 IP 地址
通常情况下,在搭建 OpenStack 网络时,会在虚拟路由器启用 SNAT 功能。这将给 OpenStack 网络提高安全性和便利性,具体表现如下。
- 启动 NAT 功能,OpenStack 内部网络被保护起来;
- 虚拟机访问外部网络通过地址转换的方式,更容易让外部路由设备寻路,即不需要增加额外的回包路由条目。
所以,当网络启用了 NAT 功能后,在允许虚拟机访问外部网络的同时,也阻止了外部网络访问虚拟机的流量,如 SSH 管理流量。但是可以通过目标地址转换的方式实现外部网络访问内部虚拟机,即 NAT 地址映射。配置 NAT 地址映射需要在虚拟 路由器外部接口配置相应的外部网络地址池,而这些地址池中的地址就是浮动 IP 地 址。所以浮动 IP 地址是用来解决外部网络访问虚拟机的问题。如果虚拟机不需要外部网络访问,也可以不绑定浮动 IP 地址。
6.2、组网模型
Neutron 提供了多种组网模型供不同的租户搭建各种网络拓扑。
1)Local 网络
Local 网络模型有如下特点。
- 不具备 vlan 特性,不能对二层网络进行隔离。
- 同一个 local 网络的虚拟机实例会连接到相同的虚拟交换机上,instance 之间可以通信。
- 虚拟交换机没有绑定任何物理网卡,无法与宿主机之外的网络通信。
典型的 Local 网络组网模型如下图所示。vm1 和 vm2 连接到 Linux bridge1, vm3 连接到 Linux bridge2。vm1 和 vm2 因为连接到同一个 Linux bridge,所以可以相互通信,但是不能和 vm3 进行通信。因为没有任何 Linux bridge 绑定物理网卡, 所以任何虚拟机都不能访问外部网络。
Local Network 组网模型
2)Flat 网络
Flat 组网模型不支持 vlan ,属于扁平化的网络模型。Linux bridge 直接绑定物理网卡,并连接虚拟机。每个 Flat 网络都会独占一个物理网卡,该物理网卡不能配置 IP 地址, 所有连接到此网络的虚拟机共享一个私有 IP 网段。
Flat 组网模型适用于以下应用场景。
- Flat 网络直接连接虚拟机和外部网络
如下图所示。Linux bridge1 连接 vm1 和 vm2,并绑定物理网卡 ens37,Linux bridge2 连接 vm3,并绑定物理网卡 ens38。vm1 和 vm2 可以相互通信并通过物理网卡 ens37 访问外部网络,vm3 通过物理网卡 ens38 访问外部网络。
Flat 组网模型(一)
- Flat 网络连接路由器和外部网络
如下图所示。虚拟机连接 vlan 类型的网络,并通过 vlan 对租户进行隔离,对外通过路由器连接虚拟交换机 4,并通过虚拟交换机 4 绑定物理网卡实现访问外部网 络。通过 vlan 隔离的租户网络被限制在虚拟交换机 1、虚拟交换机 2 和虚拟交换机 3 所在的 vlan 网络,而虚拟机发起的流量经过路由器转发后不携带任何 vlan 标签到达 虚拟交换机 4,并通过物理网卡访问外部网络。虚拟交换机 4 所在的网络就可以被设 计为 Flat 网络。
Flat 组网模型(二)
Flat 网络存在以下缺点。
- 存在单一网络瓶颈;
- 缺乏可伸缩性;
- 缺乏合适的多租户隔离。
3)vlan 网络
OpenStack 通过 vlan 网络解决了多租户之间的网络隔离问题。如下图所示。 Linux bridge1 和 Linux bridge2 是 属于 vlan 类 型的 网 络 ,并 分 别属 于 vlan101 和 vlan102。vm1 和 vm2 连接到 Linux bridge1,vm3 连接到 Linux bridge2,Linux bridge1 和 Linux bridge2 分别绑定物理网卡 ens37 的两个子网卡 ens37.101 和 ens37.102。 vm1 和 vm2 发起的流量在经过 ens37.101 时,被打上标签 vlan101,vm3 发起的流 量在经过 ens37.102 时被打上标签 vlan102。这就要求连接 ens37 的物理交换机相应 的接口要配置为 Trunk 模式。如果需要其他 vlan 网络,可以创建新的物理网卡子接 口,并绑定新网络。
vlan 组网模型
vlan 网络存在以下缺点。
- vlan 的数量限制:4096 个 vlan 数量不能满足大规模云计算数据中心的需求;
- 物理网络基础设施的限制:基于 IP 子网的区域划分限制了需要二层网络连通性的应用负载的部署;
- TOR 交换机 MAC 表耗尽:虚拟化以及节点间过多的流量导致更多的 MAC 表项。
4)VXLAN 网络
VXLAN 网络使用的是隧道技术,是目前 OpenStack 广泛使用的网络技术。 相比于 vlan 模型有以下改进。
- 租户数量从 4K 增加到 16M;
- 租户内部通信可以跨越任意 IP 网络,支持虚拟机任意迁移;
- 一般来说,每个租户逻辑上都有一个网关实例,IP 地址可以在租户间进行复用;
- 能够结合 SDN 技术对流量进行优化。
VXLAN 网络是在传统的 IP 网络中传输以太网数据帧。主要涉及到以下几个概念。
- VTEP(VXLAN Tunnel End Point, 简称 VTEP):VXLAN 隧道的端点,用于 VXLAN 报文的封装和解封装。类似于 IPsecVPN 中的加密点。传统的以太网 帧在发送 VTEP 端将封装新的 VXLAN、UDP、IP 以及以太网头部。而接收 VTEP 端将数据解封装。VXLAN 报文中源 IP 地址为本节点的 VTEP 地址, VXLAN 报文中目的 IP 地址为对端节点的 VTEP 地址,一对 VTEP 地址就对 应着一个 VXLAN 隧道。
- VNI(VXLAN Network Identifier,简称 VNI):用来标识一个 VXLAN 段,在 VXLAN 网络中,通过 VNI 标识一个租户,类似 vlan 网络中的 vlan ID。不同 VXLAN 段的虚拟机之间不能直接二层相互通信。VNI 由 24 比特组成,支持 多达 16M 的租户。
在 VXLAN 网络通信中,虚拟机之间的通信过程如下图所示。
VXLAN 组网模型
- VTEP1 将来自 vm1 的数据帧添加 VXLAN 头部、外部 UDP 和 IP 首部。
- VTEP1 通过传统的 IP 网络将数据发送至 VTEP2。
- VTEP2 收到 VXLAN 报文时,拆除外部 IP、UDP 以及 VXLAN 首部,然后将内部数据包交付给正确的终端 vm2。
七、块存储 Cinder
块存储服务(Cinder)提供块存储。存储的分配和消耗是由块存储驱动器或者多后端配置的驱动器决定的。还有很多驱动程序可用:NAS/SAN、NFS、ISCSI、CEPH 等。块存储适合性能敏感性业务场景,例如数据库存储大规模可扩展的文件系统或服务器需要访问到块级的裸设备存储。典型情况下,块服务 API 和调度器服务运行在控制节点上。取决于使用的驱动,卷服务器可以运行在控制节点、计算节点或单独的存储节点之上。
块存储服务为 OpenStack 中的实例提供持久的存储,块存储提供一个基础设施,用于管理卷以及和 OpenStack 计算服务交互,为实例提供卷、快照、卷类型等功能。站在实例 的角度,挂载的每个卷都是一块独立的硬盘。Cinder 提供了从创建卷到删除卷整个生命周 期的管理。其具体功能是:
- 提供 REST API 接口,使用户能够查询和管理卷、卷快照以及卷类型;
- 协调卷的创建请求,合理优化存储资源的分配;
- 通过驱动架构支持多种后端存储方式,包括 LVM、NFS、Ceph 和其他诸如 EMC、 IBM 等商业存储产品和方案。
Cinder 服务涉及到以下组件。
1)Cinder-Api
Cinder-API 用来接受 API 请求,并将其路由到 Cinder-Volume 执行。
2)Cinder-Volume
Cinder-Volume 用来与块存储服务和 Cinder-Scheduler 进程进行直接交互。也可以与这些进程通过一个消息队列进行交互。Cinder-Volume 服务响应到块存储服务的读写请求, 可以在多种存储驱动架构下交互。当用户请求一个存储资源时,由 Cinder-API 负责接受请 求,Cinder-Scheduler 负责调度资源,而真正执行存储任务的是 Cinder-Volume。这样的工作机制使得存储架构非常容易扩展。当存储资源不足时,可以增加存储节点(运行 Cinder-Volume )。当客户的请求量太大调度不过来时,可以增加调度(运行 Cinder-Scheduler)。
3)Cinder-Scheduler
Cinder-Scheduler 守护进程会选择最优存储节点来创建卷,其工作机制与 Nova-Scheduler 类似。当需要创建卷时,Cinder-Scheduler 根据存储节点的资源使用情况选择一个最合适的节点来创建卷。
4)Cinder-Backup 守护进程
Cinder-Backup 服务提供任何种类备份卷到一个备份存储提供者。就像 Cinder-Volume 服务,它与多种存储提供者在驱动架构下进行交互。
5)消息队列
消息队列作用是在块存储的进程之间路由信息。Cinder 各个子服务通过消息队列实现进程间通信和相互协作。
6)Database
Cinder 有一些数据需要存放到数据库中,一般使用 MySQL。数据库是安装在控制节点上的,比如在我们的实验环境中,可以访问名称为“Cinder”的数据库。
以创建卷为例,Cinder 的工作流程如下。
- 用户向 Cinder-API 发送创建卷请求:“帮我创建一个卷”;
- Cinder-API 对请求做一些必要处理后,向消息队列发送一条消息:“ 让 Cinder-Scheduler 创建一个卷”;
- Cinder-Scheduler 从消息队列获取到消息,然后执行调度算法,从若干存储节点中选出节点 A;
- Cinder-Scheduler 向消息队列发送一条消息:“让存储节点 A 创建这个卷”;
- 存储节点 A 的 Cinder-Volume 从消息队列中获取到消息,然后通过卷提供者的驱动创建卷。
八、对象存储 swift
OpenStack Object Storage(Swift)是 OpenStack 开源云计算项目的子项目之一。Swift 的目的是使用普通硬件来构建冗余的、可扩展的分布式对象存储集群,存储容量可达 PB 级。 Swift 并不是文件系统或者实时的数据存储系统,它是对象存储,用于永久类型的静态数据长期存储,这些数据可以检索、调整,必要时进行更新。最适合存储的数据类型是虚拟机镜 像、图片存储、邮件存储和存档备份。
Swift 无需采用 RAID(磁盘冗余阵列),也没有中心单元或主控结点。Swift 通过在软件层面引入一致性哈希技术和数据冗余性,牺牲一定程度的数据一致性来达到高可用性(High Availability,简称 HA)和可伸缩性,支持多租户模式、容器和对象读写操作,适合解决互联网应用场景下非结构化数据存储问题。
1)Swift 的主要特性
- 极高的数据持久性(Durability)。
- 完全对称的系统架构,“对称”意味着 Swift 中各节点可以完全对等,能极大地降低系统维护成本。
- 无限的可扩展性,一方面是数据存储容量无限可扩展;另一方面是 Swift 性能(如 QPS、吞吐量等)可线性提升。
- 无单点故障,Swift 的元数据存储是完全均匀随机分布的,并且与对象文件存储一 样,元数据也会存储多份。整个 Swift 集群中,也没有一个角色是单点的,并且在架构和设计上保证无单点业务。
- 简单、可依赖。
2)Swift 和 HDFS 的对比
Swift 和 Hadoop 分布式文件系统(HDFS)都有着相似的目的:实现冗余、快速、联 网的存储,它们的技术差异如下:
- 在 Swift 中,元数据呈分布式,跨集群复制。而 HDFS 使用了中央系统来维护文件元数据(Namenode,名称节点),这对 HDFS 来说无异于单一故障点,因而扩展到规模非常大的环境显得更困难。
- Swift 在设计时考虑到了多租户架构,而 HDFS 没有多租户架构这个概念。
- 在 Swift 中,文件可以写入多次;在并发操作环境下,以最近一次操作为准。而在 HDFS 中,文件写入一次,而且每次只能有一个文件写入。
- Swift 用 Python 来编写,而 HDFS 用 Java 来编写。
- Swift 被设计成了一种比较通用的存储解决方案,能够可靠地存储数量非常多的大小不一的文件;而 HDFS 被设计成可以存储数量中等的大文件(HDFS 针对更庞 大的文件作了优化),以支持数据处理。
3)一致性哈希算法
在分布式对象存储中,一个关键问题是数据该如何存放。Swift 是基于一致性哈希技术, 通过计算可将对象均匀分布到虚拟空间的虚拟节点上,在增加或删除节点时可大大减少需移动的数据量;虚拟空间大小通常采用 2 的 n 次幂,便于进行高效的移位操作;然后通过独 特的数据结构 Ring(环)再将虚拟节点映射到实际的物理存储设备上,完成寻址过程。
衡量一致性哈希的四个指标:
- 平衡性(Balance):平衡性是指 Hash 的结果能够尽可能分布均匀,充分利用所有缓存空间。
- 单调性(Monotonicity):单调性是指如果已经有一些内容通过哈希分派到了相应的缓冲中,又有新的缓冲加入到系统中。哈希的结果应能够保证原有已分配的内容可以被映射到新的缓冲中去,而不会被映射到旧的缓冲集合中的其他缓冲区。
- 分散性(Spread):分散性定义了分布式环境中,不同终端通过 Hash 过程将内容映射至缓存上时,因可见缓存不同,Hash 结果不一致,相同的内容被映射至不同的缓冲区。
- 负载(Load):负载是对分散性要求的另一个纬度。既然不同的终端可以将相同的内容映射到不同的缓冲区中,那么对于一个特定的缓冲区而言,也可能被不同的用户映射为不同的内容。
Swift 使用该算法的主要目的是在改变集群的 node 数量时(增加/删除服务器),能够尽可能少地改变已存在 key 和 node 的映射关系,以满足单调性。
考虑到哈希算法在 node 较少的情况下,改变 node 数会带来巨大的数据迁移。为了解 决这种情况,一致性哈希引入了“虚拟节点”(vnode,也称为 partition)的概念:“虚拟节点” 是实际节点在环形空间的复制品,一个实际节点对应了若干个“虚拟节点”,“虚拟节点”在哈 希空间中以哈希值排列。
总的来说,Swift 中存在两种映射关系,对于一个文件,通过哈希算法(MD5)找到对 应的虚节点(一对一的映射关系),虚节点再通过映射关系(ring 文件中二维数组)找到对应的设备(多对多的映射关系),这样就完成了一个文件存储在设备上的映射。
在分布式系统中,数据的单点是不允许存在的。线上正常存在的 replica 数量是 1 的话 将非常危险,因为一旦这个 replica 再次错误,就可能发生数据的永久性错误。假如我们把 N 设置成为 2,那么,只要有一个存储节点发生损坏,就会有单点的存在。所以 N 必须大于 2。但 N 越高,系统的维护和整体成本就越高。所以,正式线上环境通常把 N 设置为 3。
Swift 数据模型共分为三层逻辑结构:Account/Container/Object(账户/容器/对象)。每 层节点数均没有限制,可以任意扩展。这里的账户和个人账户不是一个概念,可理解为租户, 用来做顶层的隔离机制,可以被多个个人账户所共同使用;容器类似文件夹,代表封装一组 对象;对象由元数据和数据两部分组成。
Swift 系统架构采用完全对称、面向资源的分布式系统架构设计,所有组件都可扩展, 避免因单点失效从而影响整个系统运转;通信方式采用非阻塞式 I/O 模式,提高了系统吞 吐和响应能力。
4)Swift 组件
- 代理服务(Proxy Server)
Swift 通过 Proxy Server 向外提供基于 HTTP 的 REST 服务接口,会根据环的信息来查找服务地址并转发用户请求至相应的账户、容器或者对象,进行 CRUD(增删改查)等操 作。由于采用无状态的 REST 请求协议,可以进行横向扩展来均衡负载。在访问 Swift 服务 之前,需要先通过认证服务获取访问令牌,然后在发送的请求中加入头部信息 X-Auth-Token。 代理服务器负责 Swift 架构的其余组件间的相互通信。代理服务器也处理大量的失败请求。 例如,如果对于某个对象 PUT 请求时,某个存储节点不可用,它将会查询环可传送的服务 器并转发请求。对象以流的形式到达(来自)对象服务器,它们直接从代理服务器传送到(来 自)用户,代理服务器并不缓冲它们。
- 认证服务(Authentication Server)
验证访问用户的身份信息,并获得一个对象访问令牌(Token),在一定的时间内会一 直有效;验证访问令牌的有效性并缓存下来直至过期。
- 缓存服务(Cache Server)
缓存的内容包括对象服务令牌,账户和容器的存在信息,但不会缓存对象本身的数据; 缓存服务可采用 Memcached 集群,Swift 会使用一致性哈希算法来分配缓存地址。
- 账户服务(Account Server)
提供账户元数据和统计信息,并维护所含容器列表的服务,每个账户的信息被存储在一个 SQLite 数据库中。
- 容器服务(Container Server)
提供容器元数据和统计信息(比如对象的总数,容器的使用情况等),并维护所含对象 列表的服务。容器服务并不知道对象存储在哪,只知道指定容器里存的哪些对象。这些对象信息以 SQLite 数据库文件的形式存在,和对象一样在集群上做类似的备份。
- 对象服务(Object Server)
提供对象元数据和内容服务,可以用来存储、检索和删除本地设备上的对象。在文件系统中,对象以二进制文件的形式存储,它的元数据存储在文件系统的扩展属性(xattr)中, 建议采用默认支持扩展属性(xattr)的 XFS 文件系统。每个对象使用对象名称的哈希值和 操作时间戳组成的路径来存储。最后一次写操作总可以成功,并确保最新一次的对象版本将 会被处理。删除也被视为文件的一个版本(一个以".ts"结尾的 0 字节文件,ts 表示墓碑)。
- 复制服务(Replicator)
会检测本地分区副本和远程副本是否一致,具体是通过对比哈希文件和高级水印来完成, 发现不一致时会采用推式(Push)更新远程副本:对于对象的复制、更新使用 rsync 同步 文件到对等节点。帐号和容器的复制通过 HTTP 或 rsync 来推送整个数据库文件上丢失的记 录;另外一个任务是确保被标记删除的对象从文件系统中移除:当有一项(对象、容器、或 者帐号)被删除,则一个墓碑文件被设置作为该项的最新版本。复制器将会检测到该墓碑文 件并确保将它从整个系统中移除。
- 更新服务(Updater)
当对象由于高负载或者系统故障等原因而无法立即更新时,任务将会被序列化到在本地文件系统中进行排队,以便服务恢复后进行异步更新;例如成功创建对象后容器服务器没有及时更新对象列表,这个时候容器的更新操作就会进入排队中,更新服务会在系统恢复正常后扫描队列并进行相应的更新处理。
- 审计服务(Auditor)
在本地服务器上会反复地爬取来检查对象、容器和账户的完整性,如果发现比特级的错误,文件将被隔离,并复制其他的副本以覆盖本地损坏的副本;其他类型的错误(比如在任何一个容器服务器中都找不到所需的对象列表)会被记录到日志中。
- 账户清理服务(Account Reaper)
移除被标记为删除的账户,删除其所包含的所有容器和对象。删除账号的过程是相当直接的。对于每个账号中的容器,每个对象先被删除然后容器再被删除。任何失败的删除请求将不会阻止整个过程,但是将会导致整个过程最终失败(例如,如果一个对象的删除超时, 容器将不能被删除,因此账号也不能被删除)。整个处理过程即使遭遇失败也会继续执行,这样它不会因为一个麻烦的问题而中止恢复集群空间。账号收割器将会继续不断地尝试删除 账号直到它最终变为空,此时数据库在 db_replicator 中回收处理,最终移除这个数据库文 件。
5)Swift 存储结构
在 Storage Node 上运行着 Linux 系统并使用了 XFS 文件系统,逻辑上使用一致性哈希算法将固定总数的 partition 映射到每个 Storage Node 上,每个 data 也使用同样的哈希算法映射到 partition 上。
存储内容一般放在/srv/node/sdb1 之类的路径下,其目录结构如下所示:accounts、 async_pending、containers、objects、quarantined 和 tmp。其中 accounts、containers、 objects 分别是账号、容器、对象的存储目录,async_pending 是异步待更新目录,quarantined 是隔离目录,tmp 是临时目录。