0%

Salt的state配置比较复杂,官方文档也比较零散。初学者不易掌握。但是如果把Salt的state配置看做是编写代码,就很容易掌握其脉络。

配置的目标是通过master管理多个mision的状态,最终配置的实现是使用文件夹和文件。而Salt state的设计就是在二者之间建立逻辑关系。

Salt的state配置比较复杂,官方文档也比较零散。初学者不易掌握。但是如果把Salt的state配置看做是编写代码,就很容易掌握其脉络。

下图是Salt state配置结构的逻辑图:

配置的目标是通过master管理多个mision的状态,最终配置的实现是使用文件夹和文件。而Salt state的设计就是在二者之间建立逻辑关系。

StateTree 和 Environment

每个master上面都会建立一棵state树,将各个state的配置分级管理。

这棵树的第一层就是环境(environment)的划分。salt将环境分为base环境和自定义环境。base环境是必须存在的,其他的环境根据自己的需要进行定义。典型的可以划分开发环境(dev), 用户参与测试环境(uat),生成环境(prod), 备份环境(backup)等等。

Salt约定base环境必须存在,是其他环境的基础,base环境中定义的state可以在各个自定义环境中使用。

显然,每个环境至少需要一个文件夹来保持多个state配置。事实上,Salt允许一个环境使用多个文件夹。

Salt环境与目录的对应关系在salt master的配置文件/etc/salt/masterfile_roots变量中定义。/etc/salt/master文件也是使用YAML格式。

一个典型的配置如下:

1
2
3
4
5
6
7
8
9
file_roots:
base:
- /srv/salt/
dev:
- /srv/salt/dev/services
- /srv/salt/dev/states
prod:
- /srv/salt/prod/services
- /srv/salt/prod/states

state定义

Salt state即可以使用单个的sls文件(single state),也可以使用一个文件夹并在其中保持多个sls及其他配置文件(multi-state)。

state之间还可以使用require, include, extend等关系进行关联。

minion 与 state之间的映射

一个salt master可以管理多个minion, 也可以定义很多个state。需要在minion和state之间建立一种多对多的映射关系。

Salt在一个top.sls文件中定义这种映射关系。比如:

1
2
3
4
5
6
base:
'*':
- servers
dev:
'*nodb*':
- mongodb

小结

按环境的不同划分state的存放目录;定义state文件/文件夹并在state之间使用关系实现复用;建立minion和state之间的多对多映射关系。

掌握了这三点,就掌握了Salt state配置的脉络。

实际上,Salt中Pillar的配置也使用了类似的结构。

在Salt的官方教程中,以apache和sshd的state配置作为例子。掌握这两个例子,就能够触类旁通,处理日常工作中大部分的配置管理问题。

本文对这两个例子进行详细的分析和注释.

在Salt的官方教程中,以apache和sshd的state配置作为例子。掌握这两个例子,就能够触类旁通,处理日常工作中大部分的配置管理问题。
本文对这两个例子进行详细的分析和注释。

目录结构

文档
中的例子包含了多个文件。这些文件之间互相引用和关联。目录结构及文件清单如下:

  • apache/init.sls

  • apache/httpd.conf

  • ssh/init.sls

  • ssh/server.sls

  • ssh/banner

  • ssh/ssh_config

  • ssh/sshd_config

  • ssh/custom-server.sls

两个配置分别放在了apachessh文件夹。一个Salt状态可以使用单个的SLS文件,或者使用一个文件夹。后者更加灵活方便。

apache/init.sls

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
30
31
32
33
34

apache:
pkg:
- installed
service:
- running
- watch:
- pkg: apache
- file: /etc/httpd/conf/httpd.conf
- user: apache
user.present:
- uid: 87
- gid: 87
- home: /var/www/html
- shell: /bin/nologin
- require:
- group: apache
group.present:
- gid: 87
- require:
- pkg: apache

/etc/httpd/conf/httpd.conf:
file.managed:
- source: salt://apache/httpd.conf
- user: root
- group: root
- mode: 644
- template: jinja
- context:
custom_var: "override"
- defaults:
custom_var: "default value"
other_var: 123

