0%

对基础设施的监控主要包括三个方面:状态,性能和可用性。通俗的讲就是:是否在干活,干了多少活,还能干多少。与Cacti、Nagios、Zabbix等工具相比,Ganglia更关注整个集群的性能和可用性。可以用于集群的性能监控、分析和优化。

Read more »

DRBD在服务器之间对块设备(如硬盘,分区,逻辑卷等)进行复制。一个虚拟的DRBD设备同时映射到本地和远端的块设备。从用户的角度来说,DRBD设备与其他块设备没有任何不同,可以在其上创建文件系统,进行文件操作。

Read more »

目标:高可用

“高可用性”(High Availability)通常来描述一个系统经过专门的设计,从而减少停工时间,而保持其服务的高度可用性。

通过高可用性设计,可以提高系统的平均无故障时间(MTTF),
对于重要的系统或系统中重要的节点,必须有高可用性的设计来保证系统的平均无故障时间达到预期的要求。

前面的NginX负载均衡方案中就使用了keepalived实现NginX节点的高可用,但那只是高可用性设计中的一种工作方式。
通常来说,高可用设计中多个冗余设备可以采用以下三种工作方式:

  • 主从方式 (非对称方式)

    主机工作,备机处于监控准备状况;当主机宕机时,备机接管主机的一切工作,待主机恢复正常后,按使用者的设定以自动或手动方式将服务切换到主机上运行,数据的一致性通过共享存储系统解决。

  • 双机双工方式(互备互援)

    两台主机同时运行各自的服务工作且相互监测情况,当任一台主机宕机时,另一台主机立即接管它的一切工作,保证工作实时,应用服务系统的关键数据存放在共享存储系统中。

  • 集群工作方式(多服务器互备方式)

    多台主机一起工作,各自运行一个或几个服务,各为服务定义一个或多个备用主机,当某个主机故障时,运行在其上的服务就可以被其它主机接管。

显然,主从方式最简单但存在资源浪费的情况;双工方式可以充分利用资源,但配置较复杂,两个节点之间要进行心跳监测;集群工作方式与双工方式并没有本质的区别,但复杂度急剧增加,除了健康状态要多播外,还需要考虑脑裂、仲裁、法定人数等问题。

本文只讨论双机互备的工作方式。

keepalived简介

keepalivedLVS的扩展项目,最初是为了解决LVS负载调度器的单点故障问题,但由于其适用性较强,配置简洁,也被用在许多其他场合,比如NginX负载均衡的高可用设计。

keepalived的设计如下图:

  • WatchDog:监控checkers和vrrp 进程
  • Checkers:服务器健康状态检查(healthchecking)。可以编写自定义的健康检查脚本。
  • VRRP STACK:当健康检查失败(服务不可用)时,在节点见进行切换。使用VRRP(Virtual Router Redundancy Protocol, 虚拟路由器冗余协议)的组播实现。
  • IPVS wrappers:生成ipvs规则。专门为LVS所用。
  • Netlink Reflector:设定vrpp的vip地址。

keepalived可以在每个节点配置相同的VRRP实例(vrrp_instance),并指定状态为MASTER或BACKUP。

当Checkers监测到本节点的服务不可用时,使本机的VRRP实例停止工作,并通知另外节点的VRRP STACK接管VRRP实例,从而对外保证服务继续可用。

双机互备方式的实现

keepalived实现主备工作的资料到处都有,我这里也有一个NginX主备机制的例子,这里就不再重复了。

其实,只要稍微动点脑筋,在主备的基础上就可以实现双机互备甚至集群的工作方式。因为有两个前提:

  • keepalived并没有限定节点的个数只能是2个
  • keepalived没有限定每个节点只能有一个VRRP实例

那么,双机互备的实现原理就是:

  • 在每个节点配置两个VRRP实例
  • 两个实例分别以一个节点为主(MASTER),另一个节点为备(BACKUP)
  • 通过外部的其他机制,如DNS轮询,使得两个VRRP实例同时对外提供服务

配置实例

keepalived的配置文件(/etc/keepalived/keepalived.conf)中包含3部分内容:

  • global_defs: 全局配置
  • vrrp_instance:vrrp实例,用来定义虚拟路由组
  • virtual_server:定义LVS虚拟服务器

这里面只例举一下vrrp实例的配置。

  • 节点1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29

