Jenkins自动化任务工具介绍

Jenkins是一个独立的开源自动化服务器,可用于自动化各种任务,如构建,测试和部署软件。Jenkins可以通过本机系统包 Docker安装(https://www.w3cschool.cn/docker/),甚至可以通过安装Java Runtime Environment的任何机器独立运行。

说明

本说明是针对使用需要Java 8的“独立”Jenkins发行版。还建议使用超过512MB RAM的系统。

  • 下载Jenkins (http://mirrors.jenkins.io/war-stable/latest/jenkins.war)

  • 在下载目录中打开终端并运行 java -jar jenkins.war –httpPort=8080

  • 浏览http://localhost:8080并按照说明完成安装。

  • 许多Pipeline示例需要 在与Jenkins相同的计算机上安装Docker。Docker安装下载教程:https://www.w3cschool.cn/docker/

安装完成后,开始将Jenkins运行并创建Pipeline。

Jenkins Pipeline是一套插件,支持将连续输送Pipeline实施和整合到Jenkins。Pipeline提供了一组可扩展的工具,用于将“复制代码”作为代码进行建模。

Jenkinsfile 是一个包含Jenkins Pipeline定义的文本文件,并被检入源代码控制。这是“Pipeline代码”的基础; 处理连续输送Pipeline的一部分应用程序,以像其他代码一样进行版本检查。创建Jenkinsfile提供了一些直接的好处:

  • 自动创建所有分支和拉请求的Pipeline

  • Pipeline上的代码审查/迭代

  • Pipeline的审计跟踪

  • Pipeline的唯一真实来源 ,可以由项目的多个成员查看和编辑。

虽然在Web UI或a中定义Pipeline的语法 Jenkinsfile是相同的,但通常认为最佳做法是在Jenkinsfile中定义Pipeline并检查源控制。

etcd分布式键值存储服务的备份与恢复

  • etcd 是一款开源的分布式一致性键值存储,由 CoreOS 公司进行维护,详细的介绍请参考官方文档。

  • etcd 目前最新的版本的 v3.1.1,但它的 API 又有 v3 和 v2 之分,社区通常所说的 v3 与 v2 都是指 API 的版本号。从 etcd 2.3 版本开始推出了一个实验性的全新 v3 版本 API 的实现,v2 与 v3 API 使用了不同的存储引擎,所以客户端命令也完全不同。

# etcdctl --version
etcdctl version: 3.0.4
API version: 2
  • 官方指出 etcd v2 和 v3 的数据不能混合存放,support backup of v2 and v3 stores 。

  • 特别提醒:

    • 若使用 v3 备份数据时存在 v2 的数据则不影响恢复
    • 若使用 v2 备份数据时存在 v3 的数据则恢复失败

对于 API 2 备份与恢复方法

官方 v2 admin guide (https://github.com/coreos/etcd/blob/master/Documentation/v2/admin_guide.md#disaster-recovery)

etcd的数据默认会存放在我们的命令工作目录中,我们发现数据所在的目录,会被分为两个文件夹中:

  • snap: 存放快照数据,etcd防止WAL文件过多而设置的快照,存储etcd数据状态。
  • wal: 存放预写式日志,最大的作用是记录了整个数据变化的全部历程。在etcd中,所有数据的修改在提交前,都要先写入到WAL中。
# etcdctl backup --data-dir /home/etcd/ --backup-dir /home/etcd_backup

# etcd -data-dir=/home/etcd_backup/  -force-new-cluster

恢复时会覆盖 snapshot 的元数据(member ID 和 cluster ID),所以需要启动一个新的集群。

对于 API 3 备份与恢复方法

官方 v3 admin guide (https://github.com/coreos/etcd/blob/master/Documentation/op-guide/recovery.md)

在使用 API 3 时需要使用环境变量 ETCDCTL_API 明确指定。
在命令行设置:

# export ETCDCTL_API=3

备份数据:

# etcdctl --endpoints localhost:2379 snapshot save snapshot.db

恢复:

# etcdctl snapshot restore snapshot.db --name m3 --data-dir=/home/etcd_data

恢复后的文件需要修改权限为 etcd:etcd

  • –name:重新指定一个数据目录,可以不指定,默认为 default.etcd
  • –data-dir:指定数据目录

建议使用时不指定 name 但指定 data-dir,并将 data-dir 对应于 etcd 服务中配置的 data-dir

etcd 集群都是至少 3 台机器,官方也说明了集群容错为 (N-1)/2,所以备份数据一般都是用不到,但是鉴上次 gitlab 出现的问题,对于备份数据也要非常重视。

Linux服务器CPU占用率较高问题排查思路

注意:本文相关配置及说明已在 CentOS 6.5 64 位操作系统中进行过测试。其它类型及版本操作系统配置可能有所差异,具体情况请参阅相应操作系统官方文档。

如果云服务器 ECS Linux 系统的 CPU 持续跑高,则会对系统稳定性和业务运行造成影响。本文对 CPU 占用率较高问题的排查分析做简要说明。

CPU 负载查看方法

使用 vmstat 查看系统纬度的 CPU 负载

可以通过 vmstat 从系统维度查看 CPU 资源的使用情况。

用法说明:

格式:vmstat -n 1

-n 1 表示结果一秒刷新一次。

示例输出:$ vmstat -n 1procs —————-memory————— —-swap— ——-io—— -system— ———cpu——- r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st 0  0      0  70352 169448 448452    0    0     0     4   10   11  0  0 99  0  0 0  0      0  70376 169448 448484    0    0     0     0  175  406  0  0 100  0  0 0  0      0  70376 169448 448484    0    0     0     0  173  414  0  1 99  0  0 0  0      0  70376 169448 448484    0    0     0   128  212  429  3  0 96  1  0^C

回显说明:

返回结果中的主要数据列说明:

  • r: 表示系统中 CPU 等待处理的线程。由于 CPU 每次只能处理一个线程,所以,该数值越大,通常表示系统运行越慢。
  • us:用户模式消耗的 CPU 时间百分比。该值较高时,说明用户进程消耗的 CPU 时间比较多,比如,如果该值长期超过 50%,则需要对程序算法或代码等进行优化。
  • sy:内核模式消耗的 CPU 时间百分比。
  • wa:IO 等待消耗的 CPU 时间百分比。该值较高时,说明 IO 等待比较严重,这可能磁盘大量作随机访问造成的,也可能是磁盘性能出现了瓶颈。
  • id:处于空闲状态的 CPU 时间百分比。如果该值持续为 0,同时 sy 是 us 的两倍,则通常说明系统则面临着 CPU 资源的短缺。

使用 top 查看进程纬度的 CPU 负载

可以通过 top 从进程纬度来查看其 CPU、内存等资源的使用情况。

用法说明:

格式:top

示例输出:top - 17:27:13 up 27 days,  3:13,  1 user,  load average: 0.02, 0.03, 0.05Tasks:  94 total,   1 running,  93 sleeping,   0 stopped,   0 zombie%Cpu(s):  0.3 us,  0.1 sy,  0.0 ni, 99.5 id,  0.0 wa,  0.0 hi,  0.0 si,  0.1 stKiB Mem:   1016656 total,   946628 used,    70028 free,   169536 buffersKiB Swap:        0 total,        0 used,        0 free.   448644 cached Mem

  PID USER      PR  NI    VIRT    RES    SHR S %CPU %MEM     TIME+ COMMAND    1 root      20   0   41412   3824   2308 S  0.0  0.4   0:19.01 systemd    2 root      20   0       0      0      0 S  0.0  0.0   0:00.04 kthreadd 

回显说明:

默认界面上第三行会显示当前 CPU 资源的总体使用情况,下方会显示各个进程的资源占用情况。

可以直接在界面输入大小字母 P,来使监控结果按 CPU 使用率倒序排列,进而定位系统中占用 CPU 较高的进程。最后,根据系统日志和程序自身相关日志,对相应进程做进一步排查分析,以判断其占用过高 CPU 的原因。

操作案例

使用 top 直接终止 CPU 消耗较大的进程

如前面所述,可以通过 top 命令查看系统的负载问题,并定位耗用较多 CPU 资源的进程。

可以直接在 top 运行界面快速终止相应的异常进程。说明如下:

  • 想要终止某个进程,只需按下小写的 k 键。

  • 输入想要终止的进程 PID (top 输出结果的第一列)。比如,如下图所示,假如想要终止 PID 为 23 的进程,输入 23 后按回车。

未分类

  • 如下图所示,操作成功后,界面会出现类似 “Send pid 23 signal [15/sigterm]” 的提示信息让用户进行确认。按回车确认即可。

未分类

CPU 使用率较低但负载较高

  • 问题描述:

Linux 系统没有业务程序运行,通过 top 观察,类似如下图所示,CPU 很空闲,但是 load average 却非常高:

未分类

  • 处理办法:

load average 是对 CPU 负载的评估,其值越高,说明其任务队列越长,处于等待执行的任务越多。

出现此种情况时,可能是由于僵死进程导致的。可以通过指令 ps -axjf 查看是否存在 D 状态进程。

D 状态是指不可中断的睡眠状态。该状态的进程无法被 kill,也无法自行退出。只能通过恢复其依赖的资源或者重启系统来解决。

未分类

kswapd0 进程占用 CPU 较高

操作系统都用分页机制来管理物理内存,操作系统将磁盘的一部分划出来作为虚拟内存,由于内存的速度要比磁盘快得多,所以操作系统要按照某种换页机制将不需要的页面换到磁盘中,将需要的页面调到内存中,由于内存持续不足,这个换页动作持续进行,kswapd0是虚拟内存管理中负责换页的,当服务器内存不足的时候kswapd0会执行换页操作,这个换页操作是十分消耗主机CPU资源的。如果通过top发现该进程持续处于非睡眠状态,且运行时间较长,可以初步判定系统在持续的进行换页操作,可以将问题转向内存不足的原因来排查。

  • 问题描述:

kswapd0 进程占用了系统大量 CPU 资源。

  • 处理办法:

Linux 系统通过分页机制管理内存的同时,将磁盘的一部分划出来作为虚拟内存。而 kswapd0 是 Linux 系统虚拟内存管理中负责换页的进程。当系统内存不足时,kswapd0 会频繁的进行换页操作。而由于换页操作非常消耗 CPU 资源,所以会导致该进程持续占用较高 CPU 资源。
如果通过 top 等监控发现 kswapd0 进程持续处于非睡眠状态,且运行时间较长并持续占用较高 CPU 资源,则通常是由于系统在持续的进行换页操作所致。则可以通过 free 、ps 等指令进一步查询系统及系统内进程的内存占用情况,做进一步排查分析。

查看crontab的日志记录定位定时任务问题

昨天crontab中的同步任务没有执行,不知道是什么原因没有执行,貌似任务hang住了,想查询一下crontab到底问题出在哪里,或者hang在了什么地方。

1、linux

看 /var/log/cron这个文件就可以,可以用tail -f /var/log/cron观察

2、unix

在 /var/spool/cron/tmp文件中,有croutXXX001864的tmp文件,tail 这些文件就可以看到正在执行的任务了。

3、mail任务

在 /var/spool/mail/root 文件中,有crontab执行日志的记录,用tail -f /var/spool/mail/root 即可查看最近的crontab执行情况。

python flask before_request、after_request修饰器截获所有请求

在学习着用flask开发安卓后天接口时,遇到一个需求,就是想截获所有请求,即在所有请求进入app.route装饰的函数前先被处理一次。

经过在网上查找资料后,知道了@before_request、@after_request这两个方法,示例:

@app.before_request
def before_request():
    ip = request.remote_addr
    url = request.url
    print ip,
    print url

before_request()函数被app.before_request修饰以后,每一次请求到来后,都会先进入函数before_request()中,如上代码,获取请求的ip以及url,并打印出来,执行完毕后请求才会正常进入到app.route修饰的函数中响应,如果有多个函数被app.before_request修饰了,那么这些函数会被依次执行。

app.before_request修饰器在开发中用处非常大,比如判断某个ip是否有恶意访问行为,从而进行拦截等操作。

此外同理,app.after_request修饰器是在用户请求得到函数响应后被执行,不过需要注意的是这个执行是在函数返回数据前被调用,即请求已经被app.route修饰的函数响应过了,已经形成了response,但还未返回给用户的时候,调用的。

linux后台进程管理工具-supervisor

安装环境为:centos,如果是ubuntu的话命令可能会不一样。

Supervisor 是一个用python编写的进程管理工具,能将一个普通的命令行进程变为后台的deamon,方便管理。

安装supervisor

可以通过yum和pip来安装,可以根据个人喜好来使用,我用yum来安装的:

yum -y install supervisor //-y 为自动安装,不会再弹确认提醒

yum安装完成以后会在 /etc/下创建 supervisord.conf 配置文件及supervisord.d文件夹。

supervisord.conf 选项及值可以去supervisor官网查看 //有时间整理下写上来

配置supervisor

我们为自己开发的应用程序编写一个配置文件,放在/etc/supervisord.d下,以.conf或.ini结尾,下面写个简单的例子,详细的可以去看supervisor官网

[program:app]
command=/usr/bin/xxx    //运行程序的命令
directory=/tmp/xxx      //程序的目录
user=xxx                //运行程序的用户身份

启动supervisor服务

supervisord -c /etc/supervisor.conf

用supervisor客户端管理工具supervisorctl,来管理进程。

$ supervisorctl status      //查看状态
$ supervisorctl stop xxx    //停止应用
$ supervisorctl start xxx   //启动应用
$ supervisorctl restart xxx //重启应用

CentOS7下部署ceph-12 (luminous)多机集群

一、准备

前一篇点击打开链接只部署了一个单机集群。在这一篇里,手动部署一个多机集群:mycluster。我们有三台机器nod1,node2和node3;其中node1可以免密ssh/scp任意其他两台机器。我们的所有工作都在node1上完成。

准备工作包括在各个机器上安装ceph rpm包(见前一篇第1节点击打开链接),并在各个机器上修改下列文件:

/usr/lib/systemd/system/[email protected]
/usr/lib/systemd/system/[email protected]
/usr/lib/systemd/system/[email protected]
/usr/lib/systemd/system/[email protected]
/usr/lib/systemd/system/[email protected]

修改:

Environment=CLUSTER=ceph                                                  <---  改成CLUSTER=mycluster
ExecStart=/usr/bin/... --id %i --setuser ceph --setgroup ceph    <--- 删掉--setuser ceph --setgroup ceph

二、创建工作目录

在node1创建一个工作目录,后续所有工作都在node1上的这个工作目录中完成;

mkdir /tmp/mk-ceph-cluster  
cd /tmp/mk-ceph-cluster  

三、创建配置文件

vim mycluster.conf  
[global]  
    cluster                     = mycluster  
    fsid                        = 116d4de8-fd14-491f-811f-c1bdd8fac141  

    public network              = 192.168.100.0/24  
    cluster network             = 192.168.73.0/24  

    auth cluster required       = cephx  
    auth service required       = cephx  
    auth client required        = cephx  

    osd pool default size       = 3  
    osd pool default min size   = 2  

    osd pool default pg num     = 128  
    osd pool default pgp num    = 128  

    osd pool default crush rule = 0  
    osd crush chooseleaf type   = 1  

    admin socket                = /var/run/ceph/$cluster-$name.asock  
    pid file                    = /var/run/ceph/$cluster-$name.pid  
    log file                    = /var/log/ceph/$cluster-$name.log  
    log to syslog               = false  

    max open files              = 131072  
    ms bind ipv6                = false  

[mon]  
    mon initial members = node1,node2,node3  
    mon host = 192.168.100.131:6789,192.168.100.132:6789,192.168.100.133:6789  

    ;Yuanguo: the default value of {mon data} is /var/lib/ceph/mon/$cluster-$id,  
    ;         we overwrite it.  
    mon data                     = /var/lib/ceph/mon/$cluster-$name  
    mon clock drift allowed      = 10  
    mon clock drift warn backoff = 30  

    mon osd full ratio           = .95  
    mon osd nearfull ratio       = .85  

    mon osd down out interval    = 600  
    mon osd report timeout       = 300  

    debug ms                     = 20  
    debug mon                    = 20  
    debug paxos                  = 20  
    debug auth                   = 20  

[mon.node1]  
    host                         = node1  
    mon addr                     = 192.168.100.131:6789  
[mon.node2]  
    host                         = node2  
    mon addr                     = 192.168.100.132:6789  
[mon.node3]  
    host                         = node3  
    mon addr                     = 192.168.100.133:6789  

[mgr]  
    ;Yuanguo: the default value of {mgr data} is /var/lib/ceph/mgr/$cluster-$id,  
    ;         we overwrite it.  
    mgr data                     = /var/lib/ceph/mgr/$cluster-$name  

[osd]  
    ;Yuanguo: we wish to overwrite {osd data}, but it seems that 'ceph-disk' forces  
    ;     to use the default value, so keep the default now; maybe in later versions  
    ;     of ceph the limitation will be eliminated.  
    osd data                     = /var/lib/ceph/osd/$cluster-$id  
    osd recovery max active      = 3  
    osd max backfills            = 5  
    osd max scrubs               = 2  

    osd mkfs type = xfs  
    osd mkfs options xfs = -f -i size=1024  
    osd mount options xfs = rw,noatime,inode64,logbsize=256k,delaylog  

    filestore max sync interval  = 5  
    osd op threads               = 2  

    debug ms                     = 100  
    debug osd                    = 100

需要说明的是,在这个配置文件中,我们覆盖了一些默认值,比如:{mon data}和{mgr data},但是没有覆盖{osd data},因为ceph-disk貌似强制使用默认值。另外,pid, sock文件被放置在/var/run/ceph/中,以$cluster-$name命名;log文件放置在/var/log/ceph/中,也是以$cluster-$name命名。这些都可以覆盖。

四、生成keyring

在单机部署中点击打开链接,我们说过,有两种操作集群中user及其权限的方式,这里我们使用第一种:先生成keyring文件,然后在创建集群时带入使之生效。

ceph-authtool --create-keyring mycluster.keyring --gen-key -n mon. --cap mon 'allow *'  

ceph-authtool --create-keyring mycluster.client.admin.keyring --gen-key -n client.admin --set-uid=0 --cap mon 'allow *' --cap osd 'allow *' --cap mds 'allow *' --cap mgr 'allow *'  
ceph-authtool --create-keyring mycluster.client.bootstrap-osd.keyring --gen-key -n client.bootstrap-osd --cap mon 'allow profile bootstrap-osd'  
ceph-authtool --create-keyring mycluster.mgr.node1.keyring --gen-key -n mgr.node1 --cap mon 'allow profile mgr' --cap osd 'allow *' --cap mds 'allow *'  
ceph-authtool --create-keyring mycluster.mgr.node2.keyring --gen-key -n mgr.node2 --cap mon 'allow profile mgr' --cap osd 'allow *' --cap mds 'allow *'  
ceph-authtool --create-keyring mycluster.mgr.node3.keyring --gen-key -n mgr.node3 --cap mon 'allow profile mgr' --cap osd 'allow *' --cap mds 'allow *'  

ceph-authtool mycluster.keyring  --import-keyring mycluster.client.admin.keyring  
ceph-authtool mycluster.keyring  --import-keyring mycluster.client.bootstrap-osd.keyring  
ceph-authtool mycluster.keyring  --import-keyring mycluster.mgr.node1.keyring  
ceph-authtool mycluster.keyring  --import-keyring mycluster.mgr.node2.keyring  
ceph-authtool mycluster.keyring  --import-keyring mycluster.mgr.node3.keyring  
cat mycluster.keyring  
[mon.]  
        key = AQA525NZsY73ERAAIM1J6wSxglBNma3XAdEcVg==  
        caps mon = "allow *"  
[client.admin]  
        key = AQBJ25NZznIpEBAAlCdCy+OyUIvxtNq+1DSLqg==  
        auid = 0  
        caps mds = "allow *"  
        caps mgr = "allow *"  
        caps mon = "allow *"  
        caps osd = "allow *"  
[client.bootstrap-osd]  
        key = AQBW25NZtl/RBxAACGWafYy1gPWEmx9geCLi6w==  
        caps mon = "allow profile bootstrap-osd"  
[mgr.node1]  
        key = AQBb25NZ1mIeFhAA/PmRHFY6OgnAMXL1/8pSxw==  
        caps mds = "allow *"  
        caps mon = "allow profile mgr"  
        caps osd = "allow *"  
[mgr.node2]  
        key = AQBg25NZJ6jyHxAAf2GfBAG5tuNwf9YjkhhEWA==  
        caps mds = "allow *"  
        caps mon = "allow profile mgr"  
        caps osd = "allow *"  
[mgr.node3]  
        key = AQBl25NZ7h6CJRAAaFiea7hiTrQNVoZysA7n/g==  
        caps mds = "allow *"  
        caps mon = "allow profile mgr"  
        caps osd = "allow *"  

五、生成monmap

生成monmap并添加3个monitor

monmaptool --create --add node1 192.168.100.131:6789 --add node2 192.168.100.132:6789 --add node3 192.168.100.133:6789  --fsid 116d4de8-fd14-491f-811f-c1bdd8fac141 monmap  
[plain] view plain copy
monmaptool --print monmap  
monmaptool: monmap file monmap  
epoch 0  
fsid 116d4de8-fd14-491f-811f-c1bdd8fac141  
last_changed 2017-08-16 05:45:37.851899  
created 2017-08-16 05:45:37.851899  
0: 192.168.100.131:6789/0 mon.node1  
1: 192.168.100.132:6789/0 mon.node2  
2: 192.168.100.133:6789/0 mon.node3  

六、分发配置文件

keyring和monmap

把第2、3和4步中生成的配置文件,keyring,monmap分发到各个机器。由于mycluster.mgr.nodeX.keyring暂时使用不到,先不分发它们(见第8节)。

cp mycluster.client.admin.keyring mycluster.client.bootstrap-osd.keyring mycluster.keyring  mycluster.conf monmap /etc/ceph  
scp mycluster.client.admin.keyring mycluster.client.bootstrap-osd.keyring mycluster.keyring  mycluster.conf monmap node2:/etc/ceph  
scp mycluster.client.admin.keyring mycluster.client.bootstrap-osd.keyring mycluster.keyring  mycluster.conf monmap node3:/etc/ceph  

七、创建集群

1、创建{mon data}目录

mkdir /var/lib/ceph/mon/mycluster-mon.node1      
ssh node2 mkdir /var/lib/ceph/mon/mycluster-mon.node2  
ssh node3 mkdir /var/lib/ceph/mon/mycluster-mon.node3  

注意,在配置文件mycluster.conf中,我们把{mon data}设置为/var/lib/ceph/mon/$cluster-$name,而不是默认的/var/lib/ceph/mon/$cluster-$id;
$cluster-$name展开为mycluster-mon.node1(23);
默认的$cluster-$id展开为mycluster-node1(23);

2、初始化monitor

ceph-mon --cluster mycluster --mkfs -i node1 --monmap /etc/ceph/monmap --keyring /etc/ceph/mycluster.keyring  
ssh node2 ceph-mon --cluster mycluster --mkfs -i node2 --monmap /etc/ceph/monmap --keyring /etc/ceph/mycluster.keyring  
ssh node3 ceph-mon --cluster mycluster --mkfs -i node3 --monmap /etc/ceph/monmap --keyring /etc/ceph/mycluster.keyring  

注意,在配置文件mycluster.conf,我们把{mon data}设置为/var/lib/ceph/mon/$cluster-$name,展开为/var/lib/ceph/mon/mycluster-mon.node1(23)。ceph-mon会
根据–cluster mycluster找到配置文件mycluster.conf,并解析出{mon data},然后在那个目录下进行初始化。

3、touch done

touch /var/lib/ceph/mon/mycluster-mon.node1/done  
ssh node2 touch /var/lib/ceph/mon/mycluster-mon.node2/done  
ssh node3 touch /var/lib/ceph/mon/mycluster-mon.node3/done  

4、启动monitors

systemctl start ceph-mon@node1  
ssh node2 systemctl start ceph-mon@node2  
ssh node3 systemctl start ceph-mon@node3  

5、检查机器状态

ceph --cluster mycluster -s  
  cluster:  
    id:     116d4de8-fd14-491f-811f-c1bdd8fac141  
    health: HEALTH_OK  

  services:  
    mon: 3 daemons, quorum node1,node2,node3  
    mgr: no daemons active  
    osd: 0 osds: 0 up, 0 in  

  data:  
    pools:   0 pools, 0 pgs  
    objects: 0 objects, 0 bytes  
    usage:   0 kB used, 0 kB / 0 kB avail  
    pgs:  

八、添加osd

每台集群都有一个/dev/sdb,我们把它们作为osd。

1、删除它们的分区

2、prepare

ceph-disk prepare --cluster mycluster --cluster-uuid 116d4de8-fd14-491f-811f-c1bdd8fac141 --bluestore --block.db /dev/sdb  --block.wal /dev/sdb /dev/sdb  
ssh node2 ceph-disk prepare --cluster mycluster --cluster-uuid 116d4de8-fd14-491f-811f-c1bdd8fac141 --bluestore --block.db /dev/sdb  --block.wal /dev/sdb /dev/sdb  
ssh node3 ceph-disk prepare --cluster mycluster --cluster-uuid 116d4de8-fd14-491f-811f-c1bdd8fac141 /dev/sdb  
注意:prepare node3:/dev/sdb时,我们没有加选项:--bluestore --block.db /dev/sdb  --block.wal /dev/sdb;后面我们会看它和其他两个有什么不同。

3、activate

ceph-disk activate /dev/sdb1 --activate-key /etc/ceph/mycluster.client.bootstrap-osd.keyring  
ssh node2 ceph-disk activate /dev/sdb1 --activate-key /etc/ceph/mycluster.client.bootstrap-osd.keyring  
ssh node3 ceph-disk activate /dev/sdb1 --activate-key /etc/ceph/mycluster.client.bootstrap-osd.keyring  

注意:ceph-disk好像有两个问题:

  • 前面说过,它不使用自定义的{osd data},而强制使用默认值 /var/lib/ceph/osd/$cluster-$id

  • 好像不能为一个磁盘指定osd id,而只能依赖它自动生成。虽然ceph-disk prepare有一个选项–osd-id,但是ceph-disk activate并不使用它而是自己生成。当不匹配时,会出现 如下错误:

# ceph-disk activate /dev/sdb1 --activate-key /etc/ceph/mycluster.client.bootstrap-osd.keyring  
command_with_stdin: Error EEXIST: entity osd.0 exists but key does not match  

mount_activate: Failed to activate  
'['ceph', '--cluster', 'mycluster', '--name', 'client.bootstrap-osd', '--keyring', '/etc/ceph/mycluster.client.bootstrap-osd.keyring', '-i', '-', 'osd', 'new', u'ca8aac6a-b442-4b07-8fa6-62ac93b7cd29']' failed with status code 17  

从 ‘-i’, ‘-‘可以看出,它只能自动生成osd id;

4、检查osd

在ceph-disk prepare时,node1:/dev/sdb和node2:/dev/sdb一样,都有–bluestore –block.db /dev/sdb –block.wal选项;node3:/dev/sdb不同,没有加这些选项。我们看看有什么不同。

4.1 node1

mount | grep sdb  
/dev/sdb1 on /var/lib/ceph/osd/mycluster-0 type xfs (rw,noatime,seclabel,attr2,inode64,noquota)  

ls /var/lib/ceph/osd/mycluster-0/  
activate.monmap  block     block.db_uuid  block.wal       bluefs     fsid     kv_backend  mkfs_done  systemd  whoami  
active           block.db  block_uuid     block.wal_uuid  ceph_fsid  keyring  magic       ready      type  

ls -l /var/lib/ceph/osd/mycluster-0/block  
lrwxrwxrwx. 1 ceph ceph 58 Aug 16 05:52 /var/lib/ceph/osd/mycluster-0/block -> /dev/disk/by-partuuid/a12dd642-b64c-4fef-b9e6-0b45cff40fa9  

ls -l /dev/disk/by-partuuid/a12dd642-b64c-4fef-b9e6-0b45cff40fa9  
lrwxrwxrwx. 1 root root 10 Aug 16 05:55 /dev/disk/by-partuuid/a12dd642-b64c-4fef-b9e6-0b45cff40fa9 -> ../../sdb2  

blkid /dev/sdb2  
/dev/sdb2: PARTLABEL="ceph block" PARTUUID="a12dd642-b64c-4fef-b9e6-0b45cff40fa9"  

cat /var/lib/ceph/osd/mycluster-0/block_uuid  
a12dd642-b64c-4fef-b9e6-0b45cff40fa9  



ls -l /var/lib/ceph/osd/mycluster-0/block.db  
lrwxrwxrwx. 1 ceph ceph 58 Aug 16 05:52 /var/lib/ceph/osd/mycluster-0/block.db -> /dev/disk/by-partuuid/1c107775-45e6-4b79-8a2f-1592f5cb03f2  

ls -l /dev/disk/by-partuuid/1c107775-45e6-4b79-8a2f-1592f5cb03f2  
lrwxrwxrwx. 1 root root 10 Aug 16 05:55 /dev/disk/by-partuuid/1c107775-45e6-4b79-8a2f-1592f5cb03f2 -> ../../sdb3  

blkid /dev/sdb3  
/dev/sdb3: PARTLABEL="ceph block.db" PARTUUID="1c107775-45e6-4b79-8a2f-1592f5cb03f2"  

cat /var/lib/ceph/osd/mycluster-0/block.db_uuid  
1c107775-45e6-4b79-8a2f-1592f5cb03f2  



ls -l /var/lib/ceph/osd/mycluster-0/block.wal  
lrwxrwxrwx. 1 ceph ceph 58 Aug 16 05:52 /var/lib/ceph/osd/mycluster-0/block.wal -> /dev/disk/by-partuuid/76055101-b892-4da9-b80a-c1920f24183f  

ls -l /dev/disk/by-partuuid/76055101-b892-4da9-b80a-c1920f24183f  
lrwxrwxrwx. 1 root root 10 Aug 16 05:55 /dev/disk/by-partuuid/76055101-b892-4da9-b80a-c1920f24183f -> ../../sdb4  

blkid /dev/sdb4  
/dev/sdb4: PARTLABEL="ceph block.wal" PARTUUID="76055101-b892-4da9-b80a-c1920f24183f"  

cat /var/lib/ceph/osd/mycluster-0/block.wal_uuid  
76055101-b892-4da9-b80a-c1920f24183f  

可见,node1(node2)上,/dev/sdb被分为4个分区:

  • /dev/sdb1: metadata
  • /dev/sdb2:the main block device
  • /dev/sdb3: db
  • /dev/sdb4: wal

具体见:ceph-disk prepare –help

4.2 node3

mount | grep sdb  
/dev/sdb1 on /var/lib/ceph/osd/mycluster-2 type xfs (rw,noatime,seclabel,attr2,inode64,noquota)  

ls /var/lib/ceph/osd/mycluster-2  
activate.monmap  active  block  block_uuid  bluefs  ceph_fsid  fsid  keyring  kv_backend  magic  mkfs_done  ready  systemd  type  whoami  

ls -l /var/lib/ceph/osd/mycluster-2/block  
lrwxrwxrwx. 1 ceph ceph 58 Aug 16 05:54 /var/lib/ceph/osd/mycluster-2/block -> /dev/disk/by-partuuid/0a70b661-43f5-4562-83e0-cbe6bdbd31fb  

ls -l /dev/disk/by-partuuid/0a70b661-43f5-4562-83e0-cbe6bdbd31fb  
lrwxrwxrwx. 1 root root 10 Aug 16 05:56 /dev/disk/by-partuuid/0a70b661-43f5-4562-83e0-cbe6bdbd31fb -> ../../sdb2  

blkid /dev/sdb2  
/dev/sdb2: PARTLABEL="ceph block" PARTUUID="0a70b661-43f5-4562-83e0-cbe6bdbd31fb"  

cat /var/lib/ceph/osd/mycluster-2/block_uuid  
0a70b661-43f5-4562-83e0-cbe6bdbd31fb  

可见,在node3上,/dev/sdb被分为2个分区:

  • /dev/sdb1:metadata
  • /dev/sdb2:the main block device;db和wal也在这个分区上。

具体见:ceph-disk prepare –help

5、检查集群状态

ceph --cluster mycluster -s  
  cluster:  
    id:     116d4de8-fd14-491f-811f-c1bdd8fac141  
    health: HEALTH_WARN  
            no active mgr  

  services:  
    mon: 3 daemons, quorum node1,node2,node3  
    mgr: no daemons active  
    osd: 3 osds: 3 up, 3 in  

  data:  
    pools:   0 pools, 0 pgs  
    objects: 0 objects, 0 bytes  
    usage:   0 kB used, 0 kB / 0 kB avail  
    pgs:  

由于没有添加mgr,集群处于WARN状态。

九、添加mgr

1、创建{mgr data}目录

mkdir /var/lib/ceph/mgr/mycluster-mgr.node1  
ssh node2 mkdir /var/lib/ceph/mgr/mycluster-mgr.node2  
ssh node3 mkdir /var/lib/ceph/mgr/mycluster-mgr.node3  

注意,和{mon data}类似,在配置文件mycluster.conf中,我们把{mgr data}设置为/var/lib/ceph/mgr/$cluster-$name,而不是默认的/var/lib/ceph/mgr/$cluster-$id。

2、分发mgr的keyring

cp mycluster.mgr.node1.keyring /var/lib/ceph/mgr/mycluster-mgr.node1/keyring  
scp mycluster.mgr.node2.keyring node2:/var/lib/ceph/mgr/mycluster-mgr.node2/keyring  
scp mycluster.mgr.node3.keyring node3:/var/lib/ceph/mgr/mycluster-mgr.node3/keyring  

3、启动mgr

systemctl start ceph-mgr@node1  
ssh node2 systemctl start ceph-mgr@node2  
ssh node3 systemctl start ceph-mgr@node3  

4、检查集群状态

ceph --cluster mycluster -s  
  cluster:  
    id:     116d4de8-fd14-491f-811f-c1bdd8fac141  
    health: HEALTH_OK  

  services:  
    mon: 3 daemons, quorum node1,node2,node3  
    mgr: node1(active), standbys: node3, node2  
    osd: 3 osds: 3 up, 3 in  

  data:  
    pools:   0 pools, 0 pgs  
    objects: 0 objects, 0 bytes  
    usage:   5158 MB used, 113 GB / 118 GB avail  
    pgs:  

可见,添加mgr之后,集群处于OK状态。

安装配置HAProxy实现RabbitMQ的负载均衡

HAProxy提供高可用性、负载均衡以及基于TCP和HTTP应用的代理,支持虚拟主机,它是免费、快速并且可靠的一种解决方案,包括Twitter,Reddit,StackOverflow,GitHub在内的多家知名互联网公司在使用。HAProxy实现了一种事件驱动、单一进程模型,此模型支持非常大的并发连接数。

安装HAProxy

首先需要去HAProxy的官网下载HAProxy的安装文件,目前最新的版本为:haproxy-1.7.8.tar.gz。下载地址为http://www.haproxy.org/#down,相关文档地址为http://www.haproxy.org/#doc1.7。

将haproxy-1.7.8.tar.gz拷贝至/opt目录下,与RabbitMQ存放在同一个目录中。之后解压缩:

[root@node1 opt]# tar zxvf haproxy-1.7.8.tar.gz

将源码解压之后,需要运行make来将HAProxy编译为可执行程序。在执行make之前需要先选择目标平台,通常对于UNIX系的操作系统可以选择TARGET=generic。下面是详细操作:

[root@node1 opt]# cd haproxy-1.7.8
[root@node1 haproxy-1.7.8]# make TARGET=generic
gcc -Iinclude -Iebtree -Wall  -O2 -g -fno-strict-aliasing -Wdeclaration-after-statement -fwrapv      
-DTPROXY -DENABLE_POLL  
-DCONFIG_HAPROXY_VERSION="1.7.8" 
-DCONFIG_HAPROXY_DATE="2017/07/07" 
          -DBUILD_TARGET='"generic"' 
          -DBUILD_ARCH='""' 
          -DBUILD_CPU='"generic"' 
          -DBUILD_CC='"gcc"' 
          -DBUILD_CFLAGS='"-O2 -g -fno-strict-aliasing -Wdeclaration-after-statement -fwrapv"' 
          -DBUILD_OPTIONS='""' 
           -c -o src/haproxy.o src/haproxy.c
gcc -Iinclude -Iebtree -Wall  -O2 -g -fno-strict-aliasing -Wdeclaration-after-statement -fwrapv...
...
gcc  -g -o haproxy src/haproxy.o src/base64.o src/protocol.o src/uri_auth.o ...

编译完目录下有名为“haproxy”的可执行文件。之后再/etc/profile中加入haproxy的路径,内容如下:

export PATH=$PATH:/opt/haproxy-1.7.8/haproxy

最后执行source /etc/profile让此环境变量生效。

配置HAProxy

HAProxy使用单一配置文件来定义所有属性,包括从前端IP到后端服务器。下面展示了用于3个RabbitMQ节点组成集群的负载均衡配置。这3个节点的IP地址分别为192.168.02、192.168.0.3、192.168.0.4,HAProxy运行在192.168.0.9这台机器上。

#全局配置
global
        #日志输出配置,所有日志都记录在本机,通过local0输出
        log 127.0.0.1 local0 info
        #最大连接数
        maxconn 4096
        #改变当前的工作目录
        chroot /opt/haproxy-1.7.8
        #以指定的UID运行haproxy进程
        uid 99
        #以指定的GID运行haproxy进程
        gid 99
        #以守护进程方式运行haproxy #debug #quiet
        daemon
        #debug
        #当前进程pid文件
        pidfile /opt/haproxy-1.7.8/haproxy.pid

#默认配置
defaults
        #应用全局的日志配置
        log global
        #默认的模式mode{tcp|http|health}
        #tcp是4层,http是7层,health只返回OK
        mode tcp
        #日志类别tcplog
        option tcplog
        #不记录健康检查日志信息
        option dontlognull
        #3次失败则认为服务不可用
        retries 3
        #每个进程可用的最大连接数
        maxconn 2000
        #连接超时
        timeout connect 5s
        #客户端超时
        timeout client 120s
        #服务端超时
        timeout server 120s

#绑定配置
listen rabbitmq_cluster 5671
        #配置TCP模式
        mode tcp
        #简单的轮询
        balance roundrobin
        #RabbitMQ集群节点配置
        server rmq_node1 192.168.0.2:5672 check inter 5000 rise 2 fall 3 weight 1
        server rmq_node2 192.168.0.3:5672 check inter 5000 rise 2 fall 3 weight 1
        server rmq_node3 192.168.0.4:5672 check inter 5000 rise 2 fall 3 weight 1

#haproxy监控页面地址
listen monitor :8100
        mode http
        option httplog
        stats enable
        stats uri /stats
        stats refresh 5s

在上面的配置中“listen rabbitmq_cluster bind 192.168.0.9.5671”这里定义了客户端连接IP地址和端口号。这里配置的负载均衡算法是roundrobin,注意这里的roundrobin是加权轮询。和RabbitMQ最相关的是“ server rmq_node1 192.168.0.2:5672 check inter 5000 rise 2 fall 3 weight 1”这种,它定义了RabbitMQ服务,每个RabbitMQ服务定义指令包含6个部分:

server <name>:定义RabbitMQ服务的内部标示,注意这里的“rmq_node”是指包含有含义的字符串名称,不是指RabbitMQ的节点名称。
<ip>:<port>:定义RabbitMQ服务的连接的IP地址和端口号。
check inter <value>:定义了每隔多少毫秒检查RabbitMQ服务是否可用。
rise <value>:定义了RabbitMQ服务在发生故障之后,需要多少次健康检查才能被再次确认可用。
fall <value>:定义需要经历多少次失败的健康检查之后,HAProxy才会停止使用此RabbitMQ服务。
weight <value>:定义了当前RabbitMQ服务的权重。

最后一段配置定义的是HAProxy的数据统计页面。数据统计页面包含各个服务节点的状态、连接、负载等信息。在调用:

[root@node1 haproxy-1.7.8]# haproxy -f haproxy.cfg

运行HAProxy之后可以在浏览器上输入http://192.168.0.9:8100/stats来加载相关的页面,如下图所示:

未分类

Ubuntu 16.04系统下安装nodejs的两种方法

本文将会通过两种方法来讲述如何在Ubuntu 16.4 LTS Linux系统下安装node.js。
Node.js是一种运行在服务器端的JavaScript运行环境。

方法1: 通过apt-get 命令来安装Ubuntu 发行方repo里的版本

执行下面的apt-get 命令:

$ sudo apt-get install nodejs npm

命令输出如下:

root@ubuntutest:~# apt-get install nodejs npm
 正在读取软件包列表... 完成
 正在分析软件包的依赖关系树
 正在读取状态信息... 完成
 将会同时安装下列软件:
 ......
 建议安装:
 ......

下列【新】软件包将被安装:
 ......
 下列软件包将被升级:
 libc6 libssl1.0.0 zlib1g
 升级了 3 个软件包,新安装了 104 个软件包,要卸载 0 个软件包,有 123 个软件包未被升级。
 需要下载 54.6 MB 的归档。
 解压缩后会消耗 201 MB 的额外空间。
 您希望继续执行吗? [Y/n]Y

查看Node.js 版本

执行下面的命令:

$ nodejs --version
v4.2.6

方法2: 安装最新版本的Node.js 6.x (稳定版本)或 7.x

首先要安装Node.js 6.x 的repo,执行下面的命令:

$ curl -sL https://deb.nodesource.com/setup_t.x | sudo -E bash -

安装node.js 6.x 版本,执行命令:

$ sudo apt-get install nodejs build-essential

安装node.js 7.x 最新版本,执行下面的命令:

$ curl -sL https://deb.nodesource.com/setup_7.x | sudo -E bash -
$ sudo apt-get install -y nodejs build-essential

更多关于node.js 的信息可以查看其官方网站 https://nodejs.org/en/

Ubuntu 16.04使用apt-fast加速apt-get下载安装包

使用 apt-fast shell 封装器,通过多个连接同时下载一个包来加速 apt-get/apt 和 aptitude 命令,进而使得自己的工作效率得到提升。

如何加速在 Ubuntu Linux 16.04 或者 14.04 LTS 上从多个仓库中下载包的 apt-get 或者 apt 命令?你需要使用到 apt-fast 这个 shell 封装器,它会通过多个连接同时下载一个包来加速 apt-get/apt 和 aptitude 命令并且所有的包都会同时下载,另外它使用 aria2c 作为默认的下载加速器。

安装 apt-fast 工具

在 Ubuntu Linux 14.04 或者之后的版本尝试下面的命令:

$ sudo add-apt-repository ppa:saiarcot895/myppa

未分类

更新你的仓库:

$ sudo apt-get update

或者

$ sudo apt update

未分类

安装 apt-fast:

$ sudo apt-get -y install apt-fast

或者

$ sudo apt -y install apt-fast
Reading package lists... Done
Building dependency tree
Reading state information... Done
The following additional packages will be installed:
  aria2 libc-ares2 libssh2-1
Suggested packages:
  aptitude
The following NEW packages will be installed:
  apt-fast aria2 libc-ares2 libssh2-1
0 upgraded, 4 newly installed, 0 to remove and 0 not upgraded.
Need to get 1,282 kB of archives.
After this operation, 4,786 kB of additional disk space will be used.
Do you want to continue? [Y/n] y
Get:1 http://01.archive.ubuntu.com/ubuntu xenial/universe amd64 libssh2-1 amd64 1.5.0-2 [70.3 kB]
Get:2 http://ppa.launchpad.net/saiarcot895/myppa/ubuntu xenial/main amd64 apt-fast all 1.8.3~137+git7b72bb7-0ubuntu1~ppa3~xenial1 [34.4 kB]
Get:3 http://01.archive.ubuntu.com/ubuntu xenial/main amd64 libc-ares2 amd64 1.10.0-3 [33.9 kB]
Get:4 http://01.archive.ubuntu.com/ubuntu xenial/universe amd64 aria2 amd64 1.19.0-1build1 [1,143 kB]
54% [4 aria2 486 kB/1,143 kB 42%]                                    20.4 kB/s 32s

配置 apt-fast

你将会得到下面的提示(必须输入一个5到16的数值):

未分类

并且

未分类

你也可以直接编辑设置:

$ sudo vi /etc/apt-fast.conf

请注意这个工具并不是给慢速网络连接的,它是给快速网络连接的。如果你的网速慢,那么你将无法从这个工具中得到好处。

该怎么使用 apt-fast 命令?

语法是:

$ apt-fast command
$ apt-fast [options] command

使用 apt-fast 取回新的包列表:

$ sudo apt-fast update

使用 apt-fast 执行升级:

$ sudo apt-fast upgrade

执行发行版升级(发布或者强制内核升级),输入:

$ sudo apt-fast dist-upgrade

安装新的包

$ sudo apt-fast install pkg
比如要安装 nginx,输入:
$ sudo apt-fast install nginx

未分类

删除包:

$ sudo apt-fast remove pkg
$ sudo apt-fast remove nginx

删除包和它的配置文件:

$ sudo apt-fast purge pkg
$ sudo apt-fast purge nginx

删除所有未使用的包:

$ sudo apt-fast autoremove

下载源码包:

$ sudo apt-fast source pkgNameHere

清理下载的文件:

$ sudo apt-fast clean

清理旧的下载文件:

$ sudo apt-fast autoclean

验证没有破坏的依赖:

$ sudo apt-fast check

下载二进制包到当前目录:

$ sudo apt-fast download pkgNameHere
$ sudo apt-fast download nginx
[#7bee0c 0B/0B CN:1 DL:0B]
07/26 15:35:42 [NOTICE] Verification finished successfully. file=/home/vivek/nginx_1.10.0-0ubuntu0.16.04.2_all.deb
07/26 15:35:42 [NOTICE] Download complete: /home/vivek/nginx_1.10.0-0ubuntu0.16.04.2_all.deb
Download Results:
gid   |stat|avg speed  |path/URI
======+====+===========+=======================================================
7bee0c|OK  |        n/a|/home/vivek/nginx_1.10.0-0ubuntu0.16.04.2_all.deb
Status Legend:
(OK):download completed.

下载并显示指定包的 changelog:

$ sudo apt-fast changelog pkgNameHere
$ sudo apt-fast changelog nginx