说明:

  1. sls文件使用YAML格式定义,最外面的层级定义配置项。
  2. 一个sls文件中可以有多个配置项,配置项的ID可以起任意的名字。本例中包含ID为apache/etc/httpd/conf/httpd.conf两个配置项。
  3. 配置项内是一系列的状态声明。所有的状态项来自Salt状态模块。即可以使用Salt内置的状态模块,也可以编写自定义的状态模块
  4. 状态声明内部指定状态函数的调用。状态函数是每个Salt状态模块中定义的函数。
  • apache配置项
  • /etc/httpd/conf/httpd.conf配置项
    • file.managed是简写形式,直接调用file模块managed方法根据需要从master获取文件并可能会通过模板系统(templating system)进行渲染。文件要满足如下要求:
      1. 使用master上面的apache/httpd.conf文件
      2. user=root
      3. group=root
      4. mode=644
      5. 使用jinja模板渲染
      6. 上下文变量:
        • custom_var=”override”
      7. 默认值:
        • custom_var=”default value”
        • other_var=123

ssh/init.sls

1
2
3
4
5
6
7
8
9
10
11
openssh-client:
pkg.installed

/etc/ssh/ssh_config:
file.managed:
- user: root
- group: root
- mode: 644
- source: salt://ssh/ssh_config
- require:
- pkg: openssh-client

说明:

ssh/server.sls

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
30
31
32
33

include:
- ssh

openssh-server:
pkg.installed

sshd:
service.running:
- require:
- pkg: openssh-client
- pkg: openssh-server
- file: /etc/ssh/banner
- file: /etc/ssh/sshd_config

/etc/ssh/sshd_config:
file.managed:
- user: root
- group: root
- mode: 644
- source: salt://ssh/sshd_config
- require:
- pkg: openssh-server

/etc/ssh/banner:
file:
- managed
- user: root
- group: root
- mode: 644
- source: salt://ssh/banner
- require:
- pkg: openssh-server

说明:

  • include语句将别的state添加到当前文件中,使得state可以跨文件引用。

    使用include相当于把被引用的内容文件添加到自身,可以require、watch或extend被引用的SLS中定义的内容。

    这里引用了sshstate。

  • openssh-server配置项

  • sshd

  • /etc/ssh/sshd_config配置项

  • /etc/ssh/banner配置项

ssh/custom-server.sls

1
2
3
4
5
6
7
include:
- ssh.server

extend:
/etc/ssh/banner:
file:
- source: salt://ssh/custom-banner

说明:

  • 引用sshstate的server配置项
  • extend可以复用已有的state,在原来的基础上进行扩展,增加新的配置或修改已有的配置。
    1. /etc/ssh/banner配置项的文件修改为salt://ssh/custom-banner

本文介绍Salt的主要功能和基本使用,包括minion节点的管理,批量操作,以及非常重要的配置管理。
掌握了这些内容,可以使用Salt极大提高运维的效率(事实上,Salt对于开发阶段也能提供很大的帮助,开发和运维的界限正在逐渐模糊)。

Read more »

实在是厌倦了对大量服务器日复一日的重复操作。尤其是在虚拟化的时代,系统的每个组件都有很多个相同的节点在运行,更让重复的次数再乘以N。

当我发现Salt的时候,我的眼前一亮:这正是我所需要的东西。

引言:一个”非专职运维人员“的烦恼

加入到某证券公司的IT部门,尽管所在的部门挂了一个“研发部”的名字,但是我发现有大概40%的时间是在做运维工作。

这来自两种情况:

  • 自主开发的应用,需要持续的改进,不断的更新、发布、部署、调整配置,这不是运维部门喜欢的状态。
  • 软件商提供的“产品”无法满足运维部门的要求:无法通过简单的 Q&A 文档保证系统的正常运行,经常需要有一定技术能力的人员解决系统运行过程中各种稀奇古怪的问题。

这种情况下只能自己做一个“非专职运维人员”,需要频繁的登录各种服务器,执行一些命令来查看状态或者更改配置(包括配置文件的变更和软件包的安装部署)。很多操作都是不断的重复,日复一日,让人厌烦。

”重复的工作应该交给程序去做“,所以我自己写过一些脚本。为了避免将脚本上传到几十台服务器并且不时进行更改,我使用Fabric来进行服务器的批量操作。

