您好,欢迎访问代理记账网站
  • 价格透明
  • 信息保密
  • 进度掌控
  • 售后无忧

OpenStack

1.认识OpenStack

1.云计算的起源

早在2006年3月,亚马逊公司首先提出弹性计算云服务。2006年8月9日,谷歌公司首席执行官埃里克·施密特(Eric Schmidt)在谷歌搜索引擎大会(SES San Jose 2006)上首次提出“云计算”(Cloud Computing)的概念

2.云计算的基本概念

(1)云计算的定义:云计算是一种按使用量付费的模式,这种模式提供可用的便捷的按需的网络访问,进入可配置的计算资源共享池(资源包括网络、服务器、存储和应用软件等),这些资源能够被快速提供,只需投入很少的管理工作或与服务供应商进行很少的交互。
(2)云计算的五大特征:

① 按需自助服务:消费者可以单方面部署资源。例如服务器、网络存储,资源是按需自动部署的,不需要与服务供应商进行人工交互。
② 通过互联网获取:资源可以通过互联网获取,并可以通过标准方式访问。例如,通过瘦客户端或富客户端(移动电话、笔记本电脑和工作站等)。
③ 资源池化:供应商的资源被池化,以便以多用户租用模式被不同客户使用。例如,不同的物理和虚拟资源可根据客户需求动态分配和重新分配,通常与地域无关,这些资源包括存储、处理器、内存和网络带宽。
④ 快速伸缩:资源可以弹性地部署和释放,有时是自动化的,以便能够迅速地按需扩大和缩小规模。
⑤ 可计量:云计算系统通过使用一些与服务种类(存储、计算、带宽、激活的用户账号)对应的抽象信息提供计量能力(通常在此基础上实现按使用付费)。

(3)云计算的服务模型SPI
云计算的服务模型SPI由3大服务组成

IaaS     (基础设施即服务)
Saas     (平台即服务)
SaaS	 (软件即服务)

下面为详细的内容

① IaaS:消费者使用"基础计算资源”。资源服务包括处理能力、存储空间、网络组件或中间件服务。消费者能掌控操作系统、存储空间、已部署的应用程序及网络组件(如防火墙、负载均衡器等),但并不掌控云基础架构。如Amazon AWS、Rackspace等。
② PaaS:消费者使用主机操作应用程序。消费者掌控运作应用程序的环境(也拥有主机部分掌控权),但并不掌控操作系统、硬件或网络基础架构。平台通常是应用程序基础架构。如Google App Engine。
③ SaaS:消费者使用应用程序,但并不掌控操作系统、硬件或网络基础架构。它是一种服务观念的基础,软件服务供应商以租赁的概念提供客户服务,而非购买,比较常见的模式是提供一组账号密码。  

(4)云计算四大部署类型

① 私有云:云计算基础设施由一个单一的组织部署和独占使用,可由该组织、第三方或两者的组合来拥有和管理。
② 社区云:云计算基础设施由一些具有共有关注点的组织形成的社区中的用户部署和使用,可由一个或多个社区中的组织、第三方或两者的组合来拥有和管理、运营。
③ 公有云:云计算基础设施被部署给广泛的公众开放地使用。它可能被一个商业组织、研究机构、政府机构或者几者的混合所拥有、管理和运营,被一个销售云计算服务的组织所拥有,该组织将云计算服务销售于一般人或广泛的工业群体。
④ 混合云:云计算基础设施是由两种或两种以上的云(私有、社区或公共)组成,每种云仍然保持独立,但用标准的或专有的技术将它们组合起来,具有数据和应用程序的可移植性。

(5)云计算平台分类

存储型云平台以数据存储为主
计算型云平台以数据处理为主
综合云计算平台计算和数据存储处理兼顾的

2.基础环境和系统准备

1.节点主机名及IP地址规划

在这里插入图片描述

2.各节点安装系统要求

首先创建两台虚拟机
主机要求:主机为双网卡服务器或者PC机,内存为4GB以上,处理器2核以上。
环境要求:操作系统为 CentOS-7-x86_64-DVD-1511.iso和XianDian-IaaS-v2.2.iso

3.配置主机名

配置(控制节点)主机名为controller
配置(实例节点) 主机名为compute
在控制节点使用hostnamectl命令修改主机名

# hostnamectl set-hostname controller

在实例节点使用hostnamectl命令修改主机名

# hostnamectl set-hostname controller

修改完名字重启才能生效

# reboot

4.配置域名解析

在全部节点的/etc/hosts文件中添加域名解析。
在控制节点修改配置文件/etc/hosts

vi /etc /hosts
末尾追加以下内容
172.24.2.10     controller
172.24.2.20     compute

在实例节点修改配置文件/etc/hosts

vi /etc /hosts
末尾追加以下内容
172.24.2.10     controller
172.24.2.20     compute

5.配置环境

关闭防火墙

# systemctl stop firewalld		//关闭Firewalld防火墙服务
# systemctl disable firewalld	//关闭Firewalld防火墙开机自启动

实例节点(compute)配置同上
关闭selinux
配置文件存放位置/etc/selinux/config

# vi /etc/selinux
改SELINUX=enforcing为SELINUX=disabled

修改完配置文件,需要重启后生效,可以使用setenforce 0命令临时生效
关闭selinux的原因:表示系统会收到警告信息,但是不会受到限制,作为selinux的debug模式用处
实例节点(compute)配置同上

6.配置yum源

在这里插入图片描述
(1)建立源子目录

1.controller
2.compute
1.	mkdir  /var/software
2.  mkdir  /var/software
1   添加xiandian镜像和一块50G的硬盘 然后重启虚拟机
2   添加xiandian镜像和一块50G的硬盘 然后重启虚拟机
1	mkdir /mnt/iass       mkdir /mnt/centos  创建挂载点把镜像挂载上去
2	mkdir /mnt/iass       mkdir /mnt/centos  创建挂载点把镜像挂载上去
1   在iass目录下 cp -r iass-repo/ /var/software/
2  在mnt目录下 cp -r iass-repo/ /var/software/
1	在iass目录下 mkdir /var/software/centos7  在centos目录下 cp -r repodata var/software/centos7    cp -r Packages/ /var/software/centos7
2	在mnt目录下 mkdir /var/software/centos7  在centos目录下 cp -r repodata /var/software/centos7  cp -r Packages/ /var/software/centos7

实例节点(compute)配置如上一致
(2)yum源备份

