1 OpenStack高可用介绍
1.1 无状态和有状态服务
无状态服务指的是该服务接收的请求前后之间没有相关关系,接收并处理完该请求后不保存任何状态,在OpenStack的服务中常见的无状态服务有:nova-api、glance-api、keystone-api等服务,大部分都是一些用于接收请求的服务。
有状态服务跟无状态服务相反,它对后续请求的处理依赖于上一次请求的结果,保存了上一次请求处理的结果。在OpenStack的服务中常见的有状态服务有:数据库服务、高级消息队列服务等服务。
对于无状态服务的高可用,只需要在多个节点中都部署该服务,然后使用类似HaProxy的负载均衡软件来转发请求即可达到高可用。对于有状态的服务,可采用A/A(主/主)或A/P(主/从)方式来搭建高可用。
1.2 A/A方式
A/A方式也叫做主/主模式,一般是原生实现的方式,也就是说同时有多个相同的服务在运行,当某个节点上的服务不能提供服务时,其它节点的该服务可以替代它进行服务,从而达到高可用。
上面所说的无状态服务基本都是采用A/A这种方式,一般使用HaProxy软件作为负载均衡。而有状态的服务采用该方式就是在各节点维护完全相同的该服务,也就是说一个请求的处理也需要通知到其它节点的该服务,比如数据库服务,对数据库的更新需要同步到其它节点的数据库,保证各数据库存储的数据是一致的。
优点:多主、零切换、方便的实现负载均衡
缺点:每个节点都运行着相同实例,带来更多的负载。
1.3 A/P方式
A/P方式也叫作主/从模式,需要通过第三方软件比如pacemaker来对备份服务进行激活等管理操作,也就是说有一个服务作为主服务在运行,另一个服务作为备份,并未运行,当主服务不能提供服务时,备份服务就会被激活并替代主服务继续提供服务。比如数据库服务,某个节点的数据库服务进程进行服务,在另外一个节点维护一套灾备数据库,当主数据库服务不能提供服务时,灾备数据库就会被激活并替代主服务进行服务。
优点:两个节点也可以组成高可用
缺点:
(1)主备切换时间较长;
(2)只有主服务提供服务,在使用两个节点的情况下不能做负载均衡;
(3)DRDB脑裂会导致数据丢失的风险,A/P方式的MariaDB高可用可靠性没有A/A方式的Galera MariaDB高。
1.4 A/A和A/P的选择
部署OpenStack组件的高可用一般遵循以下原则:能采用A/A的方式就采用A/A的方式,不能的话就采用A/P的方式。
2 各类节点高可用配置
2.1 各类节点无状态服务高可用配置
无状态服务大多是属于api服务类型的,也就是进入服务的入口,比如nova-api、keystone-api等基本上都是无状态的服务,同时也包含一些服务只服务于单个节点上的,比如nova-compute、nova-conductor、nova-scheduler等,这些都只需要在多个节点上都部署相同的服务再加上使用HaProxy软件作为负载均衡即可实现高可用。以下以keystone-api为例列出在HaProxy软件中的配置信息:
listen keystone_admin_cluster bind <Virtual IP>:35357 balance source option tcpka option httpchk option tcplog server controller1 10.0.0.12:35357 check inter 2000 rise 2 fall 5 server controller2 10.0.0.13:35357 check inter 2000 rise 2 fall 5 server controller3 10.0.0.14:35357 check inter 2000 rise 2 fall 5 listen keystone_public_internal_cluster bind <Virtual IP>:5000 balance source option tcpka option httpchk option tcplog server controller1 10.0.0.12:5000 check inter 2000 rise 2 fall 5 server controller2 10.0.0.13:5000 check inter 2000 rise 2 fall 5 server controller3 10.0.0.14:5000 check inter 2000 rise 2 fall 5
这里的Virtual IP可以是由Pacemaker提供的虚拟IP。3个控制节点可以使用Pacemaker+corosync的方式组成一个集群,虚拟IP可以存在于集群中的其中一个节点上,可以设置成只有HaProxy进程是存活状态下的节点,虚拟IP才有可能会在该节点上,然后该节点的HaProxy进程就会作为接收点,其它节点的HaProxy作为备用当,该节点网络不可用时或HaProxy进程不是存活状态时,虚拟IP可以自动转移到集群中的其它正常节点上。可以看到其实HaProxy软件最大的作用就是起到了一个请求转发的作用,请求先发到了HaProxy进程中,HaProxy再根据哪个节点上的相关服务是可用的,再转发给该节点进行处理。
2.2 控制节点高可用配置
部署在控制节点的服务主要有数据库服务、高级消息队列服务、Memcached服务、身份认证服务、镜像服务、各类api服务等。各类api服务的高可用配置可以参照2.1。
2.2.1 数据库服务高可用配置
OpenStack的数据库选择可以有好几种,比如MySQL、MariaDB(MySQL的一个分支)和PostgreSQL等,但在OpenStack服务中选择使用最多的是MariaDB。MariaDB高可用既可以使用A/A方式也可以使用A/P方式,这里我们使用业界最普遍使用的A/A方式,即Galera MariaDB。
以下是Galera MariaDB的配置过程,每个节点上都需配置(可以先使用find命令搜索下你的系统里是否装有libgalera_smm.so,配置文件的选项中有需要写明路径指向它,没有的话可以尝试安装Galera):
编辑/etc/hosts文件,加上你各节点的IP和对应的节点名(10.170是虚拟IP),比如:
192.168.10.170 controller 192.168.10.171 controller1 192.168.10.172 controller2 192.168.10.173 controller3
编辑/etc/security/limits.conf文件,加上以下内容:
* soft nofile 65536 * hard nofile 65536
编辑/etc/sysctl.conf文件并加上以下内容:
fs.file-max=655350 net.ipv4.ip_local_port_range = 1025 65000 net.ipv4.tcp_tw_recycle = 1 net.ipv4.ip_nonlocal_bind = 1
然后执行:
sysctl -p
编辑/etc/my.cnf.d/mariadb-server.cnf文件,加上或更新以下配置:
[mysqld] server_id=128 datadir=/app/galera user=mysql skip-external-locking skip-name-resolve character-set-server=utf8 max_connections = 4096 [galera] wsrep_causal_reads=ON #节点应用完事务才返回查询请求 wsrep_provider_options="gcache.size=4G" #同步复制缓冲池 wsrep_certify_nonPK=ON #为没有显式申明主键的表生成一个用于certificationtest的主键,默认为ON query_cache_size=0 #关闭查询缓存 wsrep_on=ON #开启全同步复制模式 wsrep_provider=/usr/lib64/galera/libgalera_smm.so #galera library wsrep_cluster_name=MariaDB-Galera-Cluster wsrep_cluster_address="gcomm://192.168.10.171,192.168.10.172,192.168.10.173" wsrep_node_name=controller1 wsrep_node_address=192.168.10.171 binlog_format=row default_storage_engine=InnoDB innodb_autoinc_lock_mode=2 #主键自增模式修改为交叉模式 wsrep_slave_threads=8 #开启并行复制线程,根据CPU核数设置 innodb_flush_log_at_trx_commit=0 #事务提交每隔1秒刷盘 innodb_buffer_pool_size=2G wsrep_sst_method=rsync bind-address=192.168.x.x #这里ip改为你当前节点的ip
在MariaDB的各个节点上分别执行:
mysql_install_db --defaults-file=/etc/my.cnf.d/mariadb-server.cnf --user=mysql
在其中一个节点上执行(只要在一个节点上执行即可):
mysqld_safe --defaults-file=/etc/my.cnf.d/mariadb-server.cnf --user=mysql --wsrep-new-cluster &
执行完后在其它节点上分别执行:
mysqld_safe --defaults-file=/etc/my.cnf.d/mariadb-server.cnf --user=mysql &
登录三个节点查看是否已经配置好:
mysql -uroot -p MariaDB [(none)]> SHOW STATUS LIKE \'wsrep_cluster_size\'; +--------------------+-------+ | Variable_name | Value | +--------------------+-------+ | wsrep_cluster_size | 3 | +--------------------+-------+
验证是否有打出你的数据库集群数量,我这里是配置了3个MariaDB组成的一个Galera MariaDB集群,所以打出的数量是3。
如果是使用HaProxy作为负载均衡软件来访问Galera Mariadb集群,你可以使用以下配置来检查数据库集群的健康状态(以下除了数据库执行语句可以只在一个节点上执行,其它比如配置文件、服务启动都需要在各个节点上执行):
创建/etc/sysconfig/clustercheck文件并配置以下内容:
MYSQL_USERNAME="clustercheck_user" MYSQL_PASSWORD="my_clustercheck_password" MYSQL_HOST="localhost" MYSQL_PORT="3306"
登录数据库集群中的其中一个节点的数据库客户端并执行以下数据库语句:
GRANT PROCESS ON *.* TO \'clustercheck_user\'@\'localhost\' IDENTIFIED BY \'my_clustercheck_password\'; FLUSH PRIVILEGES;
创建/etc/xinetd.d/galera-monitor文件用于haproxy监视器监听配置:
service galera-monitor { port = 9200 disable = no socket_type = stream protocol = tcp wait = no user = root group = root groups = yes server = /usr/bin/clustercheck type = UNLISTED per_source = UNLIMITED log_on_success = log_on_failure = HOST flags = REUSE }
注意从上面配置文件中我们看到了:
server = /usr/bin/clustercheck
说明我们的系统中需要有这个clustercheck程序,自己可以检查下/usr/bin目录下是否有该程序,如果没有则需要下载下来并放到该目录下,下载链接:https://raw.githubusercontent.com/olafz/percona-clustercheck/master/clustercheck
且赋予执行权限:
wget https://raw.githubusercontent.com/olafz/percona-clustercheck/master/clustercheck /usr/bin/clustercheck chmod +x /usr/bin/clustercheck
它是通过执行该程序来检测当前节点的mysql是否是可用的,如果可用一般输出如下:
[root@abc2 ~]# /usr/bin/clustercheck HTTP/1.1 200 OK Content-Type: text/plain Connection: close Content-Length: 40 Percona XtraDB Cluster Node is synced.
不可用时输出如下:
[root@abc0 ~]# /usr/bin/clustercheck HTTP/1.1 503 Service Unavailable Content-Type: text/plain Connection: close Content-Length: 44 Percona XtraDB Cluster Node is not synced.
执行以下命令(确保安装了xinetd服务)
systemctl daemon-reload
systemctl enable xinetd
systemctl start xinetd
最好检测下9200端口是不是真的被xinetd程序使用着:
[root@abc2 ~]# netstat -tunlp |grep 9200 tcp6 0 0 :::9200 :::* LISTEN 1078/xinetd
在HaProxy配置文件中可以如下配置数据库请求转发服务:
listen galera_cluster bind <Virtual IP>:3306
mode tcp
balance source option mysql-check server controller1 10.0.0.12:3306 check port 9200 inter 2000 rise 2 fall 5 server controller2 10.0.0.13:3306 backup check port 9200 inter 2000 rise 2 fall 5 server controller3 10.0.0.14:3306 backup check port 9200 inter 2000 rise 2 fall 5
在keystone、nova、neutron等配置文件中凡是配置连接到数据库的配置都应该类似如下配置,以nova.conf配置文件中的为例:
[database] connection = mysql+pymysql://nova:123456@controller/nova
这里我们可以看到123456是nova用户的密码,使用的controller是虚拟IP对应的虚拟主机名,如此它就会在连接请求时先连接到HaProxy进程,再由HaProxy进程选择某个节点的数据库服务进行连接发送请求。
2.2.2 高级消息队列服务高可用配置
高级消息队列承担着为相关服务进程传递信息的作用,比如nova-api、nova-conductor、nova-scheduler等服务之间都需要通过高级消息队列来进行通信,OpenStack使用的高级消息队列都是基于AMQP的,常见的应用服务有Rabbitmq、ZeroMQ等,我们选择OpenStack支持最好的RabbitMQ来作为高级消息队列服务。
RabbitMQ原生就有高可用的实现,我们这里使用RabbitMQ集群+镜像队列模式来实现高可用,镜像队列的作用就是消息实体会主动在镜像节点之间实现同步,此模式的一个缺点是RabbitMQ集群内部的同步通讯会占用大量的网络带宽。配置方法如下:
先在各个节点上停止rabbitmq服务:
systemctl stop rabbitmq-server
rabbitmqctl stop
我这里以3个节点controller1、controller2和controller3为例,选定controller1节点,将该节点的/var/lib/rabbitmq/.erlang.cookie文件拷贝给其它节点,保证不同节点间有同一认证的Erlang Cookie:
scp /var/lib/rabbitmq/.erlang.cookie root@controller2:/var/lib/rabbitmq/ scp /var/lib/rabbitmq/.erlang.cookie root@controller3:/var/lib/rabbitmq/
接着在各节点上执行:
chown rabbitmq:rabbitmq /var/lib/rabbitmq/.erlang.cookie chmod 400 /var/lib/rabbitmq/.erlang.cookie rabbitmq-server -detached
在controller1节点上执行
rabbitmqctl start_app
在controller2和controller3节点上分别执行:
rabbitmqctl stop_app
rabbitmqctl join_cluster controller1@rabbitmqCluster
rabbitmqctl start_app
在各节点上分别执行:
systemctl restart rabbitmq-server
在各节点上分别执行rabbitmqctl cluster_status进行验证,如果类似如下即为正常:
Cluster status of node rabbit@controller1 ... [{nodes,[{disc,[rabbit@controller1,rabbit@controller2,rabbit@controller3]}]}, {running_nodes,[rabbit@controller3,rabbit@controller2,rabbit@controller1]}, {cluster_name,<<"rabbit@controller1">>}, {partitions,[]}, {alarms,[{rabbit@controller3,[]}, {rabbit@controller2,[]}, {rabbit@controller1,[]}]}]
partitions里如果有节点一般非正常,可以通过重启rabbitmq-server服务来恢复。
在controller1节点上执行以下语句使其变为镜像模式:
rabbitmqctl set_policy ha-all \'^(?!amq\.).*\' \'{"ha-mode": "all"}\'
在为OpenStack的服务配置使用rabbitmq消息队列服务时,可以如下配置:
transport_url = rabbit://openstack:123456@controller1,openstack:123456@controller2,openstack:123456@controller3
可以看到这里的配置方式是将所有节点的rabbitmq服务以拼接方式拼在一起,当controller1节点上的消息队列服务不可用时可以将请求转发给controller2,再不行可以再转发给controller3节点。
同时应该配置如下参数:
rabbit_retry_interval=1 rabbit_retry_backoff=2 rabbit_max_retries=0 rabbit_durable_queues=true rabbit_ha_queues=true
2.2.3 Memcached服务高可用配置
Memcached服务可以用来为OpenStack的多个服务缓存一些临时的数据,可以使得不用每一次都去真实访问取得数据,使得访问不至于过于频繁,减少了资源使用且加快了效率,比如可以用于缓存keystone的token值。
OpenStack服务在配置文件中配置使用Memcached服务时,可以如下配置:
memcached_servers = controller1:11211,controller2:11211,controller3:11211
2.3 网络节点高可用配置
部署在网络节点上的服务主要有DHCP Agent服务、L3 Agent服务和Metadata Agent服务,Metadata Agent服务的高可用只需各网络节点都部署该服务即可,以下主要是讲DHCP Agent和L3 Agent服务的高可用配置。
2.3.1 DHCP Agent服务高可用配置
由于DHCP协议自身就支持多个DHCP服务器,因此只需要在各个网络节点上部署DHCP Agent服务,并且在配置文件中配置相关选项,即可实现租户网络的DHCP服务是高可用的。配置方式如下:
在各网络节点上编辑/etc/neutron/neutron.conf文件,在[default]下加上以下内容:
agent_down_time = 30 report_interval=15 dhcp_agents_per_network = 3
然后重启网络服务:systemctl restart neutron-server
可以使用neutron客户端的命令验证下是否生效:
使用openstack network list查看下你的网络
然后使用neutron dhcp-agent-list-hosting-net network-id来查看该网络的DHCP服务是否是HA的。
+--------------------------------------+-------------+----------------+-------+ | id | host | admin_state_up | alive | +--------------------------------------+-------------+----------------+-------+ | 4e1ac514-f334-4f53-9765-57df5775fadd | controller3 | True | :-) | | bb89eb4d-e9a8-4fba-8c3f-cd24892c664d | controller2 | True | :-) | | db05682b-dbe1-40e6-8fe1-6205457d6c15 | controller1 | True | :-) | +--------------------------------------+-------------+----------------+-------+
由上面的表可以看出我的这个租户网络是有3个DHCP服务在为其服务的,各节点上各一个DHCP为该租户网络服务,所以即使某节点关机了,还有其它DHCP服务为该网络服务,因此是高可用的。
2.3.2 L3 Agent服务高可用配置
Neutron本身的调度器neutron-scheduler服务是支持在多个网络节点上部署L3 Agent服务的,但L3 Agent是用来管理虚拟路由器的,所以需要虚拟路由器服务自身需要实现高可用,当前虚拟路由器的高可用实现方式有几种,最主流的方式有两种,一种是VRRP(虚拟路由冗余协议)方案,另外一种是DVR(分布式虚拟路由)方案。
这里选择使用VRRP的方案来配置高可用,配置方式如下:
编辑/etc/neutron/plugins/ml2/linuxbridge_agent.ini文件并更新以下内容:
[vxlan] #l2_population = true
编辑/etc/neutron/neutron.conf文件并更新下列内容:
[default]
l3_ha = True
编辑/etc/neutron/l3_agent.ini文件并更新以下内容:
[default]
external_network_bridge =
这个external_network_bridge是故意设置成没有值的。
重启网络服务:
systemctl restart neutron-server.service neutron-linuxbridge-agent.service neutron-dhcp-agent.service neutron-metadata-agent.service neutron-l3-agent.service
可以使用命令neutron l3-agent-list-hosting-router router-id来查看router的master l3-agent是在哪个节点上。
+--------------------------------------+-------------+----------------+-------+----------+ | id | host | admin_state_up | alive | ha_state | +--------------------------------------+-------------+----------------+-------+----------+ | 1f0b2639-cff3-42f6-bb19-b57021646b60 | controller1 | True | :-) | standby | | 72e65e4b-e568-4279-8e22-aa7e80a62f5c | controller3 | True | :-) | standby | | af871274-c085-4ba6-8d8f-6a9ee909efbb | controller2 | True | :-) | active | +--------------------------------------+-------------+----------------+-------+----------+
执行后可以看到上表的输出结果,从输出结果中可以看到controller2的L3 Agent是master,controler1和controller3都是备用的。
2.4 计算节点高可用配置
部署在计算节点上的服务有L2 Agent服务、nova-compute服务等服务,这些服务都是服务于自身节点的,所以无需加任何配置,只需保证各计算节点上都有该服务即可。
2.4.1 虚拟机HA高可用配置
计算节点是运行虚拟机的节点,所以我们关心的是当该虚拟机所在的计算节点宕机后虚拟机是否还能继续正常运行,这就是虚拟机的高可用问题,按照我们想要的情况是在该计算节点宕机后该节点上的虚拟机应该能够自动迁移到其它计算节点上继续正常运行,但这也需要一些前提条件,比如虚拟机的存储应该都是存放在共享存储的,而非本地存储。目前OpenStack对于虚拟机的高可用性还在开发中,业界一些企业已经有自己的实现方案,这里只列出几个方案,其实本质就是还缺少个监控某计算节点是否真的不能再为虚拟机提供服务了,使用nova evacuate的模块功能可以将该虚拟机从共享存储上将其恢复,并运行在其它正常计算节点上。
业界的几个解决方案:
(1)利用控制节点去检查计算节点的管理网、存储网和租户网,定制特定的策略当哪些网络不可用时就判定该计算节点不可用,接着启动nova evacuate模块功能将虚拟机运行在其它可用的计算节点上。
(2)管理、存储、租户网上分别部署Gossip Pool,计算节点之间同时通过三个Gossip Pool互相检查连通性,每个Gossip Pool里发现的问题节点上报到控制节点上去。
2.5 存储节点高可用配置
存储节点的后端存储方式可以采用Ceph集群的存储方式,本身是分布式性质的存储,保证了存储数据的高可用性。部署在存储节点的OpenStack服务有cinder-api、cinder-scheduler、cinder-volume。这里只需关注cinder-volume的高可用即可。
cinder-volume由于在目前的代码中存在资源竞争问题,官方推荐的是使用A/P的方式来实现高可用,也就是说在某时刻,只有主节点上的cinder-volume在提供服务,需要借助于第三方软件比如Pacemaker来进行管理。以下是一些配置过程:
在pacemaker集群的其中一个节点上执行以下命令:
pcs resource create openstack-cinder-api systemd:openstack-cinder-api --clone interleave=true pcs resource create openstack-cinder-scheduler systemd:openstack-cinder-scheduler --clone interleave=true pcs resource create openstack-cinder-volume systemd:openstack-cinder-volume pcs constraint order start openstack-cinder-api-clone then openstack-cinder-scheduler-clone pcs constraint colocation add openstack-cinder-scheduler-clone with openstack-cinder-api-clone pcs constraint order start openstack-cinder-scheduler-clone then openstack-cinder-volume pcs constraint colocation add openstack-cinder-volume with openstack-cinder-scheduler-clone pcs constraint order start openstack-keystone-clone then openstack-cinder-api-clone
4 高可用部署方案设计
4.1 方案一
其中:
(1)首先该方案至少需要使用3个控制节点,使用Pacemaker+corosync组成一个集群,使用Pacemaker提供一个虚拟IP,每个控制节点都包含了有控制节点、计算节点、网络节点和存储节点的最基本的服务。
(2)使用HaProxy软件来做负载均衡,HaProxy的前端接收请求绑定该虚拟IP,HaProxy后端选择某个可用节点将请求转发到该节点上去处理。
(3)这三个控制节点也充当着计算节点的功能,但是可以通过创建一个配置文件,配置文件中记录该节点最多可以运行多少台虚拟机,然后在nova-scheduler调度算法上加上我们的限制逻辑,如果该控制节点的虚拟机数量超过配置文件配置的数量,则过滤掉该节点。
(4)计算节点作为可拓展的形式,可以添加新的节点作为计算节点,且计算节点也充当着存储节点的功能,让整个服务可以运行更多的虚拟机。
(5)该方案适用于规模较小的私有云,优点是可以以较少的硬件成本搭建高可用的OpenStack环境,缺点是控制节点上堆叠了过多的服务,每个控制节点的负载都偏高,性能上可能会受影响。
4.2 方案二
其中:
(1)从上图可以看到方案二其实是在方案一的基础上将各种服务分解开来,比如将网络节点和计算节点的功能都独立出来,然后3个控制节点组成一个集群,3个网络节点组成一个集群,多个Ceph节点组成Ceph集群,提供后端存储,多个计算节点用来为虚拟机提供运行资源。
(2)该方案适用于规模较大的公有云和私有云,所有服务按照分类都分散到不同的集群,节点的负载都比较少,性能能满足大量虚拟机的创建和使用。缺点是需要的硬件成本比较高。