尽管避免了”批量的人工操作“,但我还是在进行”人工的批量操作“。远远没有实现自动管理。将有限的生命解放出来,投入到更有意义的编码工作是一个奔四程序员应有的追求,所以我又睁大红肿的眼睛,迷茫的搜索这个世界。

我发现了PuppetChefCFEngine,但是并不满意。直到我发现了Salt,我的眼前一亮:这正是我所需要的东西。

如果说Salt有什么独特之处打动了我,那就是:

  • 简单:可能是源于python的简约精神,Salt的安装配置和使用简单到了令人发指的地步。任何稍有经验的linux使用者可以在10分钟之内搭建一个测试环境并跑通一个例子(相比之下,puppet可能需要30–60分钟)。
  • 高性能:Salt使用大名鼎鼎的ZeroMQ作为通讯协议,性能极高。可以在数秒钟之内完成数据的传递
  • 可伸缩:基于ZeroMQ通信,具备很强的扩展性;可以进行分级管理,能够管理分布在广域网的上万台服务器。

尽管twitter豆瓣oracle、等著名网站的运维团队都在使用puppet,但是我相信,他们切换到salt只是一个时间问题。毕竟不是所有的人都喜欢操纵傀儡(puppet),但是谁又能离开盐(salt)呢?

关于Salt和Puppet的对比,可以参考这里,或者看看中文版

Salt快速入门

Salt的体系结构中将节点区分为: master, minion, syndic。

  • master: 老大,管理端
  • minion: 马仔,被管理端
  • syndic: 头目,对于老大来说是马仔,对于马仔来说是老大

在入门阶段,先不考虑syndic。

安装配置

如果将操作系统区分为:

  • *NIX

    • Linux
    • Solaris
    • HP Unix
    • FreeBSD
    • OS X
  • windows

理论上来说,Salt可以安装在任何*NIX系统上,包括master和minion。除了源代码之外,
还可以通过Salt提供的安装脚本,或者PyPI进行安装。