# cd /etc/yum.repo
# mkdir lishi       //创建一个叫临时的目录
# mv * /lishi      //将此目录下的所有文件移动到临时目录中

实例节点(compute)配置如上一致

(3)创建repo文件
在控制节点的/etc/yum.repos.d/ 路径下创建yum.repo文件内容如下

[centos]
name=centos                            			//设置此yum的资源描述名称
baseurl=file:///var/software/centos7/		//设置yum源的访问地址路径
gpgcheck=0                              		//不使用gpg检查gpgkey
enabled=1                               		//启动此yum源
[openstack]
name=OpenStack
baseurl=file:///var/software/iass-repo/
gpgcheck=0
enabled=1 

修改完成之后
清理yum缓存并生成缓存

# yum clean all && yum makecache

实例节点(compute)配置如上一致
(4)配置ip地址
控制节点
修改配置文件/etc/sysconfig/network-scripts/ifcfg-eno16777736, 信息如下

TYPE=Ethernet
BOOTPROTO=static
DEFROUTE=yes
PEERDNS=yes
PEERROUTES=yes
IPV4_FAILURE_FATAL=no
IPV6INIT=yes
IPV6_AUTOCONF=yes
IPV6_DEFROUTE=yes
IPV6_PEERDNS=yes
IPV6_PEERROUTES=yes
IPV6_FAILURE_FATAL=no
NAME=eno16777736
UUID=17b1974f-49b3-45cf-b2e5-e2133c6c0420
DEVICE=eno16777736
ONBOOT=yes
IPADDR=172.24.2.10
NETMASK=255.255.255.0

注:ifcfg-eno16777736是仅主机模式
对配置文件/etc/sysconfig/network-scripts/ifcfg-eno33554960进行修改

TYPE=Ethernet
BOOTPROTO=static
DEFROUTE=yes
PEERDNS=yes
PEERROUTES=yes
IPV4_FAILURE_FATAL=no
IPV6INIT=yes
IPV6_AUTOCONF=yes
IPV6_DEFROUTE=yes
IPV6_PEERDNS=yes
IPV6_PEERROUTES=yes
IPV6_FAILURE_FATAL=no
NAME=eno33554960
UUID=40da3afe-717e-492b-a8f6-4a0c63737dfe
DEVICE=eno33554960
ONBOOT=yes
IPADDR=192.168.128.10
NETAMSK=255.255.255.0
GATEWAY=192.168.128.2
DNS1=114.114.114.114

注:ifcfg-eno33554960是NAT模式
修改完成重启网络

# systemctl restart network.service

实例节点
修改配置文件/etc/sysconfig/network-scripts/ifcfg-eno16777736, 信息如下。

TYPE=Ethernet
BOOTPROTO=static
DEFROUTE=yes
PEERDNS=yes
PEERROUTES=yes
IPV4_FAILURE_FATAL=no
IPV6INIT=yes
IPV6_AUTOCONF=yes
IPV6_DEFROUTE=yes
IPV6_PEERDNS=yes
IPV6_PEERROUTES=yes
IPV6_FAILURE_FATAL=no
NAME=eno16777736
UUID=17b1974f-49b3-45cf-b2e5-e2133c6c0420
DEVICE=eno16777736
ONBOOT=yes
IPADDR=172.24.2.10
NETMASK=255.255.255.0

注:ifcfg-eno16777736是仅主机模式
对配置文件/etc/sysconfig/network-scripts/ifcfg-eno33554992进行修改

TYPE=Ethernet
BOOTPROTO=static
DEFROUTE=yes
PEERDNS=yes
PEERROUTES=yes
IPV4_FAILURE_FATAL=no
IPV6INIT=yes
IPV6_AUTOCONF=yes
IPV6_DEFROUTE=yes
IPV6_PEERDNS=yes
IPV6_PEERROUTES=yes
IPV6_FAILURE_FATAL=no
NAME=eno33554960
UUID=40da3afe-717e-492b-a8f6-4a0c63737dfe
DEVICE=eno33554960
ONBOOT=yes
IPADDR=192.168.128.20
NETAMSK=255.255.255.0
GATEWAY=192.168.128.2
DNS1=114.114.114.114

注:ifcfg-eno33554992是NAT模式
修改完成重启网络

# systemctl restart network.service

(5)#控制和实例节点
安装iaas-xiandian安装包

# yum install iaas-xiandian -y

进行分区

# fdisk /dev/sdb  //分出两个大小为25G的分区
# mkfs.xfs /dev/sdb1  //进行格式化 
# mkfs.xfs /dev/sdb2  //进行格式化

编辑文件/etc/xiandian/openrc.sh(配置环境变量)
先删除文件中的所有内容在添加如下内容

HOST_IP=172.24.2.10        //仅主机模式的IP地址
HOST_NAME=controller       //控制节点的主机名
HOST_IP_NODE=172.24.2.20   //仅主机模式的IP地址
HOST_NAME_NODE=compute     //实例节点的主机名
RABBIT_USER=openstack
RABBIT_PASS=000000
DB_PASS=000000
DOMAIN_NAME=demo
ADMIN_PASS=000000
DEMO_PASS=000000
KEYSTONE_DBPASS=000000
GLANCE_DBPASS=000000
GLANCE_PASS=000000
NOVA_DBPASS=000000
NOVA_PASS=000000
NEUTRON_DBPASS=000000
NEUTRON_PASS=000000
METADATA_SECRET=000000
INTERFACE_NAME=eno33554960       //NAT模式的网卡名称
CINDER_DBPASS=000000
CINDER_PASS=000000
TROVE_DBPASS=000000
TROVE_PASS=000000
BLOCK_DISK=sdb1   
SWIFT_PASS=000000
OBJECT_DISK=sdb2
STORAGE_LOCAL_NET_IP=172.24.2.20   //实例节点的仅主机IP地址
HEAT_DBPASS=000000
HEAT_PASS=000000
CEILOMETER_DBPASS=000000
CEILOMETER_PASS=000000
AODH_DBPASS=000000
AODH_PASS=000000

实例节点(compute)配置如上一致

(6)#控制节点和实例节点
执行脚本iaas-pre-host.sh进行安装
初始化配置脚本,一定要执行,如果下面的执行脚本报错,从这一步重新开始

# iaas-pre-host.sh

(7)重启设备服务器

# reboot