vrrp_instance VI_1 {
state MASTER
interface eth0
virtual_router_id 51
priority 100
advert_int 1
authentication {
auth_type PASS
auth_pass password
}
virtual_ipaddress {
192.168.1.8
}
}
vrrp_instance VI_2 {
state BACKUP
interface eth0
virtual_router_id 52
priority 99
advert_int 1
authentication {
auth_type PASS
auth_pass password
}
virtual_ipaddress {
192.168.1.9
}
}
  • 节点2
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29

vrrp_instance VI_1 {
state BACKUP
interface eth0
virtual_router_id 51
priority 99
advert_int 1
authentication {
auth_type PASS
auth_pass password
}
virtual_ipaddress {
192.168.1.8
}
}
vrrp_instance VI_2 {
state MASTER
interface eth0
virtual_router_id 52
priority 100
advert_int 1
authentication {
auth_type PASS
auth_pass password
}
virtual_ipaddress {
192.168.1.9
}
}

技术领域又出现了无奈的一幕:最糟糕的技术被贴上最耀眼的标签,被推送到用户面前,免费赠送的还有厂商滔滔不绝的口水,让用户相信这才是最好的。

Read more »

统计学:从数据到结论,ISBN:9787503749964,作者:吴喜之 @豆瓣

统计推断(statistical inference):从数据得到关于现实世界的结论的过程。

由于统计学的研究对象是不可能穷举的大量个体,通常需要通过抽样方法得到样本,再用样本去推断总体的情况,
所以统计推断得出的不是一个精确的结论,而是近似结果。

统计推断的两个重要的方法是:

  • 估计(estimation)
  • 假设检验(hypothesis testing)

本章介绍估计,下一章介绍假设检验

5.1 用估计量估计总体参数

假定分布族

在通过样本信息推断总体情况之前,先假设总体的属性复合某种分布特征(分布族)。比如:

  • 假设身高符合正态分布族
  • 假设对某个观点的认同与否符合二项分布族

这些假设一半是通过经验获得,无法明确的证明。

确定具体分布

一个分布族下面的各种分布只是参数不同,通过研究样本确定这些参数,也就确定了具体分布。

常见的分布参数:

  • 总体均值
  • 总体标准差
  • 成功概率

正态分布由总体均值和标准差两个参数决定;
Bernoulli分布由概率一个参数决定

确定参数的过程是一个估计的过程,来源于样本数据。

通过样本计算的各种统计量中,用于估计的统计量称为估计量(estimator)。

估计量随样本的不同具有随机分布;对于给定的样本有一个给定的值,称为估计值(estimate)。

两种估计:

  • 点估计(point estimation):用一个估计值来近似总体参数
  • 区间估计(interval estimation):用一个包括估计值在内的区间表示总体参数很可能处于的范围

5.2 点估计

任何统计量都可以作为估计量。

估计量的命名可以来自:

  • 衡量一个估计量的好坏的某个标准
  • 估计量的计算方式

常见的估计量:

  • 样本均值:用于估计总体均值
  • 样本标准差(s):用于估计总体标准差
  • 成功比例(x/n):用于估计成功概率p

无偏估计量(unblased estimator):多个样本产生的估计量的期望等于要估计的总体参数,这样的估计量称为无偏估计量。

上述三种估计量都是无偏估计量。

5.3 区间估计

为了更准确的表达估算量,通常采用点估计和区间估计结合的说法。比如:

估计值+置信区间+置信度

其中:

  • 估计值是对总体量的点估计
  • 置信区间(confidence interval)是以估计值为中心的区间估计,包括上限(upper bound)和下限(lower bound)
  • 置信度(confidence level)是抽取大量样本时,该区间会覆盖样本估计值的比例

5.4 关于置信区间的注意点

置信度描述的是统计量覆盖总体参数的概率,而不是置信区间覆盖总体参数的概率

置信度越低,则置信区间越窄

5.5 小结(略)

任何事物都有内在属性和外在形式的两面。不管外在形式如何让人眼花缭乱,其内在属性都保持不变。把握了内在本质属性,才不会被各种“换汤不换药”的小把戏所迷惑。
企业服务也是一样。企业服务是web service吗?那是表面形式;企业服务是RESTful吗?那也是表面形式;企业服务是消息处理吗?那还是表面形式!

Read more »

State定义了Salt配置管理的内容,Pillar则定义了Salt配置管理的数据。Pillar使得同一个配置项在各个minion中可以使用不同的数据,从而不需要在State中定义大量的include, extend等关系。

为什么需要Pillar

看了这篇文档,你可能已经被Salt State的强大所折服。