对于Linux,尤其是企业环境中常用的RHEL,CentOS,Ubuntu,可以通过包管理器非常容易的安装master 和/或 minion。
比如: yum(需要先配置EPEL), apt(需要增加http://debian.madduck.net/repo/库),yaourt,ports。

Mac OS X 先使用HomeBrew解决依赖包:brew install swig zmq,然后用PyPI安装:pip install salt

对于windows,只能安装minion(windows只适合做马仔)。从官方网站下载合适的安装包。安装过程中可以指定master地址和本机名称。
安装后需要自己启动Salt服务。配置文件在C:\salt\conf\minion。

具体的各操作系统下的安装可以参考官方文档。这里为了简单,只考虑常用的RHEL/CentOS 和 windows。 在下面的例子中,使用一台RHEL/CentOS作为master, 另外一台RHEL/CentOS和一台windows 2003 Server作为 minion。

安装管理端(master)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

# 安装EPEL,注意选择合适的版本
rpm -ivh http://mirrors.sohu.com/fedora-epel/6/x86_64/epel-release-6-8.noarch.rpm
yum update

# 安装master
yum install salt-master

# 修改配置
vim /etc/salt/master

# 最基本的设定服务端监听的IP(比如使用VIP做master的高可用时):
# interface: 服务端监听IP
# 其他配置参考[官方文档](http://docs.saltstack.com/ref/configuration/master.html)

# 启动服务(以下命令等效)
salt-master -d
/etc/init.d/salt-master start
service salt-master start

安装被管理端(minion)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

# 安装EPEL,注意选择合适的版本
rpm -ivh http://mirrors.sohu.com/fedora-epel/6/x86_64/epel-release-6-8.noarch.rpm
yum update

# 安装minion
yum install salt-minion

# 修改配置
vim /etc/salt/minion

# 最基本的设定是指定master地址,以及本机标识符:
# master: master的主机名或IP地址
# id: 本机标识符
# 其他配置参考[官方文档](http://docs.saltstack.com/ref/configuration/minion.html)


# 启动服务(以下命令等效)
salt-minion -d
/etc/init.d/salt-minion start
service salt-minion start

接受minion的托管请求

minion向master投诚后,还需要master接受才行。这个过程叫做“授信”。

Salt底层使用公钥-私钥证书来保证通信信道的安全。具体的机制可以参考ZeroMQ的相关内容。Salt已经屏蔽了底层的细节,只需要使用封装好的命令:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

# 在master上运行
# 查看所有minion
salt-key -L

Accepted Keys:
windows
bond_app_server_main
mac_os_vm
salt-master
Unaccepted Keys:
minion1
minion2
Rejected Keys:

#其中Unaccepted Keys是未许可的minion。可以使用下面的命令通过认证:
salt-key -a minion1

测试

安装配置好之后,首先要测试一下联通性:salt '*' test.ping。salt会列出每个认证过的minion的联通状态(true 或 false)。

再举一些例子:

1
2
3
4
5
6
7
8
9
10

# 查询主机运行了多长时间
sudo salt '*' cmd.run "uptime"


# 批量重启服务
salt '*' cmd.run "service httpd restart"

# 让多台机器一起,使用Apache Bench进行压力测试
salt '*' cmd.run "ab -n 10 -c 2 http://www.google.com/"

注意,默认情况下master和minion之间使用以下端口进行通信:

  • 4505(publish_port): salt的消息发布系统
  • 4506(ret_port):salt客户端与服务端通信的端口

网络的设置需要保证这些端口可以访问。

Salt的强大功能

上面的例子都是用Salt进行批量操作。但是Salt的功能不仅如此。

认真分析一下我的“非专职运维工作”的内容,发现可以分为以下三个方面:

  • 变更操作:根据需要对节点中某个资源的某种状态进行调整,并检验变更的结果
  • 配置管理:让上述行为变得“可管理”,支持“有关人士”对上述行为的标记、控制、识别、报告、跟踪和归档甚至审批和审计
  • 状态监控:随时掌握状态,发现异常。尽量在系统用户发现问题之前解决麻烦

Salt对上述三个方面提供了完美的支持,事实上,Salt提供的功能比我需要的还要多。下图是Salt的主要功能:

具体的功能使用在这篇文章中详细说明。

Salt的网络资源

网站

代码

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

@豆瓣

概率:0–1之间的一个数目,表示事情发生的可能性/经常性。

得到概率的几种途径

  1. 利用等可能事件

    在机会均等的情况下,概率 = 要计算概率的情况的组合数 / 全部可能情况的组合数

  2. 根据长期相对频率

    如果出现的机会不等,而且未知,可以用观测数据估计概率, 此时 概率 = 观测到的发生次数k / 重复实验的次数n

    只适用于可以重复实验的情况

  3. 主观概率

    不可计算、不可实验的、主要取决于主观因素的一次性事件,其发生的概率称为主观概率。

概率的运算

事件相当于集合

概率的运算可以从集合运算的角度考虑

  1. 互补事件的概率

    互补事件/互余事件/对立事件:相当于补集的概念。互补事件的概率之和为1

    优势/赔率:两个互补事件概率的比值

  2. 概率的加法

    两个不可能发生的事件,发生其中之一的概率,等于两个事件概率之和,相当于并集的概念

  3. 概率的乘法

    两个事件同时发生的概率,等于两个事件概率之积,相当于交集的概念

    仅当两个事件独立时才成立。如果不独立,需要引入条件概率

概率的分布

概率-变量值 的函数称为概率分布。可以用图或公式表示。

概率分布与总体/样本空间相关
  1. 离散随机变量的分布

    对于变量的每一个离散的值,对应着一个概率。全部概率的和为1

    这样的关系称为该离散随机变量的概率分布

  2. 二项分布

    最简单的离散分布,变量只能有两个值(如硬币的正反面),两个事件互补

    TODO: 更详细的说明

  3. 多项分布

    二项分布的扩展

  4. 泊松(Poisson)分布

    衡量某种事件在一定期间内出现的次数的概率

  5. 超几何分布

    研究有限总体的不放回抽样(检查样品后不放回,避免重复检查)

    比如抽取样品进行质检

    TODO: 公式和理解

  6. 连续随机变量的分布

    与离散变量的分布相对

    表现为概率密度函数。所有区间概率的积分为1

  7. 正态分布/高斯分布

    一个对称的钟形曲线,最高点对应均值

    TODO: 更多的变量和参数

  8. x^2-分布/卡方分布

    n个独立标准正态变量的平方和,称为有n个自由度的x^2-分布

  9. t-分布/学生分布

    正态分布的变换

    TODO:图形

  10. F-分布

    两个独立x^2-分布变量的比,称为F-分布变量

    F-分布有两个自由度

    TODO: 图形

  1. 均匀分布/矩形分布

    最简单的连续型分布,取值范围是一个区间。形状是一个矩形

  1. 累积分布函数

    为了便于计算某个区间的概率,对概率函数进行积分后得到的函数

抽样分布、中心极限定理

抽样分布:样本的统计量(均值、中位数、标准差等)随着样本的不同也是随机的,其分布称为抽样分布

抽样分布的特征可以帮助判断抽样是否合理

用小概率事件进行判断

如果对某种(统计)结论进行验证,可以抽取一定的样本进行检验,并得出一个概率。

如果该结果与事先的结论不符,可以根据事先结论计算得到实验结果的概率。

如果得到实验结果的概率非常低,可以认为结论不正确。

负载均衡(Load Balance)是集群技术(Cluster)的一种应用。负载均衡可以将工作任务分摊到多个处理单元,从而提高并发处理能力。目前最常见的负载均衡应用是Web负载均衡。根据实现的原理不同,常见的web负载均衡技术包括:DNS轮询、IP负载均衡和CDN。其中IP负载均衡可以使用硬件设备或软件方式来实现。

Read more »

用户故事

scrum的用户故事要有弹性,要能够容纳变化。要素:用户角色、功能需求、目的、测试要点。
一个有用的模板如下:
作为【用户的类型】,我希望可以【先这样做,然后那样做,就应该得到…的结果】以便【业务价值】。
用户故事只描述一个功能(feature),而且每个用户故事的开发周期不要太长(1-5天)

本文中的用户故事如下:

作为运维人员,我希望可以通过web界面管理salt-key,包括查询、添加、删除等,
这样我就不用每次都登录到master服务器进行相应的操作。

领域模型

敏捷方法并不排斥设计和建模。实际上,领域模型及可以对用户故事进行抽象,也可以帮助发现用户故事。

本文中,salt master 管理 salt minion。而minion实际上是一个主机(Host,
包括虚拟机Virtual Host)。 Host 安装了 salt-minion 后,通过 minion-id 向
salt-master 注册自己,而 salt-master 决定是否 接受该minion的注册请求。

如果从整个项目(运维操作平台)的视角来看,我们要管理的不仅仅是主机,甚至后续
grains 信息中的操作系统、IP地址等,
以及通过state安装的平台软件,都是需要管理的资源。资源还可能包括网络设备、子网等物理、虚拟资源。

所以有必要抽象出一个【资源】的实体,【主机】是【资源】的一个子类,【主机】可以有=minion-id=属性。
salt master 维护了salt keys的清单,包括 =Accepted Keys=、=Unaccepted
Keys=、=Rejected Keys=。

领域模型的设计如下:

其中=SaltKeyService=通过调用=salt-key=命令,执行list、accept、reject等操作,并根据操作结果更改=Host=实体。

=list()=操作,后续可以加入到定时任务。

开发准备

这部分内容不属于本文,但作为一系列开发培训的一部分,这里再次强调一下版本管理:

1
2
3
git pull  # 获取最新版本
git checkout -b feature-admin_minion develop # 基于develop 分支创建 feature-admin_minion 分支
git push origin feature-admin_minion #提交分支

RESTfulAPI 与 前后端分离

为了前后端分离,本项目中 Angular 和 Flask 通过 RESTful API
进行整合。所以有了领域模型之后,就要进行RESTful API设计。
具体Endpoint设计如下:

  • /resource/hosts
    • GET:
      查询所有的主机。允许的查询条件(query_params):limit,offset,sortby,order,properties
    • POST: 增加新的主机
  • resource/hosts
    • PUT: 更新主机信息
    • DELETE: 删除主机

基于API,前端开发人员可以在API_ROOT文件夹中增加静态json文件来调试,而后端开发人员可以通过对应的URL进行检验。

后端开发

models

本项目中使用了 Flask-SQLAlchemy
插件。模型的代码如下(由于Resource容易引起歧义,模型中使用=OpsResource=以便区分):

1
2
3
4
5
6
7
8
9
10
11
from ops import db
class OpsResource(db.Model):
id = db.Column(db.Integer, primary_key=True)
comment = db.Column(db.Text)

class Host(OpsResource):
id = db.Column(db.Integer, db.ForeignKey('ops_resource.id'), primary_key=True)
hostname = db.Column(db.String(50))
virtual = db.Column(db.String(50))
minionid = db.Column(db.String(50))
keystate = db.Column(db.Enum('Accepted', 'Unaccepted','Rejected', name='SALT_KEY_STATE'))

创建数据库的脚本=createdb.py=如下:

1
2
3
4
5
6
7
8
9
10
11
import os,sys
root = os.path.dirname(__file__)
sys.path.insert(0, os.path.join(root, './'))

from ops import app,db

import config

app.config.from_object('config.DevelopmentConfig')

db.create_all()

services

views

本项目中使用了 Flask-RESTful 插件。注册view的代码为:

1
2
3
4
5
6
7
8
9
from flask.ext.restful import Api
from ops import app

from resource import *

API_ROOT = '/api/'
api = Api(app)

api.add_resource(HostResource, API_ROOT+'resource/hosts', API_ROOT+'resource/hosts/<int:id>')

实现view的代码如下:

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
30
31
32
33
34
35
36
37
38
39
40
41
42
43

from flask import request
from flask.ext.restful import abort, Resource, fields, marshal_with, marshal
import json

from ops.models import Host
from ops.services import SaltService

host_fields = {
'id': fields.Integer,
'hostname': fields.String,
'minionid': fields.String,
'keystate': fields.String,
'virtual': fields.String,
'comment': fields.String,
}

class HostResource(Resource):
@marshal_with(host_fields)

def get(self, id=None):
salt = SaltService()
salt.list()

if not id:
hosts = Host.query.all()
else:
hosts = Host.query.filter_by(id=id).first()
return hosts

def post(self):
host = marshal(request.data, host_fields)
db.session.add(host)
db.session.commit()

return {'msg':'post successfully! '}


def delete(self, id):
pass

def put(self, id):
pass

后端测试用例

(TODO)

前端开发

安装需要的插件

1
2
3
cd PROJ_ROOT/web
bower install angular-bootstrap -S
bower install restangular -S

配置app.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
angular
.module('webApp', [
...
'ui.bootstrap',
'restangular',
...
])
.run(function (){
console.log('app run');

})
.config(function ($routeProvider,RestangularProvider) {
console.log('app config');
RestangularProvider.setBaseUrl('/api/');

$routeProvider
.when(
...

脚手架

1
yo angular:route host/list

会自动在=scripts/app.js=中增加路由,创建=scripts/host/list.js=、=views/host/list.html=文件,并在=index.html=
中增加=scripts/host/list.js=的引用。

此时已经可以访问 http://0.0.0.0:9000/#/host/list 了。

实现RESTful API调用

PROJROOT/web/app/scripts/host/list.js

1
2
3
4
5
6
7
8
9
10
11

angular.module('webApp')
.controller('HostListCtrl', function ($scope,Restangular) {
console.log('@HostListCtrl');

var url = Restangular.all('resource/hosts');

url.getList().then(function(hosts) {
$scope.hosts = hosts;
});
});

添加测试数据

根据前面的RESTful API约定,可以创建静态的json文件用于前端开发测试。

  • `PROJROOT/web/app/api/resource/hosts`
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
[
{
"comment": "comment1",
"hostname": "host1",
"id": 1,
"keystate": null,
"minionid": "minion1",
},
{
"hostname": "host2",
"id": 2,
"keystate": "Accepted",
"minionid": "minion2",
"virtual": "vmware"
}
]
  • `PROJROOT/web/app/api/resource/hosts/1`
1
TODO

编写html模板

`PROJROOT/web/app/views/host/list.html`

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<div class="container" ng-controller="HostListCtrl">
<ol class="breadcrumb">
<li ><strong>资源</strong></li>
<li class="active"><strong>主机</strong></li>
</ol>
<table class="table table-striped">
<tr><th width="20%">主机名</th><th width="20%">minionid</th><th>key状态</th><th>虚拟化</th><th>操作</th></tr>
<tr ng-repeat="host in hosts | orderBy: '-id'">
<td><a ng-href="/#/{{host.id}}">{{host.hostname}}</td>
<td>{{host.minionid}}</td>
<td>{{host.keystate}}</td>
<td>{{host.virtual}}</td>
<td>
<button type="button" class="btn btn-primary btn-xs">更新</button>
<button type="button" class="btn btn-danger btn-xs">删除</button>
</td>
</tr>
<tr>
<td><button type="button" class="btn btn-success">增加主机</button></td><td></td><td></td>
</tr>
</table>
</div>

前端测试

此时,在 http://0.0.0.0:9000/#/host/list
已经可以看到json文件中的数据了。

但是,更严谨的做法是写单元测试。

(TODO)

集成测试

实现集成测试最简单的方式是:前端开发完后,作为后端Flask的static。

搭建一个“现代化”的web开发环境中,
我们已经修改了grunt配置的`dist`,所以只要修改Flask中的一些配置:

1
2
3
4

app = Flask(**~name~\_**,static~urlpath~='')

@app.route('/') def index(): return redirect('/index.html')

参考资料

  1. 白话SCRUM 之二:product backlog
    http://blog.csdn.net/dylanren/article/details/7072734

  2. Scrum 之 product Backlog http://www.zhoujingen.cn/blog/2767.html

  3. 领域驱动设计(精简版)
    http://www.infoq.com/cn/minibooks/domain-driven-design-quickly-new

  4. scrum和分支管理策略
    http://holbrook.github.io/2015/05/05/git\_branch\_within\_scrum.html

  5. SQLAlchemy继承关系映射
    http://docs.sqlalchemy.org/en/rel\_1\_0/orm/inheritance.html

  6. 【工具】bootstrap表单构造器
    http://www.bootcss.com/p/bootstrap-form-builder/

LVS是实现软件负载均衡的一种方式。LVS支持多种负载均衡机制,包括:VS/NAT、VS/TUN和VS/DR。分别基于网络地址转换技术、IP隧道技术和直接路由技术。VS/FULLNAT是新兴的LVS的负载均衡机制,试图解决前面三种机制各自的不足。

Read more »

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

##第3章 数据的描述

2013-05-31: 1st

数据难以一目了然,但数据的特征容易掌握(如:定性or定量,变量的个数,收集目的等)

借助图表和一些运算有利于掌握更多关于数据的特征

数据的特征反映了总体的特征


数据特征的图形表示

  • 定量变量的图形表示

    • 直方图

      表达数据分布的疏密。纵坐标可以是数量或百分比

      如:人数-年龄,人数-财富值。

    • 盒形图

      指标(最大值,上四分位数,中位数,下四分位数,最小值)-> 条件,表达指标的多个特征在某种条件下的分布形态

    • 茎叶图

      既表达形状,又包含数据

    • 散点图

      用于比较成对的数值。散点图通常用于比较跨类别的聚合数据

  • 定性变量(属性变量,分类变量)的图形表示


数据的概括

用汇总/概括统计量来描述定量变量

统计量:summary statistic

样本的随机性决定了统计量的随机性

样本统计量 vs 总体统计量

  • 可以用样本统计量估计总体统计量

  • 可以用样本统计量来检验对总体的假设

概括数据通常使用以下统计量

  • 数据的位置

    均值容易受单个样本偏差 or 少数极端值的影响,但位置不会

    中位数比均值稳健(robust)

    中位数,上下四分位数,

    alpha= k百分位数(k-pecentile):有k% 的观测值小于alpha, alpha称为alpha分位数(quantile)

    众数(mode):样本中出现最多的数目。 使用得较少

  • 数据的尺度

    描述数据的分布是否均匀

    尺度统计量描述数据集中与分散的程度或变化(散度统计量)

    数据越分散,尺度统计量的值越大

    • 极差(range), 最大、最小值之差

      如,盒形图中盒子的高度(有时为宽度)表示四分位间距(interquantile range)

    • 标准差,方差

      标准差是方差的平方根

      单峰值数据的分布(1delta=68%, 2delta=95%),多峰值数据的分布。。。

      同一总体,多个不同样本的均值的标准差称为标准误差(standand error)

  • 数据的标准得分

    如,两个水平接近的班级,两个老师进行评分。由于评分标准不同,两个班成绩的均值和标准差都不一样。
    如何放在一起评价?

    方法:数据标准化——可以理解为对盒形图的缩放和位移

    标准得分是比较常用的一种标准化方法:

    标准得分z = (得分-样本均值)/样本标准差