(8)部署脚本安装平台
①在控制节点执行脚本iaas-install-mysql.sh进行数据库及消息列表服务安装。

# iaas-install-mysql.sh

②在控制节点执行脚本iaas-install-keystone.sh进行keystone认证服务安装。

# iaas-install-keystone.sh

③在控制节点执行脚本iaas-install-glance.sh进行glance镜像服务安装。

# iaas-install-glance.sh

④在控制节点执行脚本iaas-install-nova-controller.sh进行nova计算服务安装。

# iaas-install-nova-controller.sh

在实例节点执行脚本iaas-install-nova-compute.sh进行nova计算服务安装。

# iaas-install-nova-compute.sh

⑤在控制节点执行脚本iaas-install-neutron-controller.sh进行neutron网络服务安装。

# iaas-install-neutron-controller.sh

注:这个脚本文件有一个地方是错误的,最后一行需要修改一下

# vim /usr/local/bin/iass-install-neutron-controller-gre.sh
# 改systemctl enabled neutron-lbaas-agent为
    systemctl enable neutron-lbaas-agent

在实例节点执行脚本iaas-install-neutron -compute.sh进行neutron网络服务安装。

# iaas-install-neutron-compute.sh

⑧在控制节点执行脚本iaas-install-neutron-controller-vlan.sh进行vlan网络安装配置

# iaas-install-neutron-controller-gre.sh

在实例节点执行脚本iaas-install-neutron-compute-vlan.sh进行vlan网络安装配置

# iaas-install-neutron-compute-gre.sh

⑨在控制节点执行脚本iaas-install-dashboard.sh进行dashboard服务安装。

# iaas-install-dashboard.sh

⑩在控制节点执行脚本iaas-install-cinder-controller.sh进行cinder块存储服务安装。

# iaas-install-cinder-controller.sh

在实例节点执行脚本iaas-install-cinder-compute.sh进行cinder块存储服务安装。

# iaas-install-cinder-compute.sh

⑪在控制节点执行脚本iaas-install-swift-controller.sh进行swift对象存储服务安装。

# iaas-install-swift-controller.sh

在实例节点执行脚本iaas-install-swift-compute.sh进行swift对象存储服务安装。

# iaas-install-swift-compute.sh

⑫在控制节点执行脚本iaas-install-heat.sh进行heat编配服务安装。

# iaas-install-heat.sh

⑬在控制节点执行脚本iaas-install-ceilometer-controller.sh进行ceilometer监控服务安装。

# iaas-install-ceilometer-controller.sh

在实例节点执行脚本 iaas-install-ceilometer-compute.sh进行ceilometer监控服务安装。

# iaas-install-ceilometer-compute.sh

⑭在控制节点执行脚本iaas-install-alarm.sh进行alarm告警服务安装。

# iaas-install-alarm.sh

验证安装基础工作完成
上述操作完成后,打开网页 http://172.24.2.10/dashboard进行验证服务,若看到图2-7 dashboard登录界面,以及管理员账号和密码登录后看到图下 dashboard管理界面,表示安装基础工作正确完成。
在这里插入图片描述
** dashboard登录界面**
在这里插入图片描述

3.认证服务

认证服务的基本概念(Keystone)
在OpenStack框架中,Keystone(OpenStack Identity Service)的功能是负责验证身份、校验服务规则和发布服务令牌的,它实现了OpenStack的Identity API。Keystone可分解为两个功能,即权限管理和服务目录。权限管理主要用于用户的管理授权。服务目录,类似一个服务总线,或者说是整个OpenStack框架的注册表。认证模块提供API服务、 token 令牌机制、服务目录、规则和认证发布等功能。
认证(Authentication)
认证是确认允许一个用户访问的进程。为了确认请求,OpenStack Identity会为访问用户提供证书,起初这些证书是用户名和密码,或用户名和API key。当OpenStack Identity认证体系接受了用户的请求之后,它会发布一个认证令牌(Token),用户在随后的请求中使用这个令牌去访问资源中其他的应用。
证书(Credentials)
用于确认用户身份的数据。例如,用户名、密码或者API key,或认证服务提供的认证令牌。
令牌(Token)
通常指的是一串比特值或者字符串,用来作为访问资源的记号。Token(令牌统一用词)中含有可访问资源的范围和有效时间,一个令牌是一个任意比特的文本,用于与其他OpenStack服务来共享信息,Keystone以此来提供一个central location,以验证访问OpenStack服务的用户。令牌的有效期是有限的,可以随时被撤回。
项目(project)
project即项目,早期版本又称为project,它是各个服务中的一些可以访问的资源集合。例如,通过nova创建虚拟机时要指定到某个项目中,在cinder创建卷也要指定到某个项目中,用户访问项目的资源前,必须与该项目关联,并且指定该用户在该项目下的角色。
平台构建完毕会产生admin、service和demo三个项目。在这些项目中,admin项目代表管理组,拥有平台的最高权限,可以更新、删除和修改系统的任何数据。service代表平台内所有服务的总集合,平台安装的所有服务默认会被加入到此项目中,为后期的统一管理提供帮助,此项目可以修改当前项目下所有服务的配置信息,提交项目的内容以及修改。demo则是一个演示测试项目,没有什么实际的用处。
用户(User)
使用服务的用户,可以是人、服务或系统使用OpenStack相关服务的一个组织。例如,一个项目映射到一个Nova的“project-id”,在对象存储中,一个项目可以有多个容器。根据不同的安装方式,一个项目可以代表一个客户、账号、组织或项目。用户通过Keystone Identity认证登录系统并调用资源。用户可以被分配到特定项目并执行项目相关操作。需要特别指出的是,OpenStack通过注册相关服务用户来管理服务,例如Nova服务注册nova用户来管理相应的服务。对于管理员来说,需要通过Keystone来注册管理用户。
角色(Role)
Role即角色,Role代表一组用户可以访问的资源权限,例如Nova中的虚拟机、Glance中的镜像。Users可以被添加到任意一个全局的role或项目内的role中。在全局的role中,用户的role权限作用于所有的项目,即可以对所有的项目执行role规定的权限。在项目内的role中,用户仅能在当前项目内执行role规定的权限。
使用云服务的用户不局限于人,也可以是系统或者服务。用户可以通过指定的令牌登录系统并调用资源。用户可以被分配到特定项目并执行项目相关操作。
平台构建完毕,系统会创建_member_、admin两个用户权限,在系统中,_member_表示系统的普通用户的权限,拥有系统的正常使用和对当前项目的管理权限。admin角色是代表系统的管理员身份,对系统有绝对的管理权限。
认证服务流程
用户请求云主机的流程涉及认证Keystone服务、计算Nova服务、镜像Glance服务,在服务流程中,令牌(Token)作为流程认证传递,具体服务申请认证机制流程,如图所示。
在这里插入图片描述

1.操作过程

如果在操作的过程当中出现这种报错,更新一下配置文件
在这里插入图片描述

# source /etc/keystone/admin-openrc.sh       //更新配置文件

Keystone服务安装完毕,通过请求身份令牌来验证服务

# openstack  --os-project-name admin --os-domain-name demo --os-username admin --os-password 000000 --os-auth-url http://controller:35357/v3 token issue      //以admin用户访问http://controller:35357/v3地址获取token值

(1)创建用户
创建一个名称为“alice”账户,密码是“mypassword123”,邮箱为“alice@example.com”

# openstack user create alice --password mypassword123 --email alice@example.com  --domain demo 

扩展:创建用户命令个格式

openstack user create [--domain <domain>]
[--password <password>]
[--email <email-address>]
[--enable | --disable]
<name>
其中,参数<name>代表新建用户名。

(2)创建项目
创建一个名为“acme”项目

# openstack project create --domain demo acme

扩展:创建项目命令格式

openstack project create [--domain <domain>]
                              [--description <description>]
                              [--enable | --disable]
                              <project-name>
其中,参数<project-name>代表新建项目名,参数 <description>代表项目描述名

(3)创建角色
创建一个角色“compute-user

# openstack role create compute-user

扩展:创建角色命令格式

openstack role create <name>

(4 ) 绑定用户和项目权限
给用户“alice”分配“acme”项目下的“compute-user”角色

# openstack role add --user alice  --project acme  compute-user

扩展:绑定用户和项目权限命令格式

openstack role add --user alice  --project acme  compute-user
其中,参数 <user>代表需要绑定的用户名称,参数<role>代表用户绑定的角色名称,参数<project>代表用户绑定的项目名称

情景操作
在这里插入图片描述
●创建服务

#  openstack service create

扩展:创建服务命令格式

openstack service create --name <name>  <type>
                               [--description <description>]
参数说明。
--name <name>:创建的服务名称。
 <type>:创建服务类型。
--description <description> 创建服务描述

●查询服务目录

#  openstack catalog list

Service Catalog(服务目录)是Keystone为OpenStack提供的一个REST API端点列表,并以此作为决策参考

openstack catalog list 					# 可以显示所有已有的service
openstack catalog show <service>			# 显示某个service信息

创建项目
方法一: 通过dashboard界面为研发部创建一个名为RD_Dept的项目
在这里插入图片描述
方法二: 通过Shell界面为业务部创建一个名为BS_Dept的项目

# openstack project create "BS_Dept" --domain demo --description 业务部门
        				    	//创建业务部门BS_Dept
# openstack project show BS_Dept          //获取项目详细信息

方法三:通过脚本为工程部创建一个名为IT_Dept的项目

# ./Keystone-manage-project.sh

创建用户账号
方法一:使用web界面创建用户
在这里插入图片描述
方法二:通过Shell命令行为项目研发部创建用户rduser002,密码为cloudpasswd

# openstack user create rduser002 --password cloudpasswd --domain demo --email rduser002@example.com

方法三:通过执行Shell脚本Keystone-manage-user.sh为项目研发部创建用户rduser003~rduser050,密码为cloudpasswd。在命令行内输入# ./Keystone-manage-user.sh,执行该脚本。命令行内按提示输入用户名称、用户密码、电子邮件域名地址、用户角色(这里只能赋予一个角色)和用户所属部门。
执行命令后结果如下所示。
在这里插入图片描述
同理,可通过执行Shell脚本为业务部创建用户bsuser001~bsuser045,密码为cloudpasswd。执行脚本结果如下所示。

在这里插入图片描述
通过执行Shell脚本为IT工程部创建用户ituser001~ituser005,密码为cloudpasswd。执行过程和结果如下所示。

在这里插入图片描述
绑定用户权限
方法一:通过web界面绑定
在这里插入图片描述
方法二: 通过Shell命令行将项目研发部用户rduser002绑定普通用户权限。命令如下

# openstack role add --user rduser002 --project RD_Dept _member_

查看执行结果

# openstack role list --user rduser002 --project RD_Dept

方法三: 通过执行Keystone-manage-add-role.sh脚本将项目IT工程部用ituser001~ituser005绑定普通用户和管理员用户权限,部分执行结果如下所示。

# ./Keystone-manage-add-role.sh

在这里插入图片描述
附录脚本内容
Keystone-manage-project.sh

#!/bin/bash
if [  -f "/etc/keystone/admin-openrc.sh" ];then
        source /etc/keystone/admin-openrc.sh
else
env_path=`find / -name admin-openrc.sh`
        source $env_path
fi
    echo -e "\033[31mPlease Input new project name : eg (openstack)\033[0m "
        read New_Project_Name
if [ ! -n "$New_Project_Name" ];then
            echo -e "\033[31mProject Name Is Empty,Exit\033[0m "
            exit 1
        fi
    echo -e "\033[31mPlease Input project description : eg (openstack description)\033[0m "
        read New_Project_des
if [ ! -n "$New_Project_des" ];then
             echo -e "\033[31mProject  Description  Is Empty,Exit\033[0m "
             exit 1
fi
T_Start=`echo $New_Project_Range |awk -F- '{ print $1}'| awk '{print $0+0}'`
N_Start=`printf "%03d\n" $T_Start`
T_End=`echo $New_Project_Range |awk -F- '{ print $2}' | awk '{print $0+0}'`
N_End=`printf "%03d\n" $T_End`
        T_End1=$[$T_End+1]
               openstack project create  $New_Project_Name --domain demo --description $New_Project_des
               echo -e "\033[31mKeystone All Project List\033[0m "
               openstack project list

Keystone-manage-user.sh

#!/bin/bash
if [  -f "/etc/keystone/admin-openrc.sh" ];then
        source /etc/keystone/admin-openrc.sh
else
env_path=`find / -name admin-openrc.sh`
        source $env_path
fi
        echo -e "\033[31mPlease Input New User Name : eg (username)\033[0m "
        read New_User_Name
