- 1. 网络结构
- 2. 搭建OpenStack基础
- 3. KeyStone组件
- 4. Glance组件
- 5. Nova组件
- 6. Neutron组件
- 7. Horizon组件
- 8. 创建一个实例
- 9. Cinder组件
- 10. Swift组件
1. 网络结构
硬件:
- 核心:
- 计算节点
- 控制节点
- 存储:
- 块存储
- 对象存储
节点服务:
网络架构:
理想情况:
- 红色: 管理网络
- 绿色: 数据网络,或隧道网络
- 蓝色: 存储网络
- 紫色: 本地网络
- 屎黄色: 公网
实验简化:
- 管理/存储/互联网络为:192.168.137.0/24
- 数据网络:172.16.0/24
- vxlan隧道网络
- 本地网络:br-exteral
2. 搭建OpenStack基础
XShell可以打开:查看->撰写->撰写栏,一次发送到所有机器
2.1. 需求
- 完整需要5台机器,最核心的是计算和管理节点.
- 给每台虚拟机添加一个仅主机的网卡(Host-Only)
- ens33:NAT模式,192.168.137.0/24网段
- 管理,存储,和互联
- ens34:桥接,用于连接外网
- ens39:linuxbridge+vlan,隧道网络,VMware中是Host-Only.
- 这个只需要配置IP和NETMASK,具体在下面
- 只用于控制和计算节点
2.2. 系统规划
- 192.168.137.30:control
- ens34桥接:192.168.1.30
- ens39Host-Only:172.17.2.30
- 硬件:2核心2G ,4G swap:
sudo dd if=/dev/zero of=/tmp/swap bs=4k count=524288
sudo chmod 600 /tmp/swap
sudo mkswap /tmp/swap
sudo swapon /tmp/swap
- 192.168.137.31: compute
- ens34桥接:192.168.1.31
- ens39Host-Only:172.17.2.31
- 硬件:1核心512M,按照需求添加swap
- 192.168.137.32:block
- ens34桥接:192.168.1.32
- ens39Host-Only:172.17.2.32(隧道网络,只用于计算和控制节点)
- 硬件:1核心512M
- 前期暂时不需要开启
- ens34桥接:192.168.1.32
- 192.168.137.33:object1
- ens34桥接:192.168.1.33
- ens39Host-Only:172.17.2.33(隧道网络,只用于计算和控制节点)
- 硬件:1核心512M
- 前期暂时不需要开启
- ens34桥接:192.168.1.33
- 192.168.137.34:object2
- ens34桥接:192.168.1.34
- ens39Host-Only:172.17.2.34(隧道网络,只用于计算和控制节点)
- 硬件:1核心512M
- 前期暂时不需要开启
- ens34桥接:192.168.1.34
2.3. 通用基础准备配置
# 配置添加的Host-Only网卡,Host-Only网卡是和主机完全隔离的,所以只需要配置一个IP即可
sudo su
cp /etc/sysconfig/network-scripts/ifcfg-ens34 /etc/sysconfig/network-scripts/ifcfg-ens39
# 不同系统可能名字不一样
echo UUID=`uuidgen ens39` >> /etc/sysconfig/network-scripts/ifcfg-ens39
vim /etc/sysconfig/network-scripts/ifcfg-ens39
# 完整的内容如下:
TYPE=Ethernet
PROXY_METHOD=static # 这里改成了static
BROWSER_ONLY=no
BOOTPROTO=static # 只要是静态ip,都是static
DEFROUTE=no # 默认用的桥接的网卡
IPV4_FAILURE_FATAL=no
IPV6INIT=yes
IPV6_AUTOCONF=yes
IPV6_DEFROUTE=yes
IPV6_FAILURE_FATAL=no
IPV6_ADDR_GEN_MODE=stable-privacy
NAME=ens39 # 更改名字
DEVICE=ens39 # 更改设备名
ONBOOT=yes
IPADDR=172.17.2.30 # IP
NETMASK=255.255.255.0
UUID=ee31b776-a9e7-4c9d-816d-da5ead1b2599
systemctl restart network
# 关闭防火墙
systemctl stop firewalld
systemctl disable firewalld
# 关闭selinux
vim /etc/sysconfig/selinux
# selinux=enforcing 改为:selinux=disabled
# 关闭NetworkManager
systemctl stop NetworkManager
systemctl disable NetworkManager
# 修改hosts
vim /etc/hosts
# 如下
192.168.137.30 controller
192.168.137.31 compute
192.168.137.32 block
192.168.137.33 object1
192.168.137.34 object2
# 修改对应的hostname
hostnamectl set-hostname 上面对应的host
2.4. 通用OpenStack组件准备
# 安装ntp
sudo yum install -y chrony
# Controller节点
sudo vim /etc/chrony.conf
# 添加网段
allow 192.168.137.0/24
# 让该网段的机器都可以访问
# 其他节点
sudo vim /etc/chrony.conf
# 注释掉所有的server,使用server controller 作为时间同步节点
server controller iburst
sudo systemctl enable chronyd.service
sudo systemctl start chronyd.service
sudo chronyc sources
# Controller使用配置文件中的4个server来同步
# 其他的使用Controller节点来同步
# 添加并更换源,国外的实在太慢了
# base:https://mirrors.tuna.tsinghua.edu.cn/help/centos/
sudo yum install -y epel-release
# epel:https://mirrors.tuna.tsinghua.edu.cn/help/epel/
sudo yum install -y centos-release-openstack-queens
# 这个主要是添加了4个源
# CentOS-Ceph-Luminous.repo
# CentOS-OpenStack-queens.repo
# CentOS-QEMU-EV.repo
# 上面这个几个只能手动改
# 打开对应的repo
sudo su
sed 's@http://mirror.centos.org@https://mirrors.tuna.tsinghua.edu.cn@g' -i /etc/yum.repos.d/CentOS-Ceph-Luminous.repo
sed 's@http://mirror.centos.org@https://mirrors.tuna.tsinghua.edu.cn@g' -i /etc/yum.repos.d/CentOS-OpenStack-queens.repo
sed 's@http://mirror.centos.org@https://mirrors.tuna.tsinghua.edu.cn@g' -i /etc/yum.repos.d/CentOS-QEMU-EV.repo
# 更新并安装
yum upgrade -y
yum install -y openstack-selinux
yum install -y python-openstackclient
2.5. Controller节点
# 数据库服务
sudo yum install -y mariadb mariadb-server python2-PyMySQL
# 也有 python36-PyMySQL,但是,好像其他相关的全部是python2
# 创建配置文件:
sudo vim /etc/my.cnf.d/openstack.cnf
# 内容如下
[mysqld]
bind-address = 192.168.137.30
# 控制节点的管理IP,或者直接controller
default-storage-engine = innodb
innodb_file_per_table = on
max_connections = 4096
collation-server = utf8_general_ci
# 或者utf8mb4_unicode_ci和utf8mb4字符集===>mysql官方推荐
character-set-server = utf8
# 如果按照官方的教程时,这里注意千万不能是utf8mb4,虽然MySQL推荐使用utf8mb4
# 否则会报错:[SQL: u'\nCREATE TABLE migrate_version (\n\trepository_id VARCHAR(250) NOT NULL, \n\trepository_path TEXT, \n\tversion INTEGER, \n\tPRIMARY KEY (repository_id)\n)\n\n']
# <https://www.cnblogs.com/youran-he/p/8176081.html>
# 如果写错了,需要删除数据库,并重建
# 或者创建数据库时指定
#服务启动并加入开启启动:
sudo systemctl enable mariadb.service && sudo systemctl start mariadb.service
# 初始化mysql的设置
sudo mysql_secure_installation
# 设置root密码,这里用openstack,需要允许远程登录,其他都可以yes
# 安装rabbitmq,消息队列
sudo yum install -y rabbitmq-server
sudo systemctl enable rabbitmq-server.service && sudo systemctl start rabbitmq-server.service
#添加openstack用户: 用户名 密码
sudo rabbitmqctl add_user openstack openstack
#为openstack用户添加读写权限:
sudo rabbitmqctl set_permissions openstack ".*" ".*" ".*"
# 安装memcached缓存
sudo yum install -y memcached python-memcached
# 编辑配置文件:
sudo vim /etc/sysconfig/memcached
# 添加一个域名
OPTIONS="-l 127.0.0.1,::1,controller"
#服务启动并设置开启启动
sudo systemctl enable memcached.service &&sudo systemctl start memcached.service
# 安装etcd服务,用于管理配置文件的,不转也行
sudo yum -y install etcd
# 修改配置文件:
sudo vim /etc/etcd/etcd.conf
# 修改以下几项,localhost改成controller
#[Member]
ETCD_LISTEN_PEER_URLS="http://192.168.137.30:2380" ETCD_LISTEN_CLIENT_URLS="http://192.168.137.30:2379"
ETCD_NAME="controller"
#[Clustering]
ETCD_INITIAL_ADVERTISE_PEER_URLS="http://192.168.137.30:2380" ETCD_ADVERTISE_CLIENT_URLS="http://192.168.137.30:2379" ETCD_INITIAL_CLUSTER="controller=http://192.168.137.30:2380"
# 这里的controller名字和上面的ETCD_NAME对应
ETCD_INITIAL_CLUSTER_TOKEN="etcd-cluster-01"
#只有一个
ETCD_INITIAL_CLUSTER_STATE="new"
# 服务启动并设置开机启动
sudo systemctl enable etcd && sudo systemctl start etcd
3. KeyStone组件
Keystone作为Openstack的核心模块,为Nova(计算),Glance(镜像),Swift(对象存储),Cinder(块存储),Neutron(网络)以及Horizon(Dashboard)提供认证服务.
3.1. KeyStone理论知识
3.1.1. KeyStone架构
除了涉及到Keystone模块之外,还有KeystoneMiddleware子项目,KeystoneMiddleware是对Keystone提供的对令牌合法性进行验证的中间件,缓存了相关的证书和令牌信息.
Keystone项目本身,除了后端的数据库,主要包含了一个处理RestFful请求的API服务进程,这些API涵盖了Identity,Token,Catalogy和Plolicy提供的各种各种服务,不同的服务都是有相应的后端Driver(BackendDriver)来实现.
3.1.2. KeyStone中的基本概念
- User:User即用户,他们代表可以通过keystone进行访问的人或程序.Users通过认证信息(credentials,如密码,API Keys等)进行验证.
- Tenant:Tenant即租户,它是各个服务中的一些可以访问的资源集合.
- 在Nova中一个tenant可以是一些机器,
- 在Swift和Glance中一个tenant可以是一些镜像存储,
- 在Neutron中一个tenant可以是一些网络资源.
- Users默认的总是绑定到某些tenant上.
- Role:Role即角色,Roles代表一组用户可以访问的资源权限,例如Nova中的虚拟机,Glance中的镜像.
- Users可以被添加到任意一个全局的或租户的角色中.
- 在全局的role中,用户的role权限作用于所有的租户,即可以对所有的租户执行role规定的权限;
- 在租户内的role中,用户仅能在当前租户内执行role规定的权限.
- Service:Service即服务,如Nova,Glance,Swift.根据前三个概念(User,Tenant和Role)一个服务可以确认当前用户是否具有访问其资源的权限.但是当一个user尝试着访问其租户内的service时,他必须知道这个service是否存在以及如何访问这个service,这里通常使用一些不同的名称表示不同的服务.
- Endpoint:Endpoint,翻译为"端点"(AWS,Docker和GCP中都有这个概念),我们可以理解它是一个服务暴露出来的访问点,如果需要访问一个服务,则必须知道他的endpoint.
- 因此,在keystone中包含一个endpoint模板,这个模板提供了所有存在的服务endpoints信息.
- 一个endpoint template包含一个URLs列表,列表中的每个URL都对应一个服务实例的访问地址,并且具有public,private和admin这三种权限.
- public url可以被全局访问(如http://compute.example.com)
- private url只能被局域网访问(如http://compute.example.local)
- admin url被从常规的访问中分离.
- Token:Token是访问资源的钥匙.它是通过Keystone验证后的返回值,在之后的与其他服务交互中只需要携带Token值即可.每个Token都有一个有效期,Token只在有效期内是有效的.
3.1.3. KeyStone各个概念的关系
- 租户下,管理着一堆用户(人,或程序).
- 每个用户都有自己的credentials(凭证)用户名+密码或者用户名+API key,或其他凭证.
- 用户在访问其他资源(计算,存储)之前,需要用自己的credential去请求keystone服务,获得验证信息(主要是Token信息)和服务信息(服务目录和它们的endpoint).
- 用户拿着Token信息,就可以去访问特定的资源了.
3.1.4. KeyStone工作流程
3.2. 安装和配置KeyStone
以下都是在controller节点上的操作
#数据库相关操作:
mysql -uroot -popenstack <<EOF
create database keystone;
#CREATE DATABASE `keystone` CHARACTER SET 'utf8' COLLATE 'utf8_general_ci';
GRANT ALL PRIVILEGES ON keystone.* TO 'keystone'@'localhost' IDENTIFIED BY 'openstack';
GRANT ALL PRIVILEGES ON keystone.* TO 'keystone'@'%' IDENTIFIED BY 'openstack';
EOF
# 安装相关包并配置
sudo yum install -y openstack-keystone httpd mod_wsgi
# mod_wsgi是python用来处理数据库请求的组件
sudo vim /etc/keystone/keystone.conf
# 内容如下
[database]
# 大约737行
connection = mysql+pymysql://keystone:openstack@controller/keystone
# keystone:密码@主机名/数据库
[token]
# 2924行,打开注释,一种provider,还有uuid
provider = fernet
# 初始化数据库,创建数据结构:
sudo su -
su -s /bin/sh -c "keystone-manage db_sync" keystone
# 会填充44个表
# 这里如果出问题,可以把上面的配置文件中
# debug=true # 154
# 然后查看 /var/log/keystone/keystone.log
# 初始化fernet密钥存储库
keystone-manage fernet_setup --keystone-user keystone --keystone-group keystone
keystone-manage credential_setup --keystone-user keystone --keystone-group keystone
# 创建keystone的服务端口:
keystone-manage bootstrap --bootstrap-password openstack --bootstrap-admin-url http://controller:35357/v3/ --bootstrap-internal-url http://controller:5000/v3/ --bootstrap-public-url http://controller:5000/v3/ --bootstrap-region-id RegionOne
#配置http 服务
sudo vim /etc/httpd/conf/httpd.conf
# 添加ServerName,96行
ServerName controller
#给/usr/share/keystone/wsgi-keystone.conf创建一个软连接
sudo ln -s /usr/share/keystone/wsgi-keystone.conf /etc/httpd/conf.d/
#服务启动并设置开机自启
sudo systemctl enable httpd.service && sudo systemctl start httpd.service
sudo su
vim /root/admin-openrc-test
# 内容如下
export OS_USERNAME=admin
export OS_PASSWORD=openstack
export OS_PROJECT_NAME=admin
export OS_USER_DOMAIN_NAME=Default
export OS_PROJECT_DOMAIN_NAME=Default
export OS_AUTH_URL=http://controller:35357/v3
export OS_IDENTITY_API_VERSION=3
# source一下
source /root/admin-openrc-test
# 创建域,项目,用户和角色
# 创建项目
openstack project create --domain default --description "Service Project" service
# 输出如下
#+-------------+----------------------------------+
#| Field | Value |
#+-------------+----------------------------------+
#| description | Service Project |
#| domain_id | default |
#| enabled | True |
#| id | fd7cc47eeb784aa08f0f3a626c2723b5 |
#| is_domain | False |
#| name | service |
#| parent_id | default |
#| tags | [] |
#+-------------+----------------------------------+
openstack project create --domain default --description "Demo Project" demo
# 下面这句要分开执行,要输入密码:
# 创建租户 demo
openstack user create --domain default --password-prompt demo
# 输入密码,我这里密码就是用户名demo
# 创建用户
openstack role create user
openstack role add --project demo --user demo user
# 验证keystone是否可用
unset OS_AUTH_URL OS_PASSWORD
# 把上面的环境变量去掉
#下面这句要分开执行,要输入admin用户的密码:
openstack --os-auth-url http://controller:35357/v3 \
--os-project-domain-name Default \
--os-user-domain-name Default \
--os-project-name admin \
--os-username admin token issue
# 获取admin的token 35357端口,密码是openstack
#下面这句要分开执行,要输入demo用户的密码:
openstack --os-auth-url http://controller:5000/v3 \
--os-project-domain-name Default \
--os-user-domain-name Default \
--os-project-name demo --os-username demo token issue
# 普通用户demo的token,密码是demo
# 创建openstack客户端的脚本环境
# 创建管理员的账号
vim admin-openrc
# 要管理admin,每次source一下,然后再操作
export OS_PROJECT_DOMAIN_NAME=Default
export OS_USER_DOMAIN_NAME=Default
export OS_PROJECT_NAME=admin
export OS_USERNAME=admin
export OS_PASSWORD=openstack
export OS_AUTH_URL=http://controller:35357/v3
export OS_IDENTITY_API_VERSION=3
# 认证服务的版本是3
export OS_IMAGE_API_VERSION=2
# 镜像服务的版本是2
# 验证直接获取token
source /root/admin-openrc
opentack token issue
# 创建demo用户的账号
vim demo-openrc
# 普通用户的脚本
export OS_PROJECT_DOMAIN_NAME=Default
export OS_USER_DOMAIN_NAME=Default
export OS_PROJECT_NAME=demo
export OS_USERNAME=demo
export OS_PASSWORD=demo
export OS_AUTH_URL=http://controller:5000/v3
export OS_IDENTITY_API_VERSION=3
export OS_IMAGE_API_VERSION=2
# 使用脚本验证
source demo-openrc
openstack token issue
东西不少,但是流程还是比较清楚的.
4. Glance组件
Image service项目代号Glance,是OpenStack的镜像服务组件.Glance主要提供了一个虚拟机镜像文件的存储,查询和检索服务,通过提供一个虚拟磁盘映像目录和存储库,为Nova的虚拟机提供镜像服务,现在Glance具有V1和V2两个版本.
4.1. Glance理论知识
4.1.1. Glance的架构
- Glance-api:是一个对外的API接口,能够接受外部的API镜像请求.主要用于分析,分发,响应各种镜像管理的REST Request,然后通过其他模块(EG. glance-registry,Store Backend后端存储接口)完成镜像的发现,获取,存储等操作.默认绑定端口是9292.
- glance-registry:用于存储,处理,获取Image Metadata.通过响应从glance-api发送过来的Image Metadata REST Request,然后与MySQL进行交互,实现Image Metadate的存储,处理,获取.默认绑定的端口是9191.
- glance-db:在Openstack中使用MySQL来支撑,用于存放Image Metadata.
- Image Metadate(镜像元数据):指通过glance-registry来保存在MySQL Database.
- Image Store:用于存储镜像文件.通过Store Backend后端存储接口来与glance-api联系.通过这个接口,glance可以从Image Store获取镜像文件再交由Nova用于创建虚拟机.
- Glance 通过Store Adapter(存储适配器)支持多种Imange Store方案.支持swift,file system,s3,sheepdog,rbd,cinder等.
4.1.2. Glance支持的镜像格式
- raw:非结构化的镜像格式
- vhd:一种通用的虚拟机磁盘格式, 可用于Vmware,Xen,Microsoft Virtual PC/Virtual Server/Hyper-V,VirtualBox等
- vmdk:Vmware的虚拟机磁盘格式, 同样也支持多种Hypervisor
- vdi:VirtualBox,QEMU等支持的虚拟机磁盘格式
- qcow2:一种支持QEMU并且可以动态扩展的磁盘格式
- aki:Amazon Kernel 镜像
- ari:Amazon Ramdisk 镜像
- ami:Amazon 虚拟机镜像
4.1.3. Glance的访问权限
- Public(公共的):可以被所有的Tenant使用.
- Private(私有的/项目的):只能被Image Owner所在的Tenant使用.
- Shared(共享的):一个非公共的Image可以共享给指定的Tenant,通过member-*操作来实现.
- Protected(受保护的):Protected Image不能被删除.
4.1.4. Glance中镜像的状态
- Queued:没有上传Image数据,只SQL Database中存有该镜像的元数据.
- Saving:正在上传Image.
- Active:正常状态.
- Deleted/pending_delete:已删除/等待删除的Image.
- Killed:Image元数据不正确,等待被删除.
4.1.4.1. 镜像状态的互相转换
- ‘queued’ => (‘saving’, ‘active’, ‘deleted’)
- ‘saving’ => (‘active’, ‘killed’, ‘deleted’, ‘queued’)
- ‘active’ => (‘queued’, ‘pending_delete’, ‘deleted’)
- ‘killed’ => (‘deleted’)
- ‘pending_delete’ => (‘deleted’)
- ‘deleted’ => ()
4.1.5. Glance两种API的区别
4.1.5.1. Glance_V1
V1的功能:提供了基本的Image和Member操作
- 镜像文件的创建,删除,查询,更改
- 镜像Tenant成员的创建,删除和查询
V1包含有glance-api和glance-registry两个WSGI service,都提供了REST API接口来接收虚拟机镜像管理的请求.
需要注意的是:
glance-api 不会真正去处理REST Request,可以将glance-api再分为两部分:
- 一部分是中间件,主要用于对REST Request的分析,分发工作.
- 另一部分来提供实际的服务Store Backend后端存储接口交互,实现镜像上传,下载)
所以若glance-api接收到涉及SQL Database的操作请求时,会调用registry-client并生成HTTP指令,然后转发给glance-registry API进行处理.
4.1.5.2. Glance_V2
V2的功能:除了拥有V1的功能之外,还能够:
- 镜像Location的添加,删除和修改
- Metadata,Namespace,Image tag操作
V2在实现上,把glance-registry和glance-api合并到了一起,减少了一个中间环节.
4.2. 安装和配置Glance
以下都是在controller节点上的操作
#数据库相关操作:
mysql -uroot -popenstack <<EOF
create database glance;
#CREATE DATABASE `glance` CHARACTER SET 'utf8' COLLATE 'utf8_general_ci';
GRANT ALL PRIVILEGES ON glance.* TO 'glance'@'localhost' IDENTIFIED BY 'openstack';
GRANT ALL PRIVILEGES ON glance.* TO 'glance'@'%' IDENTIFIED BY 'openstack';
EOF
#创建glance用户,并在service项目中添加管理员角色
sudo su
source /root/admin-openrc
#下面这句要分开执行,要输入glance用户的密码:
openstack user create --domain default --password-prompt glance
# 密码设置为glance
# service租户中添加admin权限
openstack role add --project service --user glance admin
#创建glance服务
openstack service create --name glance --description "OpenStack Image" image
#创建glance端口
openstack endpoint create --region RegionOne image public http://controller:9292
openstack endpoint create --region RegionOne image internal http://controller:9292
openstack endpoint create --region RegionOne image admin http://controller:9292
#安装相关包并配置
yum install -y openstack-glance
vim /etc/glance/glance-api.conf
# 改得有点多
[database]
connection = mysql+pymysql://glance:openstack@controller/glance
#1943行
[keystone_authtoken]
www_authenticate_uri = http://controller:5000
# 管理用的,3489行
# 现在变成了www_authenticate_uri,以前是auth_uri
auth_url = http://controller:35357
# 普通用户的,3506
memcached_servers = controller:11211
# 3555行
auth_type = password
# 3665行
project_domain_name = Default
user_domain_name = Default
project_name = service
username = glance
password = glance
# 3665行,auth_type下面
[paste_deploy]
flavor = keystone
# 4511行
[glance_store]
stores = file,http
# 2068行
default_store = file
# 2112行
filesystem_store_datadir = /var/lib/glance/images/
# 2431行
vim /etc/glance/glance-registry.conf
# 修改
[database]
connection = mysql+pymysql://glance:openstack@controller/glance
# 1189行
[keystone_authtoken]
www_authenticate_uri = http://controller:5000
#1302
auth_url = http://controller:35357
#1319
memcached_servers = controller:11211
#1370
auth_type = password
#1479
project_domain_name = Default
user_domain_name = Default
project_name = service
username = glance
password = glance
[paste_deploy]
flavor = keystone
#2302
#初始化数据库表结构
su -s /bin/sh -c "glance-manage db_sync" glance
# glance数据库中会生成15个表
#服务启动并设置开启自启
systemctl enable openstack-glance-api.service openstack-glance-registry.service && systemctl start openstack-glance-api.service openstack-glance-registry.service
# 验证
source admin-openrc
#下载实验镜像cirros
wget http://download.cirros-cloud.net/0.3.5/cirros-0.3.5-x86_64-disk.img
#创建镜像:
openstack image create "cirros" --file cirros-0.3.5-x86_64-disk.img --disk-format qcow2 --container-format bare --public
# 查看
openstack image list
# 状态时active
5. Nova组件
Nova是openstack中最核心的组件.openstack的其他组件归根结底是为Nova组件服务的,基于用户需求为VM提供计算资源管理.
5.1. Nova理论知识
5.1.1. Nova的架构
目前的Nova主要由API,Compute,Conductor,Scheduler四个核心服务组成,他们之间通过AMQP通信. API是进入Nova的HTTP接口.Compute和VMM(虚拟机管理器)交互来运行虚拟机并管理虚拟机的生命周期(通常是一个主机一个compute服务).Scheduler从可用池中选择最合适的节点来创建虚拟机实例.
5.1.2. Nova的逻辑模块
Nova服务是由多个子服务构成,子服务是通过RPC实现通信.服务之间有很松的耦合性.各个逻辑模块如下:
- Nova API :HTTP服务,用于接收和处理客户端发送的HTTP请求
- Nova Cell :Nova Cell子服务的目的便于实现横向扩展和大规模的部署,同时不增加数据库和RPC消息中间件的复杂度.在Nova Scheduler服务的主机调度的基础上实现了区域调度.
- Nova Cert :用于管理证书,为了兼容AWS.AWS提供一整套的基础设施和应用程序服务,使得几乎所有的应用程序在云上运行.
- Nova Compute :Nova组件中最核心的服务,实现虚拟机管理的功能.实现了在计算节点上创建,启动,暂停,关闭和删除虚拟机,虚拟机在不同的计算节点间迁移,虚拟机安全控制,管理虚拟机磁盘镜像以及快照等功能.
- Nova Conductor :RPC服务,主要提供数据库查询功能.以前的openstack版本中,Nova Compute子服务中定义了许多的数据库查询方法.但是,由于Nova Compute子服务需要在每个计算节点上启动,一旦某个计算节点被攻击,就将完全获得数据库的访问权限.有了Nova Compute子服务之后,便可在其中实现数据库访问权限的控制.
- Nova Scheduler :Nova调度子服务.当客户端向Nova 服务器发起创建虚拟机请求时,决定将虚拟机创建在哪个节点上.
- Nov Console,Nova Consoleauth,Nova VNCProxy :Nova控制台子服务.功能是实现客户端通过代理服务器远程访问虚拟机实例的控制界面.
5.1.3. Nova启动一个虚拟机的过程
非常重要:根据改流程来检查日志信息
- 界面或者命令行通过RESTful API向keystone发送认证信息.
- Keystone通过用户认证消息,并生成auth_token返回给对应的认证请求.
- 界面或者命令行通过RESTful API向nova API发送一个boot instance的请求(携带auth-token)
- nova-api接受请求后,向keystone发送认证请求,查看token是否为有效用户的token.
- keystone验证token是否有效,如有效,则返回有效的认证和对应的角色(备注:有些操作需要有角色权限才能操作)
- 通过认证后,nova-api和数据库通信.
- 初始化新建虚拟机的数据库记录.
- nova-api通过rpc.call向nova-scheduler请求是否有创建虚拟机的资源(Host ID).
- nova-schduler进程监听消息队列,获取nova-api的请求.
- nova-scheduler通过nova数据库中计算资源的的情况,并通过调度算法计算符合虚拟机创建需要的的主机.
- 对于有符合虚拟机创建的主机,nova-scheduler更新数据库虚拟机对应的物理主机信息.
- nova-scheduler通过rpc.cast向nova-compute发送对应的创建虚拟机请求的消息.,
- nova-compute会从对应的消息队列中获取创建虚拟机请求的消息.
- nova-compute通过rpc.call向nova-conductor请求获取虚拟机消息(flavor).
- nova-conductor从消息队列中拿到nova-compute请求信息.
- nova-conductor根据消息查询虚拟机对应的消息.
- nova-conductor 从数据库中获取虚拟机对应信息.
- nova-conductor把虚拟机信息通过消息的方式发送的消息队列中.
- nova-compute从对应的消息队列中获取虚拟节信息消息.
- nova-compute通过keystone的RESTfull API拿到的认证的token,并通过HTTP请求glance-api获取创建虚拟机所需要的镜像.
- glance-api向keystone认证token是否有效,并返回验证结果.
- token验证通过,nova-compute获取虚拟机镜像信息(URL).
- nova-compute通过keystone的RESTfull API拿到的认证的token,并通过HTTP请求neutron-server获取创建虚拟机所需要的网络信息.
- neutron-server向keystone认证token是否有效,并返回验证结果.
- token验证通过,nova-compute获取网络信息.
- nova-compute通过keystone的RESTfull API拿到的认证的token,并通过HTTP请求cinder-api获取创建虚拟机所需要的持久化存储信息.
- cinder-api向keystone认证token是否有效,并返回验证结果.
- token验证通过,nova-compute获取虚拟机持久化存储信息.
- nova-compute根据instance的信息调用配置的虚拟化驱动来创建虚拟机.
5.1.4. Nova_Scheduler_Filter的类型
选择一个虚拟机在哪个主机运行的方式有多种,nova支持的方式主要有以下三种:
- ChanceScheduler(随机调度器):从所有nova-compute服务正常运行的节点中随机选择.
- FilterScheduler(过滤调度器):根据指定的过滤条件以及权重挑选最佳节点.
- CachingScheduler:FilterScheduler一种,在FileterScheduler的基础上,将主机资源的信息存到本地的内存中,然后通过后台的定时任务定时的从数据库中获取最新的主机资源信息.
5.1.4.1. Nova_Filter_Scheduler的工作流程和具体类型
NovaFilterScheduler首先使用指定的Fileters(过滤器)得到符合条件的主机,比如内存小于50%,然后对得到的主机重新计算权重并且排列,获取最佳的一个.具体的Filter有如下几种:
-
RetryFilter (重试过滤): 假设Host1,Host2,Host3过滤筛选出来了,Host1权重最高,被选中,由于其它原因VM在Host1上落地失败,nova-scheduler会重新筛选新的host;Host1因为失败不会再入选.可通过scheduler_max_attempts=3 设置重试的次数.
-
AvalilabilityZoneFilter (可选域过滤): 可以提供容灾性和隔离服务,计算节点可以纳入一个创建好的AZ中,创建VM的时候可以指定AZ,这样虚拟机会落到指定的host中.
-
RamFilter (内存过滤): 创建VM时会选择flavor,不满足flavor中内存要求的host会过滤掉.可以通过linux里面的free来查看,超量使用的设置:ram_allocation_ratio=3(如果计算节点有16G内存,那个openstack会认为有48G内存).
-
CoreFilter (CPU core过滤): 创建VM时会选择flavor,不满足flavor中core要求的host会过滤掉.CPU的超量设置 cpu_allocaion_ratio=16.0(若计算节点为24core,那么openstack会认为348core)
-
DiskFilter (磁盘容量过滤): 创建VM时会选择flavor,不满足flavor中磁盘要求的host会过滤掉.Disk超量使用设置:disk_allocation_ratio=1.0(硬盘容量不建议调大)
-
ComputeFilter (nova-compute服务的正常过滤): 创建VM时,若host的nova-compute的服务不正常,那么就会别筛掉.
-
ComputeCababilitiesFilter (节点特性过滤): 根据计算节点的特性来筛选.例如x86_64
-
ImagePropertiesFilter (镜像属性): 根据所选的image的属性来匹配计算节点 例如希望某个image只能运行在KVM的hypervisor上,可以通过"Hypervisor Type"属性来指定.
-
ServerGroupAntiAffinityFilter (尽量将Instance部署到不同的节点上): 例如vm1,vm2,vm3,计算节点有Host1,host2,host3.
-
创建一个anti-affinity策略 server group “group-1”:
nova server-group-create –policy anti-affinity group-1 nova boot-image IMAGE_ID –flavor 1 –hint group-group1 vm1 nova boot-image IMAGE_ID –flavor 1 –hint group-group1 vm2 nova boot-image IMAGE_ID –flavor 1 –hint group-group1 vm3
-
-
ServerGroupAffinityFilter (尽量将Instance部署到同一节点上) : 例如vm1,vm2,vm3,计算节点有Host1,host2,host3.
-
创建一个group-affinity策略 server group “group-2”:
nova server-group-create –policy group-affinity group-2 nova boot-image IMAGE_ID –flavor 1 –hint group-group2 vm1 nova boot-image IMAGE_ID –flavor 1 –hint group-group2 vm2 nova boot-image IMAGE_ID –flavor 1 –hint group-group2 vm3
-
5.2. 安装和配置Nova
5.2.1. Controller节点
# 数据库相关操作:
mysql -uroot -popenstack <<EOF
#create database nova_api;
#create database nova;
#create database nova_cell0;
create database nova_api CHARACTER SET 'utf8' COLLATE 'utf8_general_ci';
create database nova CHARACTER SET 'utf8' COLLATE 'utf8_general_ci';
create database nova_cell0 CHARACTER SET 'utf8' COLLATE 'utf8_general_ci';
GRANT ALL PRIVILEGES ON nova_api.* TO 'nova'@'localhost' IDENTIFIED BY 'openstack';
GRANT ALL PRIVILEGES ON nova_api.* TO 'nova'@'%' IDENTIFIED BY 'openstack';
GRANT ALL PRIVILEGES ON nova.* TO 'nova'@'localhost' IDENTIFIED BY 'openstack'; GRANT ALL PRIVILEGES ON nova.* TO 'nova'@'%' IDENTIFIED BY 'openstack';
GRANT ALL PRIVILEGES ON nova_cell0.* TO 'nova'@'localhost' IDENTIFIED BY 'openstack';
GRANT ALL PRIVILEGES ON nova_cell0.* TO 'nova'@'%' IDENTIFIED BY 'openstack';
EOF
sudo su
#创建nova用户,并在service项目中添加管理员角色
source /root/admin-openrc
#下面这句要分开执行,要输入nova用户的密码:
openstack user create --domain default --password-prompt nova
# 密码设置为nova
# 创建role
openstack role add --project service --user nova admin
#创建nova服务及端口
openstack service create --name nova --description "OpenStack Compute" compute
openstack endpoint create --region RegionOne compute public http://controller:8774/v2.1
openstack endpoint create --region RegionOne compute internal http://controller:8774/v2.1
openstack endpoint create --region RegionOne compute admin http://controller:8774/v2.1
#创建placement用户,并在service项目中添加管理员角色
source /root/admin-openrc
#下面这句要分开执行,要输入nova用户的密码:
openstack user create --domain default --password-prompt placement
# 密码时placement
openstack role add --project service --user placement admin
#创建placement服务及端口
openstack service create --name placement --description "Placement API" placement
openstack endpoint create --region RegionOne placement public http://controller:8778
openstack endpoint create --region RegionOne placement internal http://controller:8778
openstack endpoint create --region RegionOne placement admin http://controller:8778
#安装相关包并配置
yum install -y openstack-nova-api openstack-nova-conductor openstack-nova-console openstack-nova-novncproxy openstack-nova-scheduler openstack-nova-placement-api
vim /etc/nova/nova.conf
# 修改如下
[DEFAULT]
my_ip = 192.168.137.30
# 1295
use_neutron = True
#1760
firewall_driver = nova.virt.firewall.NoopFirewallDriver
#2422
enabled_apis = osapi_compute,metadata
# 2760行
transport_url = rabbit://openstack:openstack@controller
# 3160
[api_database]
connection = mysql+pymysql://nova:openstack@controller/nova_api
#3518行
[database]
connection = mysql+pymysql://nova:openstack@controller/nova
#4642行
[api]
auth_strategy = keystone
# 3227
[keystone_authtoken]
# 这两个时以前的
www_authenticate_uri = http://controller:5000
# 6142
auth_url = http://controller:35357
# 现在官方文档直接一个auth_url
auth_url = http://controller:5000/v3
memcached_servers = controller:11211
#6209
auth_type = password
#6318
project_domain_name = Default
user_domain_name = Default
project_name = service
username = nova
password = nova
[vnc]
enabled = true
#10308
server_listen =192.168.137.30
# 10332 以前时vncserver_listen
server_proxyclient_address = 192.168.137.30
# 10345 以前时vncserver_proxyclient_address
[glance]
api_servers = http://controller:9292
#5352
[oslo_concurrency]
lock_path = /var/lib/nova/tmp
# 7439
[placement]
os_region_name = RegionOne
#8341
project_domain_name = Default
#8409
project_name = service
#8404
auth_type = password
#8383
user_domain_name = Default
8442
auth_url = http://controller:35357/v3
#8389
username = placement
#8432
password = placement
#8440
# 检查以下
egrep -v '^#|^$' /etc/nova/nova.conf
#编辑配置文件
vim /etc/httpd/conf.d/00-nova-placement-api.conf
# 在最后添加
<Directory /usr/bin>
<IfVersion >= 2.4>
Require all granted
</IfVersion>
<IfVersion < 2.4>
Order allow,deny
Allow from all
</IfVersion>
</Directory>
systemctl restart httpd
#初始化nova_api数据库表结构:
su -s /bin/sh -c "nova-manage api_db sync" nova
# 以前可能会出现如下错误:/usr/lib/python2.7/site-packages/oslo_db/sqlalchemy/enginefacade.py:332: NotSupportedWarning: Configuration option(s) ['use_tpool'] not supported
# exception.NotSupportedWarning
#修改文件:
#vim /usr/lib/python2.7/site-packages/oslo_db/sqlalchemy/enginefacade.py
#175 行,'db_max_retry_interval', 'backend', 后加入 'use_tpool'即可.
#注册cell0数据库
su -s /bin/sh -c "nova-manage cell_v2 map_cell0" nova
#创建cell1:
su -s /bin/sh -c "nova-manage cell_v2 create_cell --name=cell1 --verbose" nova
#初始化nova数据库的表结构:
su -s /bin/sh -c "nova-manage db sync" nova
# 会有一个warning
#以上数据填充后
# nova会有110个表
# nova_api32个表
# nove_cell0,110个
#验证cell0和cell1是否注册
nova-manage cell_v2 list_cells
#服务启动并加入开机自启
systemctl enable openstack-nova-api.service openstack-nova-consoleauth.service openstack-nova-scheduler.service openstack-nova-conductor.service openstack-nova-novncproxy.service
systemctl start openstack-nova-api.service openstack-nova-consoleauth.service openstack-nova-scheduler.service openstack-nova-conductor.service openstack-nova-novncproxy.service
# 查看
openstack compute service list
5.2.2. Compute节点
#安装相关包并进行配置
sudo yum install -y openstack-nova-compute
sudo vim /etc/nova/nova.conf
# 这个也不少,除了databse,和几个IP,其他一样
[DEFAULT]
my_ip = 192.168.137.31
#1295, compute的ip
use_neutron = True
#1761
firewall_driver = nova.virt.firewall.NoopFirewallDriver
#2423
enabled_apis = osapi_compute,metadata
#2760
transport_url = rabbit://openstack:openstack@controller
#3160
[api]
auth_strategy = keystone
#3229
[keystone_authtoken]
auth_url = http://controller:5000/v3
# 现在只需要这个,6128
#auth_uri = http://controller:5000
#auth_url = http://controller:35357
memcached_servers = controller:11211
#6208
auth_type = password
#6316
project_domain_name = Default
user_domain_name = Default
project_name = service
username = nova
password = nova
[vnc]
enabled = True
#10303
server_listen = 0.0.0.0
#10327
server_proxyclient_address =192.168.137.31
#10340
novncproxy_base_url = http://192.168.137.30:6080/vnc_auto.html
#10358,这里时控制节点的ip
[glance]
api_servers = http://controller:9292
#5350
[oslo_concurrency]
lock_path = /var/lib/nova/tmp
#7933
[placement]
os_region_name = RegionOne
#8833
project_domain_name = Default
#8905
project_name = service
#8898
auth_type = password
#8875
user_domain_name = Default
#8932
auth_url = http://controller:35357/v3
#8882
username = placement
# 8925
password = placement
#8935
# 查看是否支持虚拟化
egrep -c '(vmx|svm)' /proc/cpuinfo
#1
#若返回0
#vim /etc/nova/nova.conf
#[libvirt]
#virt_type = qemu #6433
#服务启动,并加入开启自启
sudo systemctl enable libvirtd.service openstack-nova-compute.service && sudo systemctl start libvirtd.service openstack-nova-compute.service
5.2.3. 在Controller节点完成最后的操作
#将compute节点添加到cell数据库
sudo su
source /root/admin-openrc
openstack compute service list --service nova-compute
# 可以看到compute节点
su -s /bin/sh -c "nova-manage cell_v2 discover_hosts --verbose" nova
# 把compute节点添加进cell====>手动
# 以下修改后,可以实现自动
#vim /etc/nova/nova.conf:
#[scheduler]
#discover_hosts_in_cells_interval = 300 #8994行
# 重启
# systemctl restart openstack-nova-api
# 验证
source /root/admin-openrc
openstack compute service list
# nova-consoleauth,nova-scheduler,nova-conductor,nova-compute
openstack catalog list
openstack image list
nova-status upgrade check
6. Neutron组件
Quantum(Neutron的前身)在Openstack的Folsom(2012年9月发布)版本正式发布,其实它已经作为试用组件包含在之前的Essex版本中.在Grizzly里功能得到了增强.因为商标侵权的原因,Openstack在Havana版本上将Quantum更名为Neutron,所以Neutron并不是什么新的东西.在Havana版里,Neutron也只增加和增强了少数功能.
Neutron是OpenStack中的一个项目,在各接口设备之间提供网络即服务(networking as a service),而且受其他OpenStack服务管理,如Nova.
具体来说,Neutron为OpenStack云更灵活地划分物理网络,在多租户环境下提供给每个租户独立的网络环境.另外,Neutron提供API来实现这种目标.Neutron中"网络"是一个可以被用户创建的对象,如果要和物理环境下的概念映射的话,这个对象相当于一个巨大的交换机,可以拥有无限多个动态可创建和销毁的虚拟端口.
6.1. Neutron理论知识
6.1.1. 网络虚拟化的原因
为了满足云计算的需求:
-
数据中心的现有网络不能满足云计算的物理要求
互联网行业数据中心的基本特征就是服务器的规模偏大.进入云计算时代后,其业务特征变得更加复杂,包括:虚拟化支持,多业务承载,资源灵活调度等.与此同时,互联网云计算的规模不但没有缩减,反而更加庞大.这就给云计算的网络带来了巨大的压力.
以上特点会带来以下问题:
- 大容量的MAC表项和ARP表项:
虚拟化会导致更大的MAC表项.假设一个互联网云计算中心的服务器有5000台,按照1:20的比例进行虚拟化,则有10万个虚拟机.通常每个虚拟机会配置两个业务网口,这样这个云计算中心就有20万个虚拟网口,对应的就是需要20万个MAC地址和IP地址.云计算要求资源灵活调度,业务资源任意迁移.也就是说任意一个虚拟机可以在整个云计算网络中任意迁移.这就要求全网在一个统一的二层网络中.全网任意交换机都有可能学习到全网所有的MAC表项.与此对应的则是,目前业界主流的接入交换机的MAC表项只有32K,基本无法满足互联网云计算的需求.另外,网关需要记录全网所有主机,所有网口的ARP信息.这就需要网关设备的有效ARP表项超过20万.大部分的网关设备芯片都不具备这种能力.
- 4K VLAN Trunk问题
传统的大二层网络支持任意VLAN的虚拟机迁移到网络的任意位置,一般有两种方式.方式一:虚拟机迁移后,通过自动化网络管理平台动态的在虚拟机对应的所有端口上下发VLAN配置;同时,还需要动态删除迁移前虚拟机对应所有端口上的VLAN配置.这种方式的缺点是实现非常复杂,同时自动化管理平台对多厂商设备还面临兼容性的问题,所以很难实现.方式二:在云计算网络上静态配置VLAN,在所有端口上配置VLAN trunk all.这种方式的优点是非常简单,是目前主流的应用方式.但这也带来了巨大的问题:任一VLAN内如果出现广播风暴,则全网所有VLAN内的虚拟机都会受到风暴影响,出现业务中断.
- 4K VLAN上限问题
云计算网络中有可能出现多租户需求.如果租户及业务的数量规模超出VLAN的上限(4K),则无法支撑客户的需求.
- 虚拟机迁移网络依赖问题
VM迁移需要在同一个二层域内,基于IP子网的区域划分限制了二层网络连通性的规模.
- 大容量的MAC表项和ARP表项:
-
数据中心的现有网络不能满足云计算软件化即SDN(Software Define Network)的需求.
数据中心(Data Center)中的物理网络是固定的,需要手工配置的,单一的,没有多租户隔离的网络.这是一个Csico给出的一个物理网络局部实例:
(图中的一个服务器有三块网卡,分别连到连接数据网络和管理网络的交换机.)
而云架构往往是多租户架构,这意味着多个客户会共享单一的物理网络.因此,除了提供基本的网络连接能力以外,云还需要提供网络在租户之间的隔离能力;同时云是自服务的,这意味着租户可以通过云提供的 API 来使用虚拟出的网络组建来设计,构建和部署各种他们需要的网络.如下图:
MidoNet是类似于OpenContrail, Neutron DVR, DragonFlow, OVN的SDN产品,其主要特性如下:
- L2交换,L3路由,L4负载均衡
- 有状态和无状态NAT
- 逻辑和分布式防火墙
- BGP与ECMP支持
- GRE,VxLAN
- VTEP(VXLAN Tunneling End Point) support with OVSDB protocol
- partial docker integration
- Re-written with Java/scala.
其架构如下:
在计算节点上要运行Midolman也就是MidoAgent来同时具备L2-L4层干活功能.采用分布式数据库NSDB来作集中的控制平面存储port, node, mac等映射关系.另外,它还支持BGP,如下图,它并不支持在同一个数据中心的多个跨三层的openstack之间运行iBGP(走GRE/VxLAN隧道),只支持在跨广域网的多个数据中心之间运行eBGP.如下图所示.
openStack 云也不例外. OpenStack 通过 Neutron 项目在物理网络环境之上提供满足多租户要求的虚拟网络和服务.Neutron 提供的网络虚拟化能力包括:
- 二层到七层网络的虚拟化:L2(virtual switch),L3(virtual Router 和 LB),L4-7(virtual Firewall )等
- 网络连通性:二层网络和三层网络
- 租户隔离性
- 网络安全性
- 网络扩展性
- REST API
- 更高级的服务,包括 LBaaS.
6.1.2. Neutron的架构
管理员创建和管理Neutron外部网络,是租户虚拟机与互联网信息交互的桥梁.更具体的,外部网络会分出一个子网,它是一组在互联网上可寻址的IP地址.一般情况下,外部网络只有一个(neutron是支持多个外部网络的,比如说公司的官网),且由管理员创建.租户虚拟机创建和管理租户网络,每个网络可以根据需要划分成多个子网.诸多子网通过路由器与Neutron外部网络(图中具体是子网A)连接.路由器的gateway网关端连接外部网络的子网,interfaces接口端有多个,连接租户网络的子网.路由器及interface接口端连接的网络都是由租户根据需要自助创建,管理者只创建和管理Neutron外部网络部分.
总结来看,创建一个Neutron网络的过程如下:
- 首先管理员拿到一组可以在互联网上寻址的IP地址,并且创建一个外部网络和子网
- 租户创建一个网络和子网
- 租户创建一个路由器并且连接租户子网和外部网络
- 租户创建虚拟机
6.1.3. Neutron支持的网络模型
单一平面网络:在 OpenStack 网络组件没有独立出来之前,OpenStack 最初的 nova-network 网络模型,如图 10-7.
单一平面网络的缺点:
- 存在单一网络瓶颈,缺乏可伸缩性.
- 缺乏合适的多租户隔离.
OpenStack nova-network 独立成为单独的组件 Neutron 后,形象的网络模型的多平面网络,混合平面私有网络.
-
多平面网络:
-
混合平面私有网络:
-
通过私有网络实现运营商路由功能
-
通过私有网络实现每个租户创建自己专属的网络区段:这个时最常用的
6.1.4. Neutron中的各种概念
Neutron 管理的网络资源包括 Network,subnet 和 port,下面依次介绍.
6.1.4.1. Network
network 是一个隔离的二层广播域.Neutron 支持多种类型的 network,包括 local, flat, VLAN, VxLAN 和 GRE.
- Local:local 网络与其他网络和节点隔离.local 网络中的 instance 只能与位于同一节点上同一网络的 instance 通信,local 网络主要用于单机测试.
- Flat:flat 网络是无 vlan tagging 的网络.flat 网络中的 instance 能与位于同一网络的 instance 通信,并且可以跨多个节点.
- Vlan:vlan 网络是具有 802.1q tagging 的网络.vlan 是一个二层的广播域,同一 vlan 中的 instance 可以通信,不同 vlan 只能通过 router 通信.vlan 网络可以跨节点,是应用最广泛的网络类型.
- Vxlan:vxlan 是基于隧道技术的 overlay 网络.vxlan 网络通过唯一的 segmentation ID(也叫 VNI)与其他 vxlan 网络区分.vxlan 中数据包会通过 VNI 封装成 UPD 包进行传输.因为二层的包通过封装在三层传输,能够克服 vlan 和物理网络基础设施的限制.
- gre:gre 是与 vxlan 类似的一种 overlay 网络.主要区别在于使用 IP 包而非 UDP 进行封装. 不同 network 之间在二层上是隔离的.
以 vlan 网络为例,network A 和 network B 会分配不同的 VLAN ID,这样就保证了 network A 中的广播包不会跑到 network B 中.当然,这里的隔离是指二层上的隔离,借助路由器不同 network 是可能在三层上通信的.
network 必须属于某个 Project( Tenant 租户),Project 中可以创建多个 network.network 与 Project 之间是 1对多关系.
6.1.4.2. subnet
subnet 是一个 IPv4 或者 IPv6 地址段.instance 的 IP 从 subnet 中分配.每个 subnet 需要定义 IP 地址的范围和掩码.
subnet 与 network 是 多对1关系.一个 subnet 只能属于某个 network;一个 network 可以有多个 subnet,这些 subnet 可以是不同的 IP 段,但不能重叠.下面的配置是有效的:
network A
subnet A-a: 10.10.1.0/24 {"start": "10.10.1.1", "end": "10.10.1.50"}
subnet A-b: 10.10.2.0/24 {"start": "10.10.2.1", "end": "10.10.2.50"}
但下面的配置则无效,因为 subnet 有重叠
networkA
subnet A-a: 10.10.1.0/24 {"start": "10.10.1.1", "end": "10.10.1.50"}
subnet A-b: 10.10.1.0/24 {"start": "10.10.1.51", "end": "10.10.1.100"}
这里不是判断 IP 是否有重叠,而是 subnet 的 CIDR 重叠(都是 10.10.1.0/24)
但是,如果 subnet 在不同的 network 中,CIDR 和 IP 都是可以重叠的,比如
networkA
subnet A-a: 10.10.1.0/24 {"start": "10.10.1.1", "end": "10.10.1.50"}
networkB
subnet B-a: 10.10.1.0/24 {"start": "10.10.1.1", "end": "10.10.1.50"}
这里大家不免会疑惑: 如果上面的IP地址是可以重叠的,那么就可能存在具有相同 IP 的两个 instance,这样会不会冲突? 简单的回答是:不会!
具体原因: 因为 Neutron 的 router 是通过 Linux network namespace 实现的.network namespace 是一种网络的隔离机制.通过它,每个 router 有自己独立的路由表.
上面的配置有两种结果:
- 如果两个 subnet 是通过同一个 router 路由,根据 router 的配置,只有指定的一个 subnet 可被路由.
- 如果上面的两个 subnet 是通过不同 router 路由,因为 router 的路由表是独立的,所以两个 subnet 都可以被路由.
6.1.4.3. port
port 可以看做虚拟交换机上的一个端口.port 上定义了 MAC 地址和 IP 地址,当 instance 的虚拟网卡 VIF(Virtual Interface) 绑定到 port 时,port 会将 MAC 和 IP 分配给 VIF.
port 与 subnet 是 1对多关系.一个 port必须属于某个subnet;一个subnet 可以有多个 port.
6.1.4.4. network_port_subnet的关系
下面总结了 Project,Network,Subnet,Port 和 VIF 之间关系.
Project 1 : m Network 1 : m Subnet 1 : m Port 1 : 1 VIF m : 1 Instance
6.1.5. Neutron中的Plugin和agent
6.2. 安装和配置Neutron
以下例子是基于LinuxBridge+Vxlan模式的.
6.2.1. Controller节点
mysql -uroot -popenstack <<EOF
create database neutron ;
#create database neutron CHARACTER SET 'utf8' COLLATE 'utf8_general_ci';
GRANT ALL PRIVILEGES ON neutron.* TO 'neutron'@'localhost' IDENTIFIED BY 'openstack';
GRANT ALL PRIVILEGES ON neutron.* TO 'neutron'@'%' IDENTIFIED BY 'openstack';
EOF
#创建neutron用户,并在service项目中添加管理员角色
sudo su
source /root/admin-openrc
#下面这句要分开执行,要输入neutron用户的密码:
openstack user create --domain default --password-prompt neutron
# 密码为neutron
openstack role add --project service --user neutron admin
#创建网络服务及端口
openstack service create --name neutron --description "OpenStack Networking" network
openstack endpoint create --region RegionOne network public http://controller:9696
openstack endpoint create --region RegionOne network admin http://controller:9696
openstack endpoint create --region RegionOne network internal http://controller:9696
#安装相关包并进行配置
yum install -y openstack-neutron openstack-neutron-ml2 openstack-neutron-linuxbridge ebtables
#下面有两种配置方式:使用第二种
# Provider: https://docs.openstack.org/neutron/stein/install/controller-install-option1-rdo.html
# Self-service: https://docs.openstack.org/neutron/stein/install/controller-install-option2-rdo.html
#编辑配置文件:
vim /etc/neutron/neutron.conf
# 也是不少
[DEFAULT]
auth_strategy = keystone
#27
core_plugin = ml2
#31
service_plugins = router
#34
allow_overlapping_ips = true
#87
notify_nova_on_port_status_changes = true
#100
notify_nova_on_port_data_changes = true
#104
transport_url = rabbit://openstack:openstack@controller
#573
[keystone_authtoken]
www_authenticate_uri = http://controller:5000
#837,下面直接加上
auth_url = http://controller:5000
memcached_servers = controller:11211
#906
auth_type = password
#1013,下面的直接添加
project_domain_name = Default
user_domain_name = Default
project_name = service
username = neutron
password = neutron
[database]
connection = mysql+pymysql://neutron:openstack@controller/neutron
#733
[nova]
auth_url = http://controller:35357
#1096
auth_type = password
#1100
project_domain_name = Default
#1141
user_domain_name = Default
#1171
region_name = RegionOne
#1079
project_name = service
#1149
username = nova
#1178
password = nova
#1134
[oslo_concurrency]
lock_path = /var/lib/neutron/tmp
#1194 ,显示是使用 $state_path 这个变量在9 行
# 两种配置方法,主要是ml2_conf.ini的配置略有不同
vim /etc/neutron/plugins/ml2/ml2_conf.ini
# 内容如下
[ml2]
type_drivers = flat,vlan,vxlan
#136
tenant_network_types = vxlan
#142
mechanism_drivers = linuxbridge,l2population
#146
extension_drivers = port_security
#152
[ml2_type_flat]
flat_networks = provider
#189
[ml2_type_vxlan]
vni_ranges = 1:1000
#243
[securitygroup]
enable_ipset = true
#267
vim /etc/neutron/plugins/ml2/linuxbridge_agent.ini
# 内容如下
[linux_bridge]
physical_interface_mappings = provider:ens34
#157,使用桥接的那张网卡
[vxlan]
enable_vxlan = true
#209
local_ip = 172.17.2.30
#235,这个是那个桥接的ens39的网卡
l2_population = true
#260
[securitygroup]
enable_security_group = true
#194
firewall_driver = neutron.agent.linux.iptables_firewall.IptablesFirewallDriver
#189
#确认操作系统内核支持桥接:
echo "net.bridge.bridge-nf-call-iptables = 1" >> /etc/sysctl.conf
echo "net.bridge.bridge-nf-call-ip6tables = 1" >> /etc/sysctl.conf
sysctl -p
#如果"sysctl -p"加载不成功,报" No such file or directory"错误,需要加载内核模块"br_netfilter";
#命令"modinfo br_netfilter"查看内核模块信息;
#命令"modprobe br_netfilter"加载内核模块
#再次执行 sysctl -p
vim /etc/neutron/l3_agent.ini
# 一个
[DEFAULT]
interface_driver = linuxbridge
#16
vim /etc/neutron/dhcp_agent.ini
#3个
[DEFAULT]
interface_driver = linuxbridge
#16
dhcp_driver = neutron.agent.linux.dhcp.Dnsmasq
#28
enable_isolated_metadata = true
#38
vim /etc/neutron/metadata_agent.ini
# 2个
[DEFAULT]
nova_metadata_host = 192.168.137.30
#22
metadata_proxy_shared_secret = openstack
#34
vim /etc/nova/nova.conf
# 最后一点
[neutron]
url = http://controller:9696
#7132
auth_url = http://controller:35357
#7208
auth_type = password
#7202
project_domain_name = Default
#7229
user_domain_name = Default
#7255
region_name = RegionOne
#7276
project_name = service
# 7223
username = neutron
#7249
password = neutron
#7258
service_metadata_proxy = true
#7171
metadata_proxy_shared_secret = openstack
#7182
ln -s /etc/neutron/plugins/ml2/ml2_conf.ini /etc/neutron/plugin.ini
#初始化neutron数据库及表结构:
su -s /bin/sh -c "neutron-db-manage --config-file /etc/neutron/neutron.conf --config-file /etc/neutron/plugins/ml2/ml2_conf.ini upgrade head" neutron
#共166个表
#重启nova服务
systemctl restart openstack-nova-api.service
#服务启动并设置开机自启
systemctl enable neutron-server.service neutron-linuxbridge-agent.service neutron-dhcp-agent.service neutron-metadata-agent.service && systemctl start neutron-server.service neutron-linuxbridge-agent.service neutron-dhcp-agent.service neutron-metadata-agent.service
#由于用的第二种方法,需要开启l3
systemctl enable neutron-l3-agent.service && systemctl start neutron-l3-agent.service
6.2.2. Compute节点
sudo su
yum install -y openstack-neutron-linuxbridge ebtables ipset
vim /etc/neutron/neutron.conf
# 不少
[DEFAULT]
transport_url = rabbit://openstack:openstack@controller
#570
auth_strategy = keystone
#27
[keystone_authtoken]
www_authenticate_uri = http://controller:5000
#832,上下两个一起
auth_url = http://controller:5000
memcached_servers = controller:11211
#898
auth_type = password
#1005,下面直接机上
project_domain_name = Default
user_domain_name = Default
project_name = service
username = neutron
password = neutron
[oslo_concurrency]
lock_path = /var/lib/neutron/tmp
#1179
vim /etc/neutron/plugins/ml2/linuxbridge_agent.ini
# 就一点
[linux_bridge]
physical_interface_mappings = provider: ens34
#157
[vxlan]
enable_vxlan = true
#208
local_ip = 172.17.2.31
#234
l2_population = true
#258
[securitygroup]
enable_security_group = true
#193
firewall_driver = neutron.agent.linux.iptables_firewall.IptablesFirewallDriver
#188
vim /etc/nova/nova.conf
# 只需要配置neutron
[neutron]
url = http://controller:9696
#7626
auth_url = http://controller:35357
#7702
auth_type = password
#7696
project_domain_name = Default
#7723
user_domain_name = Default
#7749
region_name = RegionOne
#7770
project_name = service
#7717
username = neutron
#7743
password = neutron
#7752
#重启nova-compute服务
systemctl restart openstack-nova-compute.service
#启动服务并设置开机自启
systemctl enable neutron-linuxbridge-agent.service && systemctl start neutron-linuxbridge-agent.service
6.2.3. Controller节点进行验证
sudo su
source /root/admin-openrc
openstack extension list --network
# 只要能返回列表,就ok
openstack network agent list
# 返回5个
# L3 agent
# Linux bridge agent(计算和控制各有一个)
# DHCP agent
# Metadata agent
7. Horizon组件
图形化界面
7.1. 安装和配置Horizon
在Controller节点操作
yum install -y openstack-dashboard
vim /etc/openstack-dashboard/local_settings
# 修改如下
OPENSTACK_HOST = "controller"
#188
ALLOWED_HOSTS = ['*']
#38
SESSION_ENGINE = 'django.contrib.sessions.backends.cache'
# 默认是没有的,和下面的放在一起下面是在158行,下面的需要注释掉167行
CACHES = {
'default': {
'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache',
'LOCATION': 'controller:11211',
}
}
注释掉其他cache
OPENSTACK_KEYSTONE_URL = "http://%s:5000/v3" % OPENSTACK_HOST
#191 不需要修改
OPENSTACK_KEYSTONE_MULTIDOMAIN_SUPPORT = True
#75 如果注释掉,首页就不需要输入domain
# 下面再64行
OPENSTACK_API_VERSIONS = {
"identity": 3,
"image": 2,
"volume": 2,
}
OPENSTACK_KEYSTONE_DEFAULT_DOMAIN = "Default"
# 97,
OPENSTACK_KEYSTONE_DEFAULT_ROLE = "user"
# 192
# 325行
OPENSTACK_NEUTRON_NETWORK = {
'enable_router': True,
'enable_quotas': True,
'enable_ipv6': True,
'enable_distributed_router': True, # 这个
'enable_ha_router': True, # 这个
'enable_lb': True, # 这些是增加的
'enable_firewall': True,
'enable_vpn': False,
'enable_fip_topology_check': True,
}
TIME_ZONE = "Asia/Chongqing"
# 468
vim /etc/httpd/conf.d/openstack-dashboard.conf
# 最下面增加一行
WSGIApplicationGroup %{GLOBAL}
systemctl restart httpd.service memcached.service
# 访问: 192.168.137.30/dashboard
# 用户名:admin 密码:openstack domain:default
8. 创建一个实例
8.1. 创建虚拟网络
8.1.1. 创建provider网络
对租户网络提供服务的
sudo su
source /root/admin-openrc
openstack network create --share --external \
--provider-physical-network provider \
--provider-network-type flat provider
#创建外部网络,名称为provider 共享类型的外部网络的flat
openstack subnet create --network provider \
--allocation-pool start=192.168.1.100,end=192.168.1.200 \
--dns-nameserver 223.5.5.5 --gateway 192.168.1.1 \
--subnet-range 192.168.1.1/24 provider
# 外部网络子网.和桥接网卡网段相同
8.1.2. 创建私有网络self-services
source /root/demo-openrc
openstack network create selfservice
# 租户网络
openstack subnet create --network selfservice \
--dns-nameserver 223.5.5.5 --gateway 172.16.1.1 \
--subnet-range 172.16.1.0/24 selfservice
# 租户子网,可以随意指定,
openstack router create router
# 路由
openstack router add subnet router selfservice
# 给路由添加子网
openstack router set router --external-gateway provider
# 设置路由的外部网关
8.1.3. 验证
source /root/admin-openrc
ip netns
# 应该会返回3个namespace 一个qrouter,2个qdhcp
openstack port list --router router
ping 192.168.1.104
# ping上面的地址
8.2. 创建flavor
启动虚拟机的模板
source /root/admin-openrc
# 使用admin
openstack flavor create --id 0 --vcpus 1 --ram 64 --disk 1 m1.nano
openstack flavor list
8.3. 生成密钥对
source /root/demo-openrc
ssh-keygen -q -N ""
openstack keypair create --public-key ~/.ssh/id_rsa.pub mykey
# 用于控制服务器无密码登录
openstack keypair list
8.4. 添加安全组规则
source /root/demo-openrc
openstack security group rule create --proto icmp default
#ping
openstack security group rule create --proto tcp --dst-port 22 default
# ssh
8.5. 启动一个实例
source /root/demo-openrc
openstack flavor list
openstack image list
openstack network list
openstack security group list
openstack security group show default
openstack security group rule list
# 启动一个实例
openstack server create --flavor m1.nano --image cirros \
--nic net-id=fe10a7f4-fb43-47c8-9e0d-8af7b7df2f52 --security-group default \
--key-name mykey selfservice-instance
# 虚拟机名字 selfservice-instance
# 都是可以是id也可以是名字,
# 使用selfservice的network
# 如果报错,可能是没有开启虚拟化
# 注意要开启CPU的虚拟化
# 或者nova.conf中 virt_type改成qemu
# 查看虚拟机信息
openstack server list
# 有哪些server
openstack server show b5acfca7-52ef-460a-b620-de87bb8f61e7
# 可以直接ssh到虚拟机中
ssh cirros@192.168.1.162
# 用可视化界面看看:http://192.168.137.30/dashboard/admin/instances/
openstack console log show b5acfca7-52ef-460a-b620-de87bb8f61e7
# 查看控制台信息.
9. Cinder组件
操作系统获得存储空间的方式一般有两种:
- 通过某种协议(SAS,SCSI,SAN,iSCSI 等)挂接裸硬盘,然后分区,格式化,创建文件系统;或者直接使用裸硬盘存储数据(数据库)
- 通过 NFS,CIFS 等 协议,mount 远程的文件系统
第一种裸硬盘的方式叫做 Block Storage(块存储),每个裸硬盘通常也称作 Volume(卷) 第二种叫做文件系统存储.NAS 和 NFS 服务器,以及各种分布式文件系统提供的都是这种存储. Block Storage Service提供对 volume 从创建到删除整个生命周期的管理. 从 instance 的角度看,挂载的每一个 Volume 都是一块硬盘.
OpenStack 提供 Block Storage Service 的是 Cinder,其具体功能是:
- 提供 REST API 使用户能够查询和管理 volume,volume snapshot 以及 volume type
- 提供 scheduler 调度 volume 创建请求,合理优化存储资源的分配
- 通过 driver 架构支持多种 back-end(后端)存储方式,包括 LVM,NFS,Ceph 和其他诸如 EMC,IBM 等商业存储产品和方案
9.1. Cinder理论知识
9.1.1. Cinder的架构
Cinder 包含如下几个组件:
- cinder-api:接收 API 请求,调用 cinder-volume 执行操作.
- cinder-volume:管理 volume 的服务,与 volume provider 协调工作,管理 volume 的生命周期.运行 cinder-volume 服务的节点被称作为存储节点.
- cinder-scheduler:scheduler 通过调度算法选择最合适的存储节点创建 volume.
- volume provider:数据的存储设备,为 volume 提供物理存储空间. cinder-volume 支持多种 volume provider,每种 volume provider 通过自己的 driver 与cinder-volume 协调工作.
- Message Queue:Cinder 各个子服务通过消息队列实现进程间通信和相互协作.因为有了消息队列,子服务之间实现了解耦,这种松散的结构也是分布式系统的重要特征.
- Database Cinder:有一些数据需要存放到数据库中,一般使用 MySQL.数据库是安装在控制节点上的,比如在我们的实验环境中,可以访问名称为"cinder"的数据库.
9.2. 安装和配置Cinder
9.2.1. Controller节点
#数据库相关操作:
mysql -uroot -popenstack <<EOF
create database cinder;
GRANT ALL PRIVILEGES ON cinder.* TO 'cinder'@'localhost' IDENTIFIED BY 'openstack';
GRANT ALL PRIVILEGES ON cinder.* TO 'cinder'@'%' IDENTIFIED BY 'openstack';
EOF
#创建cinder用户,并在service项目中添加管理员角色
sudo su -
source admin_openrc
#下面这句要分开执行,要输入cinder用户的密码:
openstack user create --domain default --password-prompt cinder
#密码cinder
openstack role add --project service --user cinder admin
#创建cinder服务及端口
openstack service create --name cinderv2 --description "OpenStack Block Storage" volumev2
openstack service create --name cinderv3 --description "OpenStack Block Storage" volumev3
openstack endpoint create --region RegionOne volumev2 public http://controller:8776/v2/%\(project_id\)s
openstack endpoint create --region RegionOne volumev2 internal http://controller:8776/v2/%\(project_id\)s
openstack endpoint create --region RegionOne volumev2 admin http://controller:8776/v2/%\(project_id\)s
openstack endpoint create --region RegionOne volumev3 public http://controller:8776/v3/%\(project_id\)s
openstack endpoint create --region RegionOne volumev3 internal http://controller:8776/v3/%\(project_id\)s
openstack endpoint create --region RegionOne volumev3 admin http://controller:8776/v3/%\(project_id\)s
#安装包并修改配置
yum install -y openstack-cinder
vim /etc/cinder/cinder.conf
# 内容如下
[database]
connection = mysql+pymysql://cinder:openstack@controller/cinder
[DEFAULT]
transport_url = rabbit://openstack:openstack@controller
[DEFAULT]
auth_strategy = keystone
[keystone_authtoken]
auth_uri = http://controller:5000
auth_url = http://controller:35357
memcached_servers = controller:11211
auth_type = password
project_domain_name = Default
user_domain_name = Default
project_name = service
username = cinder
password = cinder
[DEFAULT]
my_ip = 192.168.137.30
[oslo_concurrency]
lock_path = /var/lib/cinder/tmp
#初始化数据库
su -s /bin/sh -c "cinder-manage db sync" cinder
#配置计算服务使用cinder
vim /etc/nova/nova.conf
[cinder]
os_region_name = RegionOne
#计算服务重启
systemctl restart openstack-nova-api.service
#服务启动并设置开机自启
systemctl enable openstack-cinder-api.service openstack-cinder-scheduler.service && systemctl start openstack-cinder-api.service openstack-cinder-scheduler.service
9.2.2. Block节点
#添加一个新磁盘 /dev/sdb
#安装相关包,并进行配置
yum install -y lvm2 device-mapper-persistent-data
systemctl enable lvm2-lvmetad.service && systemctl start lvm2-lvmetad.service
pvcreate /dev/sdb
vgcreate cinder-volumes /dev/sdb
vim /etc/lvm/lvm.conf
# 内容如下
devices { ... filter = [ "a/sdb/", "r/.*/"]
#若操作系统安装时候了lvm,必须也要accept,配置如下,
devices { ... filter = ["a/sda/", "a/sdb/", "r/.*/"]
yum install -y openstack-cinder targetcli python-keystone
vim /etc/cinder/cinder.conf
# 内容如下
[database]
connection = mysql+pymysql://cinder:openstack@controller/cinder
[DEFAULT]
transport_url = rabbit://openstack: openstack@controller
[DEFAULT]
auth_strategy = keystone
[keystone_authtoken]
auth_uri = http://controller:5000
auth_url = http://controller:35357
memcached_servers = controller:11211
auth_type = password
project_domain_name = Default
user_domain_name = Default
project_name = service
username = cinder
password = cinder
[DEFAULT]
my_ip = 192.168.137.32
[lvm]
volume_driver = cinder.volume.drivers.lvm.LVMVolumeDriver
volume_group = cinder-volumes
iscsi_protocol = iscsi
iscsi_helper = lioadm
[DEFAULT]
enabled_backends = lvm
[DEFAULT]
glance_api_servers = http://controller:9292
[oslo_concurrency]
lock_path = /var/lib/cinder/tmp
#服务启动并加入到开机自启
systemctl enable openstack-cinder-volume.service target.service && systemctl start openstack-cinder-volume.service target.service
9.2.3. Controller节点验证
source .admin-openrc
openstack volume service list
9.2.4. 给虚拟机分配一个虚拟磁盘
. demo-openrc
openstack volume create --size 1 volume1
openstack volume list
openstack server add volume provider-instance volume1
openstack volume list
10. Swift组件
OpenStack Object Storage(Swift)是OpenStack开源云计算项目的子项目之一,被称为对象存储,提供了强大的扩展性,冗余和持久性.对象存储,用于永久类型的静态数据的长期存储.
Swift 最初是由 Rackspace 公司开发的高可用分布式对象存储服务,并于 2010 年贡献给 OpenStack 开源社区作为其最初的核心子项目之一,为其 Nova 子项目提供虚机镜像存储服务.Swift 构筑在比较便宜的标准硬件存储基础设施之上,无需采用 RAID(磁盘冗余阵列),通过在软件层面引入一致性散列技术和数据冗余性,牺牲一定程度的数据一致性来达到高可用性和可伸缩性,支持多租户模式,容器和对象读写操作,适合解决互联网的应用场景下非结构化数据存储问题.
10.1. Swift理论知识
10.1.1. Swift基本原理1_一致性散列
一致性Hash是由麻省理工学院在1997年提出的一种DHT算法,目的是为了解决分布式网络中的热点问题.其基本思想是将物理节点和key按照相同的hash算法映射到0~2^32的虚拟的散列空间环上.当接收到一个读/写请求时,计算key值K的哈希值Hash(k),如果该值与某个物理节点的hash值相同,就直接对该物理节点进行读/写操作;如果不同,就按照顺时针方向查找到第一个物理节点,对该节点进行读写操作;如果超过了〖0~2〗^32从0开始从新查找.
一致性Hash的过程如下几个步骤组成:
- 计算每个对象的hash值,并且把它们均匀的分布到一个0~2^32圆形散列的地址空间上;
- 假设有2^m个存储节点,将存储空间均匀分成2^m等份,每一份的虚拟空间大小为2^(32-m);
- 假设一个对象的hash值为n,那么其对应的存储节点为n⁄2^(32-m) .相当于将hash值向右位移(32-m)位.
在Swift对象存储系统中,为了减少节点的加入或者是删除导致的大规模的数据迁移,引入了虚拟节点的概念.以前的存储方式由对象→物理节点的一层映射关系演变成对象→虚拟节点→物理节点的两层映射关系.
在整个Swift对象存储系统的生命周期中,虚拟节点的总数是不变的,在构建Swift对象存储系统的时,考虑整个物理存储集群的最大值,虚拟节点总数是物理节点总数的100倍.
10.1.2. Swift基本原理2_数据一致性模型
按照 Eric Brewer 的 CAP(Consistency,Availability,Partition Tolerance)理论,无法同时满足 3 个方面,Swift 放弃严格一致性(满足 ACID 事务级别),而采用最终一致性模型(Eventual Consistency),来达到高可用性和无限水平扩展能力.为了实现这一目标,Swift 采用 Quorum 仲裁协议(Quorum 有法定投票人数的含义):
- 定义:N:数据的副本总数;W:写操作被确认接受的副本数量;R:读操作的副本数量
- 强一致性:R+W>N,以保证对副本的读写操作会产生交集,从而保证可以读取到最新版本;如果 W=N,R=1,则需要全部更新,适合大量读少量写操作场景下的强一致性;如果 R=N,W=1,则只更新一个副本,通过读取全部副本来得到最新版本,适合大量写少量读场景下的强一致性.
- 弱一致性:R+W<=N,如果读写操作的副本集合不产生交集,就可能会读到脏数据;适合对一致性要求比较低的场景.
Swift 针对的是读写都比较频繁的场景,所以采用了比较折中的策略,即写操作需要满足至少一半以上成功 W >N/2,再保证读操作与写操作的副本集合至少产生一个交集,即 R+W>N.Swift 默认配置是 N=3,W=2>N/2,R=1 或 2,即每个对象会存在 3 个副本,这些副本会尽量被存储在不同区域的节点上;W=2 表示至少需要更新 2 个副本才算写成功;当 R=1 时意味着某一个读操作成功便立刻返回,此种情况下可能会读取到旧版本(弱一致性模型);当 R=2 时,需要通过在读操作请求头中增加 x-newest=true 参数来同时读取 2 个副本的元数据信息,然后比较时间戳来确定哪个是最新版本(强一致性模型);如果数据出现了不一致,后台服务进程会在一定时间窗口内通过检测和复制协议来完成数据同步,从而保证达到最终一致性.
10.1.3. Swift基本原理3_环的数据结构
环是为了将虚拟节点(分区)映射到一组物理存储设备上,并提供一定的冗余度而设计的,其数据结构由以下信息组成:存储设备列表,设备信息包括唯一标识号(id),区域号(zone),权重(weight),IP 地址(ip),端口(port),设备名称(device),元数据(meta).分区到设备映射关系(replica2part2dev_id 数组).计算分区号的位移(part_shift 整数,以查找一个对象的计算过程为例:
使用对象的层次结构 account/container/object 作为键,使用 MD5 散列算法得到一个散列值,对该散列值的前 4 个字节进行右移操作得到分区索引号,移动位数由上面的 part_shift 设置指定;按照分区索引号在分区到设备映射表(replica2part2dev_id)里查找该对象所在分区的对应的所有设备编号,这些设备会被尽量选择部署在不同区域(Zone)内,区域只是个抽象概念,它可以是某台机器,某个机架,甚至某个建筑内的机群,以提供最高级别的冗余性,建议至少部署 5 个区域;权重参数是个相对值,可以来根据磁盘的大小来调节,权重越大表示可分配的空间越多,可部署更多的分区.Swift为账户,容器和对象分别定义了的环,查找账户和容器的是同样的过程.
10.1.4. Swift基本原理4_数据模型
Swift 采用层次数据模型,共设三层逻辑结构:Account/Container/Object(即账户/容器/对象),每层节点数均没有限制,可以任意扩展.这里的账户和个人账户不是一个概念,可理解为租户,用来做顶层的隔离机制,可以被多个个人账户所共同使用;容器代表封装一组对象,类似文件夹或目录;叶子节点代表对象,由元数据和内容两部分组成.
10.1.5. Swift基本原理5_系统架构
Swift 采用完全对称,面向资源的分布式系统架构设计,所有组件都可扩展,避免因单点失效而扩散并影响整个系统运转;通信方式采用非阻塞式 I/O 模式,提高了系统吞吐和响应能力.
- 代理服务(Proxy Server):对外提供对象服务 API,会根据环的信息来查找服务地址并转发用户请求至相应的账户,容器或者对象服务;由于采用无状态的 REST 请求协议,可以进行横向扩展来均衡负载.
- 认证服务(Authentication Server):验证访问用户的身份信息,并获得一个对象访问令牌(Token),在一定的时间内会一直有效;验证访问令牌的有效性并缓存下来直至过期时间.
- 缓存服务(Cache Server):缓存的内容包括对象服务令牌,账户和容器的存在信息,但不会缓存对象本身的数据;缓存服务可采用 Memcached 集群,Swift 会使用一致性散列算法来分配缓存地址.
- 账户服务(Account Server):提供账户元数据和统计信息,并维护所含容器列表的服务,每个账户的信息被存储在一个 SQLite 数据库中.
- 容器服务(Container Server):提供容器元数据和统计信息,并维护所含对象列表的服务,每个容器的信息也存储在一个 SQLite 数据库中.
- 对象服务(Object Server):提供对象元数据和内容服务,每个对象的内容会以文件的形式存储在文件系统中,元数据会作为文件属性来存储,建议采用支持扩展属性的 XFS 文件系统.
- 复制服务(Replicator):会检测本地分区副本和远程副本是否一致,具体是通过对比散列文件和高级水印来完成,发现不一致时会采用推式(Push)更新远程副本,例如对象复制服务会使用远程文件拷贝工具 rsync 来同步;另外一个任务是确保被标记删除的对象从文件系统中移除.
- 更新服务(Updater):当对象由于高负载的原因而无法立即更新时,任务将会被序列化到在本地文件系统中进行排队,以便服务恢复后进行异步更新;例如成功创建对象后容器服务器没有及时更新对象列表,这个时候容器的更新操作就会进入排队中,更新服务会在系统恢复正常后扫描队列并进行相应的更新处理.
- 审计服务(Auditor):检查对象,容器和账户的完整性,如果发现比特级的错误,文件将被隔离,并复制其他的副本以覆盖本地损坏的副本;其他类型的错误会被记录到日志中.
- 账户清理服务(Account Reaper):移除被标记为删除的账户,删除其所包含的所有容器和对象.
Ring是Swift最重要的组件,用于记录存储对象与物理位置间的映射关系.在涉及查询Account,Container,Object信息时,就需要查询集群的Ring信息. Ring使用Zone,Device,Partition和Replica来维护这些映射信息.Ring中每个Partition在集群中都(默认)有3个Replica.每个Partition的位置由Ring来维护,并存储在映射中.Ring文件在系统初始化时创建,之后每次增减存储节点时,需要重新平衡一下Ring文件中的项目,以保证增减节点时,系统因此而发生迁移的文件数量最少.
10.1.6. Swift的特性
-
极高的数据持久性 数据持久性和系统可用性不同,指的是数据的可靠性,数据存储到系统后,到某一天丢失的可能性.AS3的数据持久性是11个9,即如果存储1万个(4个0)文件到S3中,1千万(7个0)年之后,可能会丢失1个文件.
我们从理论上测算过,Swift在5个Zone,5×10个存储节点的环境下,数据复制份是为3,数据持久性的SLA能达到10个9.
-
完全对称的系统架构 “对称"意味着Swift中各节点可以完全对等,能极大地降低系统维护成本.
-
无限的可扩展性
- 数据存储容量无限可扩展;
- Swift性能(如QPS,吞吐量等)可线性提升.
Swift是完全对称的架构,扩容只需简单地新增机器,系统会自动完成数据迁移等工作,使各存储节点重新达到平衡状态.
-
无单点故障 元数据问题,Swift的元数据存储是完全均匀随机分布的,并且与对象文件存储一样,元数据也会存储多份.
-
简单,可依赖,设计简单
10.2. 安装和配置Swift
10.2.1. Controller节点
openstack user create --domain default --password-prompt swift
openstack role add --project service --user swift admin
openstack service create --name swift --description "OpenStack Object Storage" object-store
openstack endpoint create --region RegionOne object-store public http://controller:8080/v1/AUTH_%\(project_id\)s
openstack endpoint create --region RegionOne object-store internal http://controller:8080/v1/AUTH_%\(project_id\)s
openstack endpoint create --region RegionOne object-store admin http://controller:8080/v1
yum install openstack-swift-proxy python-swiftclient python-keystoneclient python-keystonemiddleware memcached
#下载swift-proxy.conf的配置文件,并修改配置:
curl -o /etc/swift/proxy-server.conf https://git.openstack.org/cgit/openstack/swift/plain/etc/proxy-server.conf-sample?h=stable/queens
vim /etc/swift/proxy-server.conf
# 内容如下
[DEFAULT]
bind_port = 8080
swift_dir = /etc/swift
user = swift
[pipeline:main]
pipeline = catch_errors gatekeeper healthcheck proxy-logging cache container_sync bulk ratelimit authtoken keystoneauth container-quotas account-quotas slo dlo versioned_writes proxy-logging proxy-server
[app:proxy-server]
use = egg:swift#proxy
account_autocreate = True
[filter:tempauth]
use = egg:swift#tempauth
user_admin_admin = admin .admin .reseller_admin
user_test_tester = testing .admin
user_test2_tester2 = testing2 .admin
user_test_tester3 = testing3
user_test5_tester5 = testing5 service
[filter:authtoken]
paste.filter_factory = keystonemiddleware.auth_token:filter_factory
www_authenticate_uri = http://controller:5000
auth_url = http://controller:35357
auth_type = password
project_domain_id = default
user_domain_id = default
project_name = service
username = swift
password = openstack
delay_auth_decision = True
[filter:keystoneauth]
use = egg:swift#keystoneauth
operator_roles = admin,user
[filter:healthcheck]
use = egg:swift#healthcheck
[filter:cache]
use = egg:swift#memcache
memcache_servers = controller:11211
[filter:ratelimit]
use = egg:swift#ratelimit
[filter:domain_remap]
use = egg:swift#domain_remap
[filter:catch_errors]
use = egg:swift#catch_errors
[filter:cname_lookup]
use = egg:swift#cname_lookup
[filter:staticweb]
use = egg:swift#staticweb
[filter:tempurl]
use = egg:swift#tempurl
[filter:formpost]
use = egg:swift#formpost
[filter:name_check]
use = egg:swift#name_check
[filter:list-endpoints]
use = egg:swift#list_endpoints
[filter:proxy-logging]
use = egg:swift#proxy_logging
[filter:bulk]
use = egg:swift#bulk
[filter:slo]
use = egg:swift#slo
[filter:dlo]
use = egg:swift#dlo
[filter:container-quotas]
use = egg:swift#container_quotas
[filter:account-quotas]
use = egg:swift#account_quotas
[filter:gatekeeper]
use = egg:swift#gatekeeper
[filter:container_sync]
use = egg:swift#container_sync
[filter:xprofile]
use = egg:swift#xprofile
[filter:versioned_writes]
use = egg:swift#versioned_writes
[filter:copy]
use = egg:swift#copy
[filter:keymaster]
use = egg:swift#keymaster
encryption_root_secret = changeme
[filter:kms_keymaster]
use = egg:swift#kms_keymaster
[filter:encryption]
use = egg:swift#encryption
[filter:listing_formats]
use = egg:swift#listing_formats
[filter:symlink]
use = egg:swift#symlink
10.2.2. 存储节点
yum install -y xfsprogs rsync
mkfs.xfs /dev/sdb
mkfs.xfs /dev/sdc
mkdir -p /srv/node/sdb
mkdir -p /srv/node/sdc
vim /etc/fstab
/dev/sdb /srv/node/sdb xfs noatime,nodiratime,nobarrier,logbufs=8 0 2
/dev/sdc /srv/node/sdc xfs noatime,nodiratime,nobarrier,logbufs=8 0 2
mount /srv/node/sdb
mount /srv/node/sdc
vim /etc/rsyncd.conf
# 内容如下
uid = swift
gid = swift
log file = /var/log/rsyncd.log
pid file = /var/run/rsyncd.pid
address = 192.168.137.33
[account]
max connections = 2
path = /srv/node/
read only = False
lock file = /var/lock/account.lock
[container]
max connections = 2
path = /srv/node/
read only = False
lock file = /var/lock/container.lock
[object]
max connections = 2
path = /srv/node/
read only = False
lock file = /var/lock/object.lock
systemctl enable rsyncd.service && systemctl start rsyncd.service
yum install -y openstack-swift-account openstack-swift-container openstack-swift-object
curl -o /etc/swift/account-server.conf https://git.openstack.org/cgit/openstack/swift/plain/etc/account-server.conf-sample?h=stable/queens
curl -o /etc/swift/container-server.conf https://git.openstack.org/cgit/openstack/swift/plain/etc/container-server.conf-sample?h=stable/queens
curl -o /etc/swift/object-server.conf https://git.openstack.org/cgit/openstack/swift/plain/etc/object-server.conf-sample?h=stable/queens
vim /etc/swift/account-server.conf
# 内容如下
[DEFAULT]
...
bind_ip = 192.168.137.33
bind_port = 6202
user = swift
swift_dir = /etc/swift
devices = /srv/node
mount_check = True
[pipeline:main]
pipeline = healthcheck recon account-server
[filter:recon]
use = egg:swift#recon
...
recon_cache_path = /var/cache/swift
vim /etc/swift/container-server.conf
# 内容如下
[DEFAULT]
...
bind_ip = 192.168.137.33
bind_port = 6201
user = swift
swift_dir = /etc/swift
devices = /srv/node
mount_check = True
[filter:recon]
use = egg:swift#recon
...
recon_cache_path = /var/cache/swift
vim /etc/swift/object-server.conf
# 内容如下
[DEFAULT]
...
bind_ip = 192.168.137.33
bind_port = 6200
user = swift
swift_dir = /etc/swift
devices = /srv/node
mount_check = True
[pipeline:main]
pipeline = healthcheck recon object-server
[filter:recon]
use = egg:swift#recon
recon_cache_path = /var/cache/swift
recon_lock_path = /var/lock
chown -R swift:swift /srv/node
mkdir -p /var/cache/swift
chown -R root:swift /var/cache/swift
chmod -R 775 /var/cache/swift
10.2.3. Create and distribute initial rings
cd /etc/swift
swift-ring-builder account.builder create 10 3 1
swift-ring-builder account.builder add \
--region 1 --zone 1 --ip 192.168.237.161 --port 6202 --device sdb --weight 100
swift-ring-builder account.builder add \
--region 1 --zone 1 --ip 192.168.237.161 --port 6202 --device sdc --weight 100
swift-ring-builder account.builder add \
--region 1 --zone 2 --ip 192.168.237.162 --port 6202 --device sdb --weight 100
swift-ring-builder account.builder add \
--region 1 --zone 2 --ip 192.168.237.162 --port 6202 --device sdc --weight 100
swift-ring-builder account.builder
swift-ring-builder account.builder rebalance
swift-ring-builder container.builder create 10 3 1
swift-ring-builder container.builder add \
--region 1 --zone 1 --ip 192.168.237.161 --port 6201 --device sdb - -weight 100
swift-ring-builder container.builder add \
--region 1 --zone 1 --ip 192.168.237.161 --port 6201 --device sdc --weight 100
swift-ring-builder container.builder add \
--region 1 --zone 2 --ip 192.168.237.162 --port 6201 --device sdb --weight 100
swift-ring-builder container.builder add \
--region 1 --zone 2 --ip 192.168.237.162 --port 6201 --device sdc --weight 100
swift-ring-builder container.builder
swift-ring-builder container.builder rebalance
swift-ring-builder object.builder create 10 3 1
swift-ring-builder object.builder add \
--region 1 --zone 1 --ip 192.168.237.161 --port 6200 --device sdb --weight 100
swift-ring-builder object.builder add \
--region 1 --zone 1 --ip 192.168.237.161 --port 6200 --device sdc --weight 100
swift-ring-builder object.builder add \
--region 1 --zone 2 --ip 192.168.237.162 --port 6200 --device sdb --weight 100
swift-ring-builder object.builder add \
--region 1 --zone 2 --ip 192.168.237.162 --port 6200 --device sdc --weight 100
swift-ring-builder object.builder
swift-ring-builder object.builder rebalance
scp account.ring.gz container.ring.gz object.ring.gz object01:/etc/swift/
scp account.ring.gz container.ring.gz object.ring.gz object02:/etc/swift/
#获取swift.conf配置文件
curl -o /etc/swift/swift.conf \
https://git.openstack.org/cgit/openstack/swift/plain/etc/swift.conf-sample?h=stable/queens
vim /etc/swift/swift.conf
# 内容如下
[swift-hash]
...
swift_hash_path_suffix = HASH_PATH_SUFFIX
swift_hash_path_prefix = HASH_PATH_PREFIX
[storage-policy:0]
...
name = Policy-0
default = yes
scp /etc/swift/swift.conf object01:/etc/swift
scp /etc/swift/swift.conf object02:/etc/swift
#所有节点执行:
chown -R root:swift /etc/swift
#控制节点:
systemctl enable openstack-swift-proxy.service memcached.service && systemctl restart openstack-swift-proxy.service memcached.service
#存储节点:
systemctl enable openstack-swift-account.service openstack-swift-account-auditor.service openstack-swift-account-reaper.service openstack-swift-account-replicator.service
systemctl restart openstack-swift-account.service openstack-swift-account-auditor.service openstack-swift-account-reaper.service openstack-swift-account-replicator.service
systemctl enable openstack-swift-container.service openstack-swift-container-auditor.service openstack-swift-container-replicator.service openstack-swift-container-updater.service
systemctl restart openstack-swift-container.service openstack-swift-container-auditor.service openstack-swift-container-replicator.service openstack-swift-container-updater.service
systemctl enable openstack-swift-object.service openstack-swift-object-auditor.service openstack-swift-object-replicator.service openstack-swift-object-updater.service
Systemctl restart openstack-swift-object.service openstack-swift-object-auditor.service openstack-swift-object-replicator.service openstack-swift-object-updater.service
10.2.4. 验证
#备注:首先检查 /var/log/audit/audit.log,若存在selinux的信息,使得swift 进程无法访问,做如下修改:
chcon -R system_u:object_r:swift_data_t:s0 /srv/node
. demo-openrc
swift stat
openstack container create container1
openstack object create container1 FILE
openstack object list container1
openstack object save container1 FILE