是的,Salt State能够解决很多配置管理的问题,但是如下两个场景,如果只用state进行配置就会比较麻烦:

  1. apache配置项适应不同的OS

    这个例子中的apache配置中通过pkg模块验证apache软件包是否安装。但是在RedHat系统的yum包管理器和Debian系统的apt包管理器中,apache的包名字分别为httpdapache2。如何避免为apache配置项针对不同的包管理器定义不同的state?

  2. 同一个应用在不同环境中的数据库连接

    假如你开发了一个Django应用,数据库连接信息在应用的settings.py中定义:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    DATABASES = {
    'default': {
    'ENGINE': 'django.db.backends.mysql',
    'NAME': 'test',
    'USER': 'root',
    'PASSWORD': 'password',
    'HOST': 'localhost',
    'PORT': '3306',
    }
    }

    显然,数据库连接信息在开发环境、测试环境、生成环境中各不相同。如果把该应用作为一个state,如何实现在不同环境中的自动部署?

Salt Pillar就是为了解决类似上述的问题而提供的组件。

Pillar是什么?

这篇文章所述,Salt Sate定义了配置项以及minion和配置项直接的映射关系;与此类似,Pillar定义了数据以及minion和数据的映射关系。Pillar中定义的数据可以在Salt的其他组件中引用,当然最常见的情况是在State中引用Pillar数据。

比如,在上一节的第一个问题中,我们可以这样定义State:

1
2
3
4

apache:
pkg.installed:
- name: {{ pillar['apache'] }}

其中,salt.states.pkg.installed函数的name参数就是引用了Pillar中定义的变量apache

而该变量在Pillar中的定义如下:

1
2
3
4
5
6

{ % if grains['os_family'] == 'RedHat' % }
apache: httpd
{ % elif grains['os_family'] == 'Debian' % }
apache: apache2
{ % endif % }

Pillar的配置结构

Pillar与State就像是配置管理的左右手,所以Pillar的配置结构与State的配置结构几乎完全一样。

Pillar Tree和Environment

State Tree一样,Salt中可以定义一棵Pillar Tree,并且将Pillar按照环境进行分组管理。

Pillar Tree定义在salt master的配置文件/etc/salt/masterpillar_roots变量中:

1
2
3
4
5
6
7
8

pillar_roots:
base:
- /srv/pillar

ext_pillar:
- hiera: /etc/hiera.yaml
- cmd_yaml: cat /etc/salt/yaml

Pillar定义

Pillar是一组key-value,使用yaml的语法格式。

简单的定义比如:

foo: bar

可以使用{ { pillar['foo'] } }的形式进行引用;

复杂的定义比如:

1
2
3
4
5
users:
thatch: 1000
shouse: 1001
utahdave: 1002
redbeard: 1003

可以使用包含jinja语法的yaml进行引用:

1
2
3
4
5
6

{ % for user, uid in pillar.get('users', {}).items() % }
{ {user} }:
user.present:
- uid: { {uid} }
{ % endfor % }

定义好的pillar数据保存在Pillar Tree下面的某个sls文件中。为了能够在State中引用Pillar数据,
Pillar的目录结构和文件名需要与State能够对应。

Pillar可以用于任何数据的定义,比如ssh key、证书、密码口令等敏感数据,minion的模块、状态、信息反馈,以及要传递给minion的任何变量的值等等。
这些数据都会以加密通道安全的分发到minion上面。

Pillar的数据不仅仅可以来自SLS文件,还可以从其他数据源获取数据。相关内容可以自行查阅官方文档

minion与Pillar之间的映射

minion与state之间的映射一样,
在Pillar的base目录中也存在一个名为top.sls的入口文件,定义minion与Pillar的映射关系,例如:

1
2
3
4
5
6

base:
'*':
- packages
'alpha':
- database

上边的例子定义了packages对所有的minion有效,database只对名字为’alpha’的minion有效.

Pillar数据的查询和使用

  1. 查询pillar数据

    1
    2
    3
    salt 'client2' pillar.data
    salt '*' pillar.data
    salt '*' pillar.raw key='roles'

更多的函数可以参考pillar模块的文档

  1. 刷新pillar数据

    在master上修改Pilla文件后,需要用以下命令刷新minion上的数据(同步到minion):

    salt '*' saltutil.refresh_pillar
  1. 在其他sls文件中引用数据

    Pillar解析后是dict对象,直接使用Python语法,可以用索引(pillar['pkgs']['apache'])或get方法(pillar.get('users', {}))获取到需要的数据。

  2. 在Targetting中使用Pillar

    Targetting中可以用-I选项指定用Pillar数据选择minion。

参考资料