if [ ! -n "$New_User_Name" ];then
                         echo -e "\033[31mUser Name Is Empty,Exit\033[0m "
                         exit 1
 fi
        echo -e "\033[31mPlease Input User Password: eg (000000)\033[0m "
        read New_User_Pw
if [ ! -n "$New_User_Pw" ];then
                 echo -e "\033[31mPasswd Is Empty,Exit\033[0m "
                 exit 1
           fi
        echo -e "\033[31mPlease Input User Email Address,If don't need  press enter: eg (openstack.com)\033[0m "
        read New_User_Email
if [ ! -n "$New_User_Email" ];then
                 echo -e "\033[31mEmail Address Is Empty,Exit\033[0m "
                 exit 1
           fi
    echo -e "\033[31mPlease Input User   Beginning And End  Number: eg (001-002)\033[0m "
        read New_User_Range
if [ ! -n "$New_User_Range" ];then
                    echo -e "\033[31mNumber Is Empty,Exit\033[0m "
                    exit 1
                else
U_Start=`echo $New_User_Range |awk -F- '{ print $1}'| awk '{print $0+0}'` 
N_U_Start=`printf "%03d\n" $U_Start`
U_End=`echo $New_User_Range |awk -F- '{ print $2}' | awk '{print $0+0}'`
N_U_End=`printf "%03d\n" $U_End`
                    U_End1=$[$U_End+1]
IF_username_exists=`openstack user list | sed '1,3d'|sed '$d'|awk '{print $4}'`
                        for username_exists in $IF_username_exists;do
                            for (( username_number = $U_Start;username_number< $U_End1;username_number++ ));do
real_username_number=`printf "%03d\n" $username_number`
                                    if [ $New_User_Name$real_username_number == $username_exists ];then
                                        echo -e "\033[31mUser $New_User_Name$real_username_number is exists\033[0m "
                                        exit 1
                                    fi
done
                        done   
            fi
        echo -e "\033[31mPlease enter the User belong Roles Name, Press enter for '_member_' role by default: eg (admin)\033[0m "
        read New_User_Role
if [ ! -n "$New_User_Role" ];then
New_User_Role=_member_
           else
IF_Role_Exists=`openstack role list |sed '1,3d' |sed '$d' |awk '{print $4}'`
                   if  echo "${IF_Role_Exists[@]}" | grep -w "$New_User_Role" >> /dev/null ; then
                           echo "exists" >> /dev/null
                   else
                          echo -e "\033[31mRole $New_User_Role not exists\033[0m "
                          exit 1
                  fi
          fi

    echo -e "\033[31mPlease Input User belong Project Name: eg (projectname)\033[0m "
        read New_User_Project
if [ ! -n "$New_User_Project" ];then
                         echo -e "\033[31mProject Name Is Empty,Exit\033[0m "
                         exit 1
            else
IF_Project_Exists=`openstack project list |sed '1,3d' |sed '$d' |awk '{print $4}'`
                   if  echo "${IF_Project_Exists[@]}" | grep -w "$New_User_Project" >> /dev/null ; then
                           echo "exists" >> /dev/null
                   else
                          echo -e "\033[31mProject $New_User_Project not exists\033[0m "
                          exit 1
                  fi
             fi
                            for (( username_number = $U_Start;username_number< $U_End1;username_number++ ));do
real_username_number=`printf "%03d\n" $username_number`
                                openstack user create  $New_User_Name$real_username_number --password $New_User_Pw --domain demo --email $New_User_Name$real_username_number@$New_User_Email
                                openstack role add --user $New_User_Name$real_username_number --project  $New_User_Project $New_User_Role 
                            done
                                echo -e "\033[31mKeystone All User List\033[0m "
                                openstack user list

Keystone-manage-add-role.sh

#!/bin/bash
# 1st keystone 
if [  -f "/etc/keystone/admin-openrc.sh" ];then
        source /etc/keystone/admin-openrc.sh
else
env_path=`find / -name admin-openrc.sh`
        source $env_path
fi
        echo -e "\033[31mPlease Enter The User Name\033[0m "
        read Add_Role_Username
        echo -e "\033[31mPlease Input User  Beginning And End  Number: eg (001-002)\033[0m "
        read Add_User_Range
                if [ ! -n "$Add_User_Range" ];then
                    Add_User_Range=$Add_User_Range
                else
                    A_R_Start=`echo $Add_User_Range |awk -F- '{ print $1}'| awk '{print $0+0}'`
                    A_R_U_Start=`printf "%03d\n" $A_R_Start`
                    A_R_End=`echo $Add_User_Range |awk -F- '{ print $2}' | awk '{print $0+0}'`
                    A_R_U_End=`printf "%03d\n" $A_R_End`
                    A_R_End1=$[$A_R_End+1]
                fi
        echo -e "\033[31mPlease Enter the Project Name\033[0m "
        read Add_Role_Tenant
            IF_Tenant_Exists=`openstack project list |sed '1,3d' |sed '$d' |awk '{print $4}'`
            if  echo "${IF_Tenant_Exists[@]}" | grep -w "$Add_Role_Tenant" >> /dev/null ; then
                echo "exists" >> /dev/null
            else
                echo -e "\033[31mProject $Add_Role_Tenant not exists\033[0m "
                exit 1
            fi
        echo -e "\033[31mPlease Enter the  Role Name\033[0m "
         read Add_Role_New_Role
            IF_Role_Exists=`openstack role list |sed '1,3d' |sed '$d' |awk '{print $4}'`
            if  echo "${IF_Role_Exists[@]}" | grep -w "$Add_Role_New_Role" >> /dev/null ; then
                 echo "exists" >> /dev/null
            else    
                 echo -e "\033[31mRole $Add_Role_New_Role not exists\033[0m "
                 exit 1
            fi
        for (( username_number=$A_R_Start;username_number<$A_R_End1;username_number++ ));do
                real_username_number=`printf "%03d\n" $username_number`
                openstack role add --project $Add_Role_Tenant --user $Add_Role_Username$real_username_number $Add_Role_New_Role
                echo -e "\033[31mKeystone user $Add_Role_Username$real_username_number Project $Add_Role_Tenant role list\033[0m "
                openstack role assignment list --user $Add_Role_Username$real_username_number --project $Add_Role_Tenant 
        done

4. 基础控制服务

1.概述

Glance镜像服务实现发现、注册、获取虚拟机镜像和镜像元数据,镜像数据支持存储多种的存储系统,可以是简单文件系统、对象存储系统等。**

2.Glance服务架构

Glance镜像服务是典型的C/S架构,Glance架构包括glance-CLIent、Glance和Glance Store。Glance主要包括REST API、数据库抽象层(DAL)、域控制器(glance domain controller)和注册层(registry layer),Glance 使用集中数据库(Glance DB)在Glance各组件间直接共享数据。
所有的镜像文件操作都通过glance_store库完成,glance_store库提供了通用接口,对接后端外部不同存储,如图所示。
**
在这里插入图片描述
(1)客户端(CLient):外部用于同Glance服务的交互和操作。
(2)glance-api:Glance对外的REST接口。
(3)数据库抽闲层(DAL):Glance和数据库直接交互的编程接口。
(4)Glance域控制器:中间件实现Glance的认证、通知、策略和数据链接等主要功能。
(5)注册层:可选层,用于管理域控制和数据库DAL层之间的安全通信。
(6)Glance DB:存储镜像的元数据,根据需要可以选择不同类型的数据库,目前采用Mysql。
(7)Glance Store:Glance对接不同数据存储的抽象层。
(8)后端存储:实际接入的存储系统。可以接入简单文件系统、Swift、Ceph和S3云存储等。当前框架选择存储在本地,目录在控制节点:/var/lib/glance/images/。

Glance服务自带两个配置文件,在使用Glance镜像服务时

镜像服务运行两个后台服务进程Demon,如下。

(1)glance-api:对外接受并发布镜像、获取和存储的请求调用。
(2)glance-registry:存储、处理和获取镜像元数据,内部服务只有Glance内部使用,不暴露给用户。
(3)glance-all:是对前两个进程的通用封装,操作方式和结果一直。

3.镜像文件格式

虚拟机镜像需要指定磁盘格式和容器格式。虚拟设备供应商将不同的格式布局的信息存在一个虚拟机磁盘映像,虚拟机的磁盘镜像的格式基本有如下几种。**
(1)raw:非结构化磁盘镜像格式。
(2)qcow2:QEMU模拟器支持的可动态扩展、写时复制的磁盘格式,是kvm虚拟机默认使用的磁盘文件格式。
(3)AMI/AKI/ARI:Amazon EC2最初支持的镜像格式。
(4)UEC tarball:ubuntu enterprise cloud tarball 是一个gzip压缩后的tar文件,包含有AMI、AKI和ARI 三种类型的文件。
(5)VHD :microsoft virtual hard disk format(微软虚拟磁盘文件)的简称。
(6)VDI:VirtualBox使用VDI(virtual disk image)的镜像格式,OpenStack没有提供直接的支持,需要进行格式转换。
(7)VMDK:VMWare virtual machine disk format是虚拟机VMware创建的虚拟机格式。
(8)OVF:open virtualization format,开放虚拟化格式,OVF文件是一种开源的文件规范,可用于虚拟机文件的打包。
容器格式是可以理解成虚拟机镜像添加元数据后重新打包的格式,目前有以下几种容器格式。

(1)Bare:指定没有容器和元数据封装在镜像中,如果Glance和OpenStack的其他服务没有使用容器格式的字符串,为了安全,建议设置bare。
(2)ovf: ovf的容器模式This is the OVF container format。
(3)aki:存储在Glance中的是Amazon的内核镜像。
(4)ari:存储在Glance中的是Amazon的ramdisk镜像。
(5)ami:存储在Glance中的是Amazon的machine镜像。
(6)ova:存储在Glance中的是OVA的tar归档文件。

4.镜像状态

由于镜像文件都比较大,镜像从创建到成功上传到Glance文件系统中,是通过异步任务的方式一步步完成的,状态包括Queued(排队)、Saving(保存中)、Acive(有效)、deactivated(无效)、Killed(错误)、Deleted(被删除)和Pending_delete(等待删除),如图所示。
在这里插入图片描述
(1)Queued排队:镜像ID已经创建和注册,但是镜像数据还没有上传。

(2)Saving保存中:镜像数据在上传中。

(3)Active有效:镜像成功创建,状态有效可用。

(4)Deactivated不活的:镜像成功创建,镜像对非管理员用户不可用。

(5)Killed错误:上传镜像数据出错,目前不可读取。

(6)Deleted被删除:镜像不可用,将被自动删除。

(7)Pending_delete等待删除:镜像不可用,等待将被自动删除

5.镜像服务基本操作

查询Glance服务状态命令如下

glance-control all status

查询glance-control版本命令如下。

glance-control --version

下面的命令作用是启动相关服务,并设置为开机启动

systemctl start openstack-glance-api
systemctl start openstack-glance-registry
systemctl enable openstack-glance-api
systemctl enable openstack-glance-registry

(1)下载CirrOS镜像文件

 mkdir /tmp/images
 cd /tmp/images/
 wget http://download.cirros-cloud.net/0.3.2/cirros-0.3.2-x86_64-disk.img

下载完成后,查看文件信息,命令如下。

file cirros-0.3.2-x86_64-disk.img

该命令执行结果如下所示。

cirros-0.3.2-x86_64-disk.img: QEMU QCOW Image (v2), 41126400 bytes

(2)使用命令行创建镜像

glance image-create --name "cirros-0.3.2-x86_64" --disk-format qcow2 --container-format bare --progress < cirros-0.3.2-x86_64-disk.img

(3)通过 Dashboard 创建镜像
通过界面,选择从互联网直接下载,创建镜像。
镜像采用 0.3.4 版本,地址如下。
http://download.cirros-cloud.net/0.3.4/cirros-0.3.4-x86_64-disk.img , 镜 像 名 称 为“cirros-0.3.4-x86_64”,格式选择“QCOW2-QEMU 模拟器”
在这里插入图片描述(4)查看镜像信息
下面通过命令方式,查看镜像的基本信息。
使用命令:openstack image list
先查看镜像列表,查询结果如下所示。

openstack image list

在这里插入图片描述然后通过 glance image-show 命令查看镜像的详细信息,其中参数可以是镜像 id 或者镜
像名称,如下所示。

openstack image show e14b5e35-5e04-4da2-823d-b5f6e3283ebd

查询结果如下所示
在这里插入图片描述

(5)通过命令删除镜像 cirros-0.3.2-x86_64 操作如下,执行结果如下所示

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VFDKFhoJ-1622695095560)(C:%5CUsers%5Czhao%5CAppData%5CRoaming%5CTypora%5Ctypora-user-images%5Cimage-20210603123318096.png)]

6.计算服务

1.概述
计算服务(Nova)表示云平台的工作负载的核心。如果有些云服务的工作中不包括计
算,那么 它们充其量只 代表静态存储 ,所有动态活 动都会涉及一 些计算元素。
OpenStackCompute 这个名称指的是一个特定的项目,该项目也被称为 Nova,OpenStack 的
其他组件依托 Nova,与 Nova 协同工作,组成了整个 OpenStack 云平台。
Nova,是 OpenStack 计算的弹性控制器。Nova 可以说是整个云平台最重要的组件,其
功能包括运行虚拟机实例,管理网络以及通过用户和项目来控制对云的访问。OpenStack
最基础的开源项目名字称为 Nova,它提供的软件可以控制基础设施即服务(IaaS)云计算
平台,与 AmazonEC2 和 Rackspace 云服务器有一定程度的相似。OpenStackCompute 没有
包含任何的虚拟化软件,相反,它定义和运行在主机操作系统上的虚拟化机制交互的驱动
程序,并通过基于 Web 的程序应用接口(API)来提供功能的使用。
2.架构介绍
Nova 服务包 含了 7 个子组 件,分别为 :NovaAPI、 NovaCert、 NovaCompute、
NovaConductor 和 NovaScheduler、NovaConsoleauth 以及 NovaVncproxy,如图所示
在这里插入图片描述(1)NovaAPI
NovaAPI 这是一个 HTTP 服务,用于接收和处理客户端发送的 HTTP 请求;API 是整
个 Nova 组件的入口。它接受用户请求,将指令发送至消息队列(Queue),并由 Nova 服
务的子服务执行相应的操作。
(2)NovaCert
用于管理证书认证,提供兼容性保障,保证所有的应用程序都能在云上运行。
(3)NovaCompute
NovaCompute 是 Nova 核心子组件,通过与 NovaClient 进行交互,实现了虚拟机管理
的功能。负责在计算节点上对虚拟机实例进行一系列操作,包括迁移、安全组策略和快照
管理等功能。
(4)NovaConductor
NovaConductor 是 OpenStack 中的一个 RPC 服务,主要提供对数据库的查询和权限分
配操作。
(5)NovaScheduler
完成 Nova 的核心调度,包括虚拟机硬件资源调度、节点调度等。同时,NovaScheduler
决定了虚拟机创建的具体位置。
(6)NovaConsoleauth
实现对 Nova 控制台(VNC)的认证操作。
(7)NovaVncproxy
Nova 的控制台组件,实现客户端与虚拟机实例的通信,在虚拟桌面领域运用较广泛。
可以通过一个 Nova 实例的启动过程来了解一下内部的数据和请求的运行情况。首先
用户会通过 Web 界面或者 CLI 界面发送一个启动实例的请求,首先需要通过认证服务的Keystone 的请求,进行身份的验证,通过之后将拿到的 token 向 nova-api 发送请求,在通
过 Glance 镜像服务检查镜像 image 和类型 flavor 时候存在。通过上述验证后将启动实例的
请求发送给计算服务的 schedule 调度节点,调度节点随机将此请求发送给一个 compute 节点,
让其启动实例,计算节点接受请求之后会到 Glance 存在的计算节点开始下载镜像并启动实
例,计算节点启动虚拟机的时候会通过 Neutron 的 DHCP 获取一个对应的 IP 等网络资源,再
次在 OVS 网桥获取相应的端口,绑定虚拟机的虚拟网卡接口。至此实例的启动已经完成。
Nova 集合了多个服务进程,每个进程扮演着不同的角色。用户通过 RESTAPI 接口访
问,Nova 的内部服务通过 RPC 消息服务通信。API 服务产生数据读写的 REST 请求,然后
产生 REST 应答。内部服务通信通过 oslo.messaging 库的 RPC 消息实现消息的通信。大部
分共用一个中心数据库。也可以把中心数据放到对象层,实现不同 OpenStack 发布版本的
兼容性,如图所示。
在这里插入图片描述3.调度机制(scheduler)
Scheduler 模块在 OpenStack 中的作用就是决策虚拟机创建在哪个主机上,目前(截至
Essex 版本),调度仅支持计算节点。
(1)主机过滤
如图 4-15 所示,FilterScheduler 首先得到未经过滤的主机列表,然后根据过滤属性,
选择主机创建指定数目的虚拟机。
目前,OpenStack 默认支持几种过滤策略,开发者也可以根据需要实现自己的过滤策略。
在 nova.scheduler.filters 包中的过滤器有以下几种。
① AllHostsFilter:不做任何过滤,直接返回所有可用的主机列表。
② AvailabilityZoneFilter:返回创建虚拟机参数指定的集群内的主机。
③ ComputeFilter:根据创建虚拟机规格属性选择主机。
④ CoreFilter:根据 CPU 数过滤主机。
⑤ IsolatedHostsFilter:根据“image_isolated”和“host_isolated”标志选择主机。
⑥ JsonFilter:根据简单的 JSON 字符串指定的规则选择主机。
⑦ RamFilter:根据指定的 RAM 值选择资源足够的主机。
⑧ SimpleCIDRAffinityFilter:选择在同一 IP 段内的主机。
⑨ DifferentHostFilter:选择与一组虚拟机不同位置的主机。
⑩ SameHostFilter:选择与一组虚拟机相同位置的主机。

在这里插入图片描述(2)权值计算
经过主机过滤后,需要对主机进行权值的计算。根据策略选择相应的某一台主机(对
于每一个要创建的虚拟机而言)。尝试在一台不适合的主机上创建虚拟机的代价比在一台
合适主机上创建的代价要高,例如,在一台高性能主机上创建一台功能简单的普通虚拟机
的代价是高的。OpenStack 对权值的计算需要一个或多个(Weight 值代价函数)的组合,
然后对每一个经过过滤的主机调用代价函数进行计算,将得到的值与 Weight 值相乘,得到
最终的权值。OpenStack 将在权值最小的主机上创建一台虚拟机,如图所示。
在这里插入图片描述(3)配置文件讲解
Nova 的安装与 Glance 组件的部署流程类似,Nova 的子服务更多,把 nova-compute 单
独部署在计算节点,Nova 的其他服务部署在控制节点。
为了实现计算节点的 Nova-compute 服务与控制节点上 Nova 其他的子服务通信,需要
在配置文件中配置 Rabbit 消息队列服务。

[root@controller ~]# vi /etc/nova/nova.conf

配置如下所示内容。

[DEFAULT]
rpc_backend = rabbit

Nova 服务的数据存储在 MySQL 数据库中,需要在数据库中创建 Nova 数据库并给予
一定的权限,在 Nova 的配置文件中配置数据库连接,指向 MySQL 中的 Nova 数据库。
配置如下所示内容。

[api_database]
connection = mysql+pymysql://nova:000000@controller/nova_api
#mysql -uroot -p

执行如下所示的命令,赋予数据库权限。

mysql> CREATE DATABASE nova; //已有数据库
mysql>GRANT REPLICATION SLAVE ON *.* to 'nova'@'%' identified by '000000';
# su -s /bin/sh -c "nova-manage db sync" nova

跟 Glance 组件一样,需要在 Keystone 创建 nova 用户,执行的命令和结果如下所示。
在这里插入图片描述赋予 nova 用户 admin 权限,并把 nova 用户规划到 service 项目下,同时在 Keystone 中
注册 Nova 服务,服务类型为 compute。执行的命令和结果如下所示。

在这里插入图片描述在 Keystone 中创建 Nova 计算服务的端点。执行的命令和结果如下所示。

#openstack service create --name nova --description "OpenStack Compute"
compute
openstack endpoint create --region RegionOne compute public
http://controller:8774/v2.1/%\(tenant_id\)s
openstack endpoint create --region RegionOne compute internal
http://controller:8774/v2.1/%\(tenant_id\)s
openstack endpoint create --region RegionOne compute admin
http://controller:8774/v2.1/%\(tenant_id\)s 

为了实现 Nova 服务调用其他服务,需要在 Nova 的配置文件中配置其通过 Keystone的认证。

#openstack-config --set /etc/nova/nova.conf DEFAULT enabled_apis
osapi_compute,metadata
openstack-config --set /etc/nova/nova.conf DEFAULT rpc_backend rabbit
openstack-config --set /etc/nova/nova.conf DEFAULT auth_strategy
keystone
openstack-config --set /etc/nova/nova.conf DEFAULT my_ip 20.0.0.10
openstack-config --set /etc/nova/nova.conf DEFAULT use_neutron True
openstack-config --set /etc/nova/nova.conf DEFAULT firewall_driver
nova.virt.firewall.NoopFirewallDriver
openstack-config --set /etc/nova/nova.conf DEFAULT metadata_listen 0.0.0.0
openstack-config --set /etc/nova/nova.conf DEFAULT metadata_listen_port
8775
openstack-config --set /etc/nova/nova.conf oslo_messaging_rabbit
rabbit_host controller
openstack-config --set /etc/nova/nova.conf oslo_messaging_rabbit
rabbit_userid openstack
openstack-config --set /etc/nova/nova.conf oslo_messaging_rabbit
rabbit_password 000000
openstack-config --set /etc/nova/nova.conf keystone_authtoken auth_uri
http://controller:5000
openstack-config --set /etc/nova/nova.conf keystone_authtoken auth_url
http://controller:35357
openstack-config --set /etc/nova/nova.conf keystone_authtoken
memcached_servers controller:11211
openstack-config --set /etc/nova/nova.conf keystone_authtoken auth_type
password
openstack-config --set /etc/nova/nova.conf keystone_authtoken
project_domain_name default
openstack-config --set /etc/nova/nova.conf keystone_authtoken
user_domain_name default
openstack-config --set /etc/nova/nova.conf keystone_authtoken
project_name service
openstack-config --set /etc/nova/nova.conf keystone_authtoken username
nova
openstack-config --set /etc/nova/nova.conf keystone_authtoken password
000000
openstack-config --set /etc/nova/nova.conf vnc vncserver_listen 20.0.0.10
openstack-config --set /etc/nova/nova.conf vnc
vncserver_proxyclient_address 20.0.0.10
openstack-config --set /etc/nova/nova.conf glance api_servers
http://controller:9292
openstack-config --set /etc/nova/nova.conf oslo_concurrency lock_path/var/lib/nova/tmp

为了实现对平台虚拟机的访问,OpenStack 提供了 VNC 的接入方式,需要在 Nova 的
配置文件中配置 vnc 接入。

[DEFAULT]
rpc_backend = qpid
qpid_hostname = controller
my_ip = 172.24.2.10
vncserver_listen = 172.24.2.10
vncserver_proxyclient_address = 172.24.2.10

(4)Nova 的主要操作命令
Nova 作为 OpenStack 的核心组件,拥有强大的功能、权限,可以对整个平台的资源(镜
像、网络和存储等)进行管理,下面来看一下 Nova 的主要操作命令。

① Nova对镜像管理

● nova image-create

功能: 通过快照创建像。

格式:

# nova image-create [--show] [--poll] <server><name>

固定参数说明。

:做快照的实例的名字或者ID。

:快照名字。

可选参数说明。

[–show] :打印出镜像信息。

[–poll]:显示进度。

● nova image-show

功能:获取镜像的详细信息。

格式:nova image-show

参数说明。

:所要查询的镜像的名字或者ID。

# nova image-list

执行结果如下所示。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-11dCIjas-1622695095589)(C:%5CUsers%5Czhao%5CAppData%5CRoaming%5CTypora%5Ctypora-user-images%5Cimage-20210530155351280.png)]

② Nova管理安全组规则。

安全组,翻译成英文是security group。安全组是一些规则的集合,用来对虚拟机的访问流量加以限制,这反映到底层,就是使用iptables,给虚拟机所在的宿主机添加iptables规则。可以定义n个安全组,每个安全组可以有n个规则,可以给每个实例绑定n个安全组,Nova中总是有一个default安全组,这个是不能被删除的。创建实例的时候,如果不指定安全组,会默认使用这个default安全组。现在Nova中安全组应该会移到Neutron中,并且会增加对虚拟机外出流量的控制。现在Nova中的安全组只是对进入虚拟机的流量加以控制,对虚拟机外出流量没有加以限制。

常用的安全组命令如下。

# nova secgroup-create

分享:

低价透明

统一报价,无隐形消费

金牌服务

一对一专属顾问7*24小时金牌服务

信息保密

个人信息安全有保障

售后无忧

服务出问题客服经理全程跟进