0%

原文地址:https://gist.github.com/elsonrodriguez/a26cdb7f04a9e94c480457e12458954a

Quick and Dirty Ceph Cluster

这是一个关于如何使用ceph-ansible设置Ceph集群的简明指南。

本指南假设:

  • Ansible安装在您的本地计算机上
  • 8个Centos 7.2节点使用XFS进行配置和格式化
  • 您对节点有ssh和sudo访问权限

Ansible Setup

首先,克隆ceph-ansible repo。

1
2
3
git clone https://github.com/ceph/ceph-ansible.git
cd ceph-ansible
git checkout a41eddf6f0d840580bc842fa59751defef10fa69

接下来,在repo的基础上添加一个inventory文件。使用以下内容作为指南,将示例IP替换为您自己的计算机IP。

1
2
3
4
5
6
7
8
9
10
11
12
13
[mons]
10.0.0.1
10.0.0.2
10.0.0.3

[osds]
10.0.0.4
10.0.0.5
10.0.0.6
10.0.0.7

[clients]
10.0.0.8

我们需要至少3个MON(cluster state daemons)4个OSD(object storage daemons)和1个client(to mount the storage)。

接下来,我们需要复制samples。

1
2
3
4
cp site.yml.sample site.yml
cp group_vars/all.sample group_vars/all
cp group_vars/mons.sample group_vars/mons
cp group_vars/osds.sample group_vars/osds

现在,我们需要修改group_vars/all中的一些变量:

1
2
3
4
5
6
7
ceph_origin: 'upstream' 
ceph_stable: true

monitor_interface: eth0
public_network: 172.20.0.0/16

journal_size: 5120

在groups_vars/osd中:

1
2
3
osd_directory: true
osd_directories:
- /var/lib/ceph/osd/mydir1

Running ceph-ansible playbook

创建inventory文件并修改变量后:

1
ansible-playbook site.yml -vvvv -i inventory -u centos

完成后,您应该有一个正常运行的Ceph集群。

Interacting with Ceph

原文地址:http://docs.ceph.com/ceph-ansible/master/

ceph-ansible

Ansible playbooks for Ceph, the distributed filesystem.

分布式文件系统,Ceph Ansible playbooks。

Installation

您可以按照以下步骤直接从GitHub上的源安装:

Clone the repository:

1
git clone https://github.com/ceph/ceph-ansible.git

接下来,您必须决定使用哪个ceph-ansible branch。 有稳定的branch可供选择,或者您可以使用master branch:

1
git checkout $branch

接下来,使用pip和提供的requirements.txt来安装ansible和其他所需的python库:

1
pip install -r requirements.txt

Ansible on RHEL and CentOS

您可以从 Ansible channel 获取并安装RHEL和CentOS上的Ansible。

On RHEL:

1
subscription-manager repos --enable=rhel-7-server-ansible-2-rpms

(CentOS不使用subscription-manager,默认情况下已启用“Extras” 。)

1
sudo yum install ansible

Ansible on Ubuntu

您可以使用 Ansible PPA 在Ubuntu上获取Ansible。

1
2
3
sudo add-apt-repository ppa:ansible/ansible
sudo apt update
sudo apt install ansible

Releases

应根据您的需求使用以下branches。stable-* branches已经过QE测试,并且在lifecycle内会得到backport修复。master branch应该被认为是实验性的,谨慎使用。

  • stable-3.0 支持ceph jewel和luminous版本。该branch需要Ansible 2.4版本。
  • stable-3.1 支持ceph luminous和mimic版本。该branch需要Ansible 2.4版本。
  • stable-3.2支持ceph luminous和mimic版本。该branch需要Ansible 2.6版本。
  • stable-4.0支持ceph nautilus版本。该branch需要Ansible 2.8版本。
  • master 支持Ceph@master版本。该branch需要Ansible 2.8版本。

Configuration and Usage

该项目假设您具有ansible的基本知识,并已经准备好主机以供Ansible配置。在clone了ceph-ansible repository后,选择你的branch并且安装了ansible,然后你需要为你的ceph集群创建你的inventory文件,playbook和configuration。

Inventory

ansible inventory文件定义集群中的主机以及每个主机在ceph集群中扮演的角色(role)。inventory文件的默认位置是/etc/ansible/hosts,但此文件可以放在任何位置,并与ansible-playbook-i flag一起使用。

示例inventory文件如下所示:

1
2
3
4
5
6
7
8
9
[mons]
mon1
mon2
mon3

[osds]
osd1
osd2
osd3
1
2
3
注意
有关ansible inventories的更多信息,请参阅ansible文档:
http://docs.ansible.com/ansible/latest/intro_inventory.html

Playbook

在部署群集时,必须有一个playbook传递给ansible-playbook命令。在ceph-ansible项目的根目录中有一个名为site.yml.sample的示例playbook。这个playbook应该适用于大多数用法,但它默认包含每个守护进程组(every daemon group),这可能不适合你的群集设置。执行以下步骤准备您的playbook:

  • 重命名示例playbook:mv site.yml.sample site.yml
  • 根据群集需求修改playbook
1
2
注意
重要的是你使用的playbook应放在ceph-ansible项目的root目录。这就是ansible能够找到ceph-ansible提供的roles的方式。

Configuration Validation

ceph-ansible项目通过ceph-validate 角色(role)提供配置验证(config validation)。如果您使用的是所提供的playbooks,此role将在部署前运行,以确保您的ceph-ansible配置正确。此检查仅确保您为群集提供了正确的配置,而不是生成healthy集群。例如,如果为monitor_address提供了错误的地址,则mon仍然无法加入群集。

验证失败的示例可能如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
TASK [ceph-validate : validate provided configuration] *************************
task path: /Users/andrewschoen/dev/ceph-ansible/roles/ceph-validate/tasks/main.yml:3
Wednesday 02 May 2018 13:48:16 -0500 (0:00:06.984) 0:00:18.803 *********
[ERROR]: [mon0] Validation failed for variable: osd_objectstore

[ERROR]: [mon0] Given value for osd_objectstore: foo

[ERROR]: [mon0] Reason: osd_objectstore must be either 'bluestore' or 'filestore'

fatal: [mon0]: FAILED! => {
"changed": false
}

Supported Validation

ceph-validate角色(role)当前支持验证以下osd场景的配置:

  • collocated(journal与data一块盘)

  • non-collocated

  • lvm

ceph-validate角色(role)还验证了以下安装选项:

  • ceph_origin 设置为 distro
  • ceph_origin 设置为 repository
  • ceph_origin 设置为 local
  • ceph_repository 设置为 rhcs
  • ceph_repository 设置为 dev
  • ceph_repository 设置为 community

Installation methods

Ceph可以通过几种方法安装。

Configuration

ceph集群的配置将通过ceph-ansible提供的ansible变量来设置。所有这些选项及其默认值都在ceph-ansible项目root目录下的group_vars/子目录中定义。Ansible将在group_vars/子目录中使用您的inventory文件或playbook配置。在group_vars/子目录中有许多ansible配置文件示例,它们通过文件名与每个ceph守护进程组(ceph daemon groups)关联。例如,osds.yml.sample包含OSD守护进程的所有默认配置。all.yml.sample文件是一个特殊的group_vars文件,适用于群集中的所有主机。

1
2
注意
有关设置group或主机特定配置的更多信息,请参阅ansible文档:http://docs.ansible.com/ansible/latest/intro_inventory.html#splitting-out-host-and-group-specific-data

最基本的,您必须告诉ceph-ansible要安装的ceph版本,安装方法,群集网络设置以及希望如何配置OSD。开始配置,请重命名group_vars/目录中的每个文件,让它不包含文件名末尾的.sample,取消要更改选项的注释并提供自己的值。

使用lvm批处理方法部署Ceph upstream的octopus版本,在group_vars/all.yml中如下配置:

1
2
3
4
5
6
7
8
9
ceph_origin: repository
ceph_repository: community
ceph_stable_release: octopus
public_network: "192.168.3.0/24"
cluster_network: "192.168.4.0/24"
monitor_interface: eth1
devices:
- '/dev/sda'
- '/dev/sdb'

所有安装都需要更改以下配置选项,但可能还有其他必需选项,具体取决于OSD方案选择或群集的其他方面。

  • ceph_origin
  • ceph_stable_release
  • public_network
  • monitor_interface or monitor_address

部署RGW实例时,需要设置``radosgw_interfaceradosgw_address`选项。

ceph.conf Configuration File

覆盖已定义 ceph.conf 中内容的方法是使用 ceph_conf_overrides 变量。这允许您使用 INI 格式指定配置选项。此变量可用于覆盖已在 ceph.conf 中定义的sections(请参见:roles/ceph-config/templates/ceph.conf.j2)或提供新的配置选项。

支持ceph.conf中的以下部分:

  • [global]
  • [mon]
  • [osd]
  • [mds]
  • [client.rgw.{instance_name}]

例如:

1
2
3
4
5
6
ceph_conf_overrides:
global:
foo: 1234
bar: 5678
osd:
osd_mkfs_type: ext4
1
2
注意
我们将不再接受修改ceph.conf模板的pull requests,除非它有助于部署。对于简单的配置调整,请使用ceph_conf_overrides变量。

用于配置每个ceph daemon types的完整文档,在以下各sections中。

OSD Configuration

通过选择OSD场景并提供该场景所需的配置来设置OSD配置。从稳定4.0版的nautilus开始,唯一可用的场景是lvm。

stable-4.0开始,不再支持下列场景,因为他们与ceph-disk相关联:

  • collocated
  • non-collocated

自Ceph luminous发布以来,首选使用ceph-volume工具的lvm场景。任何其他方案都将导致弃用警告。

ceph-disk在ceph-ansible 3.2中被弃用,并且已经在Nautilus版本完全从Ceph本身中删除。 目前(从稳定版4.0开始),只有一个场景,默认为lvm,参见:

  • lvm

因此不再需要配置osd_scenario,它默认为lvm

上面提到的lvm场景支持containerized和non-containerized集群。提醒一下,可以通过将containerized_deployment设置为True来完成部署容器化集群。

lvm

此场景使用ceph-volume来创建LVM的OSD,并且仅在Ceph luminous或更新的版本才可用。它会自动启用。

其他(可选)支持的设置:

  • osd_objectstore:为OSD设置Ceph objectstore。可用选项是filestorebluestore。你只能选择luminous或更高Ceph版本的bluestore。如果未设置,则默认为bluestore

  • dmcrypt:使用dmcrypt在OSD上启用Ceph加密。如果未设置,则默认为false。

  • osds_per_device:为每个设备提供多个OSD(如果未设置,默认为1,也就是说1个设备1个OSD)。

Simple configuration

使用这种方法,有关设备如何配置为预配 OSD 的决策都由 Ceph 工具完成的(本例中为ceph-volume lvm批处理)。在给定输入设备的情况下,几乎无法修改OSD的组合方式。

要使用此配置,必须配置使用OSD的原始设备路径填充devices选项。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
注意
原始设备必须“干净”,没有gpt分区表或逻辑卷存在。
[root@dev ~]# yum install gdisk -y
[root@dev ~]# gdisk /dev/sda
GPT fdisk (gdisk) version 0.8.10

Partition table scan:
MBR: not present
BSD: not present
APM: not present
GPT: not present

Creating new GPT entries.

Command (? for help): x

Expert command (? for help): z
About to wipe out GPT on /dev/sda. Proceed? (Y/N): Y
GPT data structures destroyed! You may now partition the disk using fdisk or
other utilities.
Blank out MBR? (Y/N): Y

例如,对于具有/dev/sda/dev/sdb的节点,配置将是:

1
2
3
devices:
- /dev/sda
- /dev/sdb

在上述情况下,如果两个设备都是spinning(旋转)设备(HDD),则会创建2个OSD,每个OSD都有自己的collocated journal(journal与data同盘)。

其他方式可能是spinning设备与solid state设备混合部署(HDD+SSD),例如:

1
2
3
4
devices:
- /dev/sda
- /dev/sdb
- /dev/nvme0n1

与最初的示例类似,最终会生成2个OSD,但数据将放在较慢的spinning设备(/dev/sda, 和/dev/sdb)上,而journals将放在速度更快的solid state设备/dev/nvme0n1上。 ceph-volume工具在“batch”子命令部分详细描述了这一点

此选项也可以与osd_auto_discovery一起使用,这意味着您不需要直接填充devices ,而是使用ansible找到的任何适当的设备。

1
osd_auto_discovery: true

其他(可选)支持的设置:

  • crush_device_class:为使用此方法创建的所有OSD设置CRUSH device class(使用simple configuration方法不可能每个OSD都有CRUSH device class)。 值必须是字符串,如crush_device_class:"ssd"
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
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
未使用crush_device_class
# begin crush map
tunable choose_local_tries 0
tunable choose_local_fallback_tries 0
tunable choose_total_tries 50
tunable chooseleaf_descend_once 1
tunable chooseleaf_vary_r 1
tunable chooseleaf_stable 1
tunable straw_calc_version 1
tunable allowed_bucket_algs 54

# devices
device 0 osd.0 class hdd
device 1 osd.1 class hdd
device 2 osd.2 class hdd
device 3 osd.3 class hdd
device 4 osd.4 class hdd
device 5 osd.5 class hdd
device 6 osd.6 class hdd
device 7 osd.7 class hdd
device 8 osd.8 class hdd

# types
type 0 osd
type 1 host
type 2 chassis
type 3 rack
type 4 row
type 5 pdu
type 6 pod
type 7 room
type 8 datacenter
type 9 zone
type 10 region
type 11 root

# buckets
host community-ceph13-1 {
id -3 # do not change unnecessarily
id -4 class hdd # do not change unnecessarily
# weight 0.144
alg straw2
hash 0 # rjenkins1
item osd.0 weight 0.048
item osd.3 weight 0.048
item osd.6 weight 0.048
}
host community-ceph13-2 {
id -5 # do not change unnecessarily
id -6 class hdd # do not change unnecessarily
# weight 0.144
alg straw2
hash 0 # rjenkins1
item osd.1 weight 0.048
item osd.4 weight 0.048
item osd.8 weight 0.048
}
host community-ceph13-3 {
id -7 # do not change unnecessarily
id -8 class hdd # do not change unnecessarily
# weight 0.144
alg straw2
hash 0 # rjenkins1
item osd.2 weight 0.048
item osd.5 weight 0.048
item osd.7 weight 0.048
}
root default {
id -1 # do not change unnecessarily
id -2 class hdd # do not change unnecessarily
# weight 0.431
alg straw2
hash 0 # rjenkins1
item community-ceph13-1 weight 0.144
item community-ceph13-2 weight 0.144
item community-ceph13-3 weight 0.144
}

# rules
rule replicated_rule {
id 0
type replicated
min_size 1
max_size 10
step take default
step chooseleaf firstn 0 type host
step emit
}

# end crush map

Advanced configuration

当在设置devices需要更精细的控制OSD时,非常有用。它需要已存在的volume groups和logical volumes设置(ceph-volume不会创建这些卷)。

要使用此配置,必须使用logical volumes和volume groups填充lvm_volumes选项。此外,分区的绝对路径可用于journalblock.dbblock.wal

1
2
注意
此配置使用ceph-volume lvm create来设置OSD

支持的lvm_volumes配置设置:

  • data:logical volume名称或raw device(原始设备)的绝对路径(使用 100% 的原始设备创建 LV)

  • data_vg:volume group名称,如果data是logical volume,则为必需。

  • crush_device_class:生成OSD的CRUSH device class名,允许为每个OSD设置device class,而不像全局crush_device_class那样为所有OSD设置它们。

1
2
注意
如果在使用devices时为OSD设置crush_device_class,则必须使用全局crush_device_class选项设置它,如上所示。 当使用像lvm_volumes这样的devices时,无法为每个OSD定义特定的CRUSH device class。

filestore objectstore变量:

  • journal:logical volume名称或分区的绝对路径。
  • journal_vg:volume group名称,如果journal是logical volume,则是必选。
1
2
警告
每个entry(条目)必须是唯一的,不允许重复的值

bluestore objectstore变量:

  • db: logical volume名称或分区的绝对路径。
  • db_vg: volume group名称,如果db是logical volume,则是必选。
  • wal: logical volume名称或分区的绝对路径。
  • wal_vg: volume group名称,如果wal是logical volume,则是必选。
1
2
注意
这些bluestore变量是可选的优化选项。 Bluestore的db和wal只会从更快的设备中受益。可以使用单个raw device(原始设备)创建bluestore OSD。
1
2
警告
每个entry(条目)必须是唯一的,不允许重复的值

使用 raw devices(原始设备)的bluestore示例:

1
2
3
4
osd_objectstore: bluestore
lvm_volumes:
- data: /dev/sda
- data: /dev/sdb
1
2
注意
在这种情况下,将使用100%的devices创建volume groups和logical volumes。

具有logical volumes的bluestore示例:

1
2
3
4
5
6
osd_objectstore: bluestore
lvm_volumes:
- data: data-lv1
data_vg: data-vg1
- data: data-lv2
data_vg: data-vg2
1
2
注意
必须存在Volume groups和logical volumes。

定义waldblogical volumes的bluestore示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
osd_objectstore: bluestore
lvm_volumes:
- data: data-lv1
data_vg: data-vg1
db: db-lv1
db_vg: db-vg1
wal: wal-lv1
wal_vg: wal-vg1
- data: data-lv2
data_vg: data-vg2
db: db-lv2
db_vg: db-vg2
wal: wal-lv2
wal_vg: wal-vg2
1
2
注意
必须存在volume groups和logical volumes。

具有logical volumes的filestore示例:

1
2
3
4
5
6
7
8
9
10
osd_objectstore: filestore
lvm_volumes:
- data: data-lv1
data_vg: data-vg1
journal: journal-lv1
journal_vg: journal-vg1
- data: data-lv2
data_vg: data-vg2
journal: journal-lv2
journal_vg: journal-vg2
1
2
注意
必须存在volume groups和logical volumes。

Contribution

有关如何为ceph-ansible做出贡献的指导,请参阅以下部分。

Testing

用于编写 ceph-ansible 功能测试方案的文档。

Demos

Vagrant Demo

在裸机上从头开始部署:https://youtu.be/E8-96NamLDo

Bare metal demo

在裸机上从头开始部署:https://youtu.be/dv_PEp9qAqg

ansible不配置ssh免密钥,使用密码登录

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
1、编辑/etc/ansible/ansible.cfg
取消注释:#host_key_checking = False

2、编辑/etc/ansible/hosts
[ceph_exporter]
10.121.136.110 ansible_user=root ansible_ssh_pass=root
10.121.136.111 ansible_user=root ansible_ssh_pass=root
10.121.136.112 ansible_user=root ansible_ssh_pass=root
10.121.136.113 ansible_user=root ansible_ssh_pass=root
10.121.136.114 ansible_user=root ansible_ssh_pass=root
10.121.136.115 ansible_user=root ansible_ssh_pass=root

[node_exporter]
10.121.136.110 ansible_user=root ansible_ssh_pass=root
10.121.136.111 ansible_user=root ansible_ssh_pass=root
10.121.136.112 ansible_user=root ansible_ssh_pass=root
10.121.136.113 ansible_user=root ansible_ssh_pass=root
10.121.136.114 ansible_user=root ansible_ssh_pass=root
10.121.136.115 ansible_user=root ansible_ssh_pass=root

3、测试
ansible all -m ping

清除集群中的LVM

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
[root@dev yujiang]# cat remove_ceph_lvm.sh 
#!/bin/bash
set -x

DEVICE_LIST=(a b c d e f g h i j k l)
DEVICE_PATH="/dev"
DEVICE_PREFIX="sd"

VG=`ls -l /dev/ | grep ceph- | awk '{print $9}' `

for name in ${DEVICE_LIST[@]}
do
echo ${name}
done

for name in ${VG[@]}
do
LV=`ls -l ${DEVICE_PATH}/${name} | grep osd- | awk '{print $9}'`
for lv in ${LV}
do
LV_PATH=${DEVICE_PATH}/${name}/${lv}
lvremove ${LV_PATH}
done
vgremove ${DEVICE_PATH}/${name}
done

for name in ${DEVICE_LIST[@]}
do
pvremove ${DEVICE_PATH}/${DEVICE_PREFIX}${name}
done

环境准备

1
2
3
Python
Setuptools
pip(可选)

Ansible快速安装

1
2
安装pip:easy_install pip
安装Ansible:pip install ansible

Ansible源码安装

1
2
3
4
获取源码
解压源码
进入源码目录
运行source ./hacking/env-setup

Ansible系统源安装

1
2
3
4
5
6
7
Centos
- yum install ansible
Ubuntu
- apt-get install software-properties-common
- apt-add-repository ppa:ansible/ansible
- apt-get update
- apt-get install ansible

Ansible运行

1
2
      client              server
Ansible --> ssh =====> ssh --> shell

Ansible配置文件路径搜索优先级

1
2
3
4
export ANSIBLE_CONFIG
./ansible.cfg
~/.ansible.cfg
/etc/ansible/ansible.cfg

Ansible配置文件获取

1
2
/etc/ansible/目录下
https://raw.github.com/ansible/ansible/devel/examples/ansible.cfg

Ansible配置详细

1
2
3
4
5
6
defaults默认配置项
privilege_escalation执行命令的用户权限设置(ssh到客户机以哪个用户执行命令,关于这个用户的权限设置)
paramiko_connection paramika插件设置(python插件实现的ssh协议,如果不设置会走Ansible自己的ssh协议通道)
ssh_connection ssh连接设置
accelerate
selinux & colors
1
2
3
ask_pass & ask_sudo_pass
ask_pass:可以控制,Ansible剧本playbook是否会自动默认弹出密码输入框(遇到输入密码的情况下)
ask_sudo_pass:用户使用的系统平台开启了sudo密码的话,应该开启这一参数(如果目标机开启了sudo免密码的话,应该开启该项,否则报错)
1
2
gather_subset
gather_subset:设置手机的内容,包括all,network,hardware,virtual,facter,ohai
1
2
3
4
remote_port & remote_tmp & remote_user
remote_port:设置远程客户机ssh监听的端口
remote_tmp:设置远程客户机临时目录
remote_user:设置远程客户机执行命令的用户(以哪个用户执行shell)
1
2
3
4
sudo_exe & sudo_flags & sudo_user
sudo_exe:sudo命令路径(默认/usr/bin)
sudo_flags:sudo参数
sudo_user:能够使用sudo的user
1
2
3
4
5
6
7
8
action_plugins & callback_plugins & connection_plugins & filter_plugins & lookup_plugins & vars_plugins
开发者中心的插件相关功能,开发者可以开发相应的插件,来完成自己的功能。
action_plugins:激活事件(在某个事件发生的时候,去执行插件中的内容)
callback_plugins:回调
connection_plugins:连接
filter_plugins:过滤器
lookup_plugins:加载路径
vars_plugins:任何地方加载
1
2
forks
forks:最大开辟的进程数,这个数不宜过大,过大性能损耗高,不易过小,过小并发性能低,一般的设置方法是cpu核数*2
1
2
module_name
module_name:这个是/usr/bin/ansible的默认模块名(-m)。默认是'command'模块。之前提到过,command模块不支持shell变量,管道,配额。所以也许你希望把这个参数改为'shell'。
1
2
3
4
vault_password_file
vault_password_file:这个文件也可以是脚本的形式。如果你使用脚本而不是单纯文件的话,请确保它可以执行并且密码可以在标准输出上打印出来。如果你的脚本需要提示请求数据,请求将会发到标准错误输出中。

存放远程客户机密码的文件,因为有时候sudo是需要输入密码的,而我们希望Ansible执行比较流畅(不需要人工干预),这个时候可以通过机器代填密码的方式。这个文件可以是个脚本,也可以是单独的一条密码。如果是脚本,确保该脚本是可运行的,并且运行的,结果输出到标准输出中stdout。
1
2
pattern
pattern:如果没有提供"hosts"节点,这是playbook要通信的默认主机组。默认值是对所有主机通信,如果不想被惊吓到,最好还是设置这个选项
1
2
3
inventory & library
inventory:可通信主机的目录(默认/etc/ansible/hosts)
library:Ansible默认搜索模块路径(默认/usr/share/my_modules/)

新手上路

如何添加一台机器?

1
2
3
4
1、编辑/etc/ansible/hosts
2、添加本机的public SSH key到目标机器的authorized_keys
3、添加本机的私钥到Ansible
4、运行ansible all -m ping测试是否添加成功

Ansible命令格式——ansible all -m ping

1
2
3
4
1、ansible命令主体 —— ansible/ansible-playbook
2、被操作的目标机器的正则表达式 —— all
3、指定要使用的模块 —— -m ping
4、传入的参数( ansible all -a 'ls' )

执行ping模块发生了什么?

1
唤起Ansible --> 查询hosts,获取指定的目标机器 --> 调用指定模块 --> 传入参数 --> 返回执行结果

Ansible命令详解

1
2
3
4
5
6
7
-a 指定传入模块的参数
-C -D 两个一起使用,检查hosts规则文件的修改
-l 限制匹配规则的主机数
--list-hosts 显示所有匹配规则的主机数
-m -M 指定所使用的模块和模块的路径
--syntax-check 检查语法
-v 显示详细的日志
1
2
ansible all -a 'ls'
ansible all -a 'ls' --list-hosts

Ansible——Inventory(分组)

什么是Inventory?

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
Ansible可同时操作属于一个组的多台主机,组和主机之间的关系通过inventory文件配置。默认的文件路径为/etc/ansible/hosts
中文:库存、清单
作用:分组

一个简单的实例
one.example.com
[webservers]
two.example.com
three.example.com
方括号[]中是组名,一个主机可以属于不同的组,比如一台服务器可以同时属于webserver组和vim组。这时,指定webserver或者vim组,都可以操作这台主机。

ansible webservers -a 'ls'
ansible <IP> -a 'ls'

如何自定义连接端口?
在编写hosts文件时,在域名或者ip后加上端口号,例如:
192.168.100.101:5000
one.example.com:6000

IP域名写起来太长?起个别名吧
jumper ansible_ssh_port=5555 ansible_ssh_host=192.168.1.50

不想以root用户登录
例如:
jumper ansible_ssh_port=5555 ansible_ssh_host=192.168.1.50 ansible_ssh_user=papa

机器太多,但是连续的,写起来好麻烦
[vim]
vim[1:50].example.com
vim[a-f].example.com

Inventory参数选项
ansible_ssh_host
ansible_ssh_port
ansible_ssh_user
ansible_ssh_pass ssh密码(非公钥免密方式)
ansible_sudo_pass sudo密码
ansible_sudo_exe
ansible_connection 与主机的连接类型。比如:local,ssh或者paramiko。
ansible_ssh_private_key_file 私钥文件
ansible_shell_type 目标系统的shell类型
ansible_python_interpreter

分文件管理

1
2
3
4
5
6
7
8
9
分文件 —— 例如:
/etc/ansible/group_vars/vim (一组)
/etc/ansible/group_vars/webservers (一组)
/etc/ansible/host_vars/foosball (不分组)
vim文件中的内容大致这样:
---
ntp_server:acme.example.org
database_server:storage.example.org
这时候文件名就是组名

分文件夹管理

1
2
3
4
5
6
7
8
9
分文件 —— 例如:
/etc/ansible/group_vars/vim/install
/etc/ansible/group_vars/vim/init
/etc/ansible/host_vars/foosball
install文件中的内容大致这样:
---
ntp_server:acme.example.org
database_server:storage.example.org
这时候文件夹名就是组名

Ansible——Patterns

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
什么是Patterns?
在Ansible中,Patterns是指我们通过类正则表达式的方式,决定与哪台主机进行交互

1、所有hosts机器:all或者星号(*)
例如:
ansible all -m ping
2、通过域名或者IP指定一台特定的机器
例如:
ansible one.example.com -m ping
ansible 192.168.1.2 -m ping
3、指定一组连续机器
例如:
ansible 192.168.1.* -m ping 指定192.168.1.0/24段的所有机器
4、指定一组不相关的机器
例如:
ansible one.example.com:two.example.com -m ping 指定one two两台机器
5、组也支持Patterns
webservers -- 指定webserver组
webservers:nginx -- 指定webservers和nginx两个组
6、与和非
webservers:!phoenix -- 指定在webserver组但不在phoenix组
webservers:&nginx -- 指定同时在webservers和nginx组

问题:webservers:nginx:&vim:!python:!mysql
如上的语句是什么意思?
温馨提示:匹配时从左到右依次匹配!

Ansible——Ad-Hoc

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
什么是Ad-Hoc
这其实是一个概念性的名字,是相对于写Ansible playbook来说的。类似于在命令行敲入shell命令和写shell scripts两者之间的关系
如果我们敲入一些命令去比较快的完成一些事情,而不需要将这些执行的命令保存下来,这样的命令就叫做ad-hoc命令。

执行shell命令:
ansible atlanta -a "/sbin/reboot" -f 10
这个命令中,atlanta是一个组,这个组里面有很多服务器,"/sbin/reboot"命令会在atlanta组下的所有机器上执行。这里ssh-agent会fork出10个子进程(bash)以并行的方式执行reboot命令。如前所说"每次重启10个"即是以这种方式实现。

指定用户执行shell命令:
ansible atlanta -a "/usr/bin/foo" -u username
使用sudo:
ansible atlanta -a "/usr/bin/foo" -u username --sudo [--ask-sudo-pass]

文件管理:
创建文件夹:ansible webservers -m file -a "dest=/path/to/c mode=755 owner=mdehaan group=mdehaan state=directory"
拷贝文件:ansible atlanta -m copy -a "src=/etc/hosts dest=/tmp/hosts"

软件包管理:
确认一个软件包已经安装,但不去升级它:ansible webservers -m yum -a "name=acme state=present"
确认一个软件包的安装版本:ansible webservers -m yum -a "name=acme-1.5 state=present"
确认一个软件包还没有安装:ansible webservers -m yum -a "name=acme state=absent"

其他模块
git模块:git相关
service模块:系统服务相关
setup模块:系统环境相关

如何执行一个耗时的任务

1
2
3
4
5
6
7
ansible all -B 3600 -P 0 -a "/usr/bin/long_running_operation --do-stuff"
-B 1800 表示最多运行60分钟,-P 0表示不获取状态

ansible all -B 1800 -P 60 -a "/usr/bin/long_running_operation --do-stuff"
-B 1800表示最多运行30分钟,-P 60表示每隔一分钟获取一次状态

ansible web1.example.com -m async_status -a "jid=488359678239.2844"

Ansible——Playbook简介

什么是playbook?

1
2
3
简单来说,playbook是一种简单的配置管理系统与多机器部署系统的基础。与现有的其他系统有不同之处,且非常适合于复杂应用的部署。

playbook可用于声明配置,更强大的地方在于,在playbooks中可以编排有序的执行过程,甚至于做到在多组机器间,来回有序的执行特别指定的步骤。并且可以同步或异步的发起任务。

Ansible API

API提供了哪些功能?

1
2
3
1、调用Ansible的模块
2、开发动态的Inventory数据源
3、更好的控制playbook等功能的运行

如何调用Ansible模块?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
1、引入Ansible runner库
2、初始化runner对象,传入相关参数
3、运行runner对象的run函数

示例代码(Ansible2.0之前):
import ansible.runner

runner = ansible.runner.Runner(
module_name='ping',
module_args='',
pattern='web*',
forks=10
)

datastructrue = runner.run()

Directory Layout 目录布局

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

production # inventory file for production servers(生产服务器的inventory文件)
staging # inventory file for staging environment(临时环境的inventory文件)

group_vars/
group1.yml # here we assign variables to particular groups(将变量分配给特定的groups)
group2.yml
host_vars/
hostname1.yml # here we assign variables to particular systems(将变量分配给特定systems)
hostname2.yml

library/ # if any custom modules, put them here (可选)(放置自定义modules)
module_utils/ # if any custom module_utils to support modules, put them here (可选)(放置支持modules的自定义module_utils)
filter_plugins/ # if any custom filter plugins, put them here (可选)(放置自定义filter plugins)

site.yml # master playbook(playbook入口)
webservers.yml # playbook for webserver tier(webserver层playbook)
dbservers.yml # playbook for dbserver tier(dbserver层playbook)

roles/
common/ # this hierarchy represents a "role"(这个层次代表role)
tasks/ #
main.yml # <-- tasks file can include smaller files if warranted(tasks文件)
handlers/ #
main.yml # <-- handlers file(处理程序文件)
templates/ # <-- files for use with the template resource(用于模板资源的文件)
ntp.conf.j2 # <------- templates end in .j2(模板以.j2结尾)
files/ #
bar.txt # <-- files for use with the copy resource(用于复制资源的文件)
foo.sh # <-- script files for use with the script resource(用于脚本资源的脚本文件)
vars/ #
main.yml # <-- variables associated with this role(与此role关联的变量)
defaults/ #
main.yml # <-- default lower priority variables for this role(此role的默认优先级较低的变量)
meta/ #
main.yml # <-- role dependencies(role依赖)
library/ # roles can also include custom modules(role还可以包括自定义modules)
module_utils/ # roles can also include custom module_utils(role还可以包括自定义module_utils)
lookup_plugins/ # or other types of plugins, like lookup in this case(或其他类型的plugins,例如lookup)

webtier/ # same kind of structure as "common" was above, done for the webtier role(与上面的"common"相同的结构,为webtier role定义)
monitoring/ # ""
fooapp/ # ""

常用操作

查看环境变量

1
ansible-config dump

课程地址

https://www.imooc.com/video/15236

原文:http://www.10tiao.com/html/489/201702/2247483836/1.html

1
2
3
4
5
6
7
$mkdir -p $GOPATH/src/golang.org/x/
$cd $GOPATH/src/golang.org/x/
$git clone https://github.com/golang/net.git net
$go install net
或者
$git clone https://github.com/golang/text.git $GOPATH/src/golang.org/x/text
$git clone https://github.com/golang/net.git $GOPATH/src/golang.org/x/net

go get 获取第三方库

  • go get命令演示
  • 使用gopm来获取无法下载的包
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
yujiangdeMBP-13:~ yujiang$ go get -v github.com/gpmgo/gopm

yujiangdeMBP-13:~ yujiang$ cat ~/.bashrc
export PATH=$PATH:/home/go/bin:/root/go/bin
export GOPATH="/root/go"
yujiangdeMBP-13:~ yujiang$ source ~/.bashrc

yujiangdeMBP-13:~ yujiang$ gopm get -g -v golang.org/x/tools/cmd/goimports
yujiangdeMBP-13:~ yujiang$ ls go/src/golang.org/x/tools/imports/
fix.go fix_test.go imports.go mkindex.go mkstdlib.go sortimports.go zstdlib.go
# 编译出goimports
yujiangdeMBP-13:~ yujiang$ go build golang.org/x/tools/cmd/goimports
# 编译并安装到$GOPATH/bin/目录下
yujiangdeMBP-13:~ yujiang$ go install golang.org/x/tools/cmd/goimports


go get -v github.com/golang/tools/go/...
go get -v github.com/golang/tools/...

go get -u golang.org/x/tools/...
  • go build编译
  • go install产生pkg文件和可执行文件
  • go run直接编译运行

centos install

安装文档

1
2
https://pkg.jenkins.io/redhat-stable/
https://www.vultr.com/docs/how-to-install-jenkins-on-centos-7

启动jenkins

1
2
systemctl start jenkins.service
systemctl enable jenkins.service

中文插件

1
Locale plugin

多任务插件

1
Multijob plugin

这是E.S.R.Labs Repo —— 就像Google Repo,但它也可以在Microsoft Windows运行。Repo是Google建立在Git之上的repository管理工具。必要时,Repo会统一许多Git repositories上传到版本控制系统,并使部分开发工作流程自动化。Repo并不意味着取代Git,只是为了更容易在多个repositories的环境中使用Git。repo command是一个可执行的Python脚本,您可以将其放在任何路径。在处理源文件时,您将使用Repo进行跨网络操作。例如,使用Repo命令,可以将多个repositories中的文件下载到本地工作目录中。

Setup steps for Microsoft Windows

修复权限以允许创建符号链接

如果您是Administrators group的member,则必须关闭User Access Control (UAC),然后重新启动计算机。

否则,您必须调整您的用户权限才能获得SeCreateSymbolicLinkPrivilege权限。editrights工具是作为Microsoft Windows的git-repo的一部分提供的。

Highly experimental(除开发此功能外,请勿使用!):如果您不想使用符号链接,而是文件夹和文件的硬链接(hardlinks),则必须在~/.gitconfig中设置以下内容:

1
2
[portable]
windowsNoSymlinks = true

这不需要上述所说的设置权限。

已知问题:硬链接被git销毁,例如,当你删除一个branch时(breaks .git/config)。这会破坏project workspace!

Download and install Git

下载Git(http://git-scm.com/downloads)

将Git添加到path环境变量中:例如C:\Program Files (x86)\Git\cmd;

将MinGW添加到path环境变量中:例如C:\Program Files (x86)\Git\bin;

Download and install Python

下载Python 2.7+(https://www.python.org/downloads/)

将Python添加到path环境变量中:例如C:\Python27;

注意:git-repo在实验环境支持Python 3.x

使用Windows Command Shell或Git Bash下载并安装Repo

Windows Command Shell

1
2
3
md %USERPROFILE%\bin
curl https://raw.githubusercontent.com/esrlabs/git-repo/stable/repo > %USERPROFILE%/bin/repo
curl https://raw.githubusercontent.com/esrlabs/git-repo/stable/repo.cmd > %USERPROFILE%/bin/repo.cmd

Windows PowerShell

1
2
3
md $env:USERPROFILE\bin
curl https://raw.githubusercontent.com/esrlabs/git-repo/stable/repo > $env:USERPROFILE/bin/repo
curl https://raw.githubusercontent.com/esrlabs/git-repo/stable/repo.cmd > $env:USERPROFILE/bin/repo.cmd

Git Bash

1
2
3
mkdir ~/bin
curl https://raw.githubusercontent.com/esrlabs/git-repo/stable/repo > ~/bin/repo
curl https://raw.githubusercontent.com/esrlabs/git-repo/stable/repo.cmd > ~/bin/repo.cmd

将Repo添加path环境变量:%USERPROFILE%\bin;

创建一个指向%USERPROFILE%的HOME环境变量(OpenSSH需要找到它的.ssh目录)。

创建一个GIT_EDITOR环境变量,其中包含一个editor可执行文件作为值。为此,首先将editor可执行文件的主目录添加到path环境变量中。例如,GIT_EDITOR可以设置为”notepad++.exe”,”gvim.exe”。

Setup steps for Linux

下载并安装Git和Python

1
2
sudo apt-get install git-core
sudo apt-get install python

下载并安装Repo

1
2
3
4
$ mkdir ~/bin
$ PATH=~/bin:$PATH
$ curl https://raw.githubusercontent.com/esrlabs/git-repo/stable/repo > ~/bin/repo
$ chmod a+x ~/bin/repo

用法

有关git-repo用法的更多详细说明,请访问git-repo。

常见问题解答

  • 我无法看到repo状态的任何颜色

用于repo状态的pager默认设置为less,除非另外配置,否则将忽略转义序列。您可以将环境变量LESS设置为-FRSX以减少处理颜色。 (您可能还想将LESSCHARSET设置为utf-8)

它仍然不起作用!

对pager有更多的选择。它的行为并不像less一样,但它对你来说可能已经足够了。

1
git config --global core.pager more

或者,环境变量GIT_PAGER可以设置为more。

  • 在使用repo init初始化我的repo时,我在Windows Command Shell中遇到WindowsError

如果在输出开始时出现警告,表示GPG不可用

1
2
warning: gpg (GnuPG) is not available.
warning: Installing it is strongly encouraged.

你必须添加gpg.exe到你的PATH变量。可执行文件可以在Git安装文件夹$GIT\usr\bin中找到。当你使用Git Bash时,$Git\usr\bin文件夹已经被添加到你的PATH中。

Developer Information

与official google repo同步

为了与official google repo git同步,这里是与official google repo的tag v1.12.33同步的命令:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# add google git-repo remote with tag
git remote add googlesource https://android.googlesource.com/tools/repo/
git checkout v1.12.33 -b google-latest

# checkout basis for resync
git checkout google-git-repo-base -b update
git merge --allow-unrelated-histories -Xtheirs --squash google-latest
git commit -m "Update: google git-repo v1.12.33"
git rebase stable

# solve conflicts; keep portability in mind

git checkout stable
git rebase update

# cleanup
git branch -D update
git branch -D google-latest

创建一个新的签名版本

用于创建新版本repo的命令:

1
2
3
git tag -s -u KEYID v0.4.16 -m "COMMENT"
git push origin stable:stable
git push origin v0.4.16

替换KEYID(类似0x ..)

v0.4.16(两次)

用更多的解释替换COMMENT

LTP测试可以用C或Shell脚本编写。

Getting Started

Git-clone主LTP repository,如自述文件中所述, 并更改目录到checked-out的Git repository。我们建议安装LTP并运行Quick guide(在自述文件中)中提到的测试之一,以确保您从良好的状态开始。我们还建议克隆Linux kernel repository以供参考,本指南将涉及主线kernel 4.12内的文件和目录。

1
$ git clone git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git

还有许多其他的repositories可以参考,包括GNU C library glibc和可选的C library musl。一些system calls被部分或完全实现在user land作为标准C library的一部分。所以在这些情况下,C library是一个重要的参考。glibc是Linux最常用的C library,然而musl通常更容易理解。

实现system calls的方式因体系结构,以及内核版本和C library版本而异。要找出system calls是否真的在任何机器上访问内核,可以使用strace。这会拦截system calls并打印它们。我们将在后面的教程中使用它。

Choose a System Call to test

我们将使用statx() system call来提供测试的具体示例。在撰写本文时,没有测试Linux内核版本4.11中的system call。Linux system call特定的测试主要包含在testcases/kernel/syscalls目录,但你也可以grep整个LTP repository以检查任何现有system call的用法。

找到当前未被LTP测试的system call的方法是在内核树中查看include/linux/syscalls.h。

Find an untested System call

尝试找到一个未经测试的系统调用,它有一个手册页(即man syscall产生一个结果)。Git-clone最新的kernel man-pages repository是一个好主意。

1
$ git clone git://git.kernel.org/pub/scm/docs/man-pages/man-pages.git

在写这篇文章时,最新的man-pages release和repository HEAD之间的差异超过了100次commits。这代表了大约9周的变化。如果你使用的是稳定的Linux发行版,那么你的man-pages package可能已经有几年了。就像kernel一样,最好有Git repository作为参考。

Create the test skeleton

我将调用我的测试statx01.c,在你读这个文件名的时候,可能会采用这个文件名,所以可以根据需要增加文件名中的数字,或者用练习2.1中选择的system call替换statx。(怕被占用)

1
2
3
$ mkdir testcases/kernel/syscalls/statx
$ cd testcases/kernel/syscalls/statx
$ echo statx >> .gitignore

接下来打开statx01.c并添加如下。确保将right notice更改为您的name/company,如有必要,更正test name和最低kernel version。我将在下面解释代码的作用。

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
/*
* Copyright (c) 2017 Instruction Ignorer <"can't"@be.bothered.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

/*
* Test statx
*
* All tests should start with a description of _what_ we are testing.
* Non-trivial explanations of _how_ the code works should also go here.
* Include relevant links, Git commit hashes and CVE numbers.
* Inline comments should be avoided.
*/

#include "tst_test.h"

static void run(void)
{
tst_res(TPASS, "Doing hardly anything is easy");
}

static struct tst_test test = {
.test_all = run,
.min_kver = "4.11",
};

#include语句开始,我们将复制main LTP test library headers。这包括最常见的test API函数和test harness初始化代码。需要注意的是,这是一个完全普通的,独立的C程序,但缺少main(),因为它在tst_test.h中实现。

我们使用tst_test结构指定运行一部分测试代码。测试编写器可以设置各种回调,包括我们已经设置为运行()的test.test_all。test writer可以设置各种回调, 包括test.test_all,我们已经设置run()。测试工具将在一个单独的进程(使用fork())中执行此回调,如果在test.timeout秒后没有返回,则强制终止它。

原文

【1】https://github.com/linux-test-project/ltp/wiki/C-Test-Case-Tutorial

系统环境

1
2
3
4
5
LSB Version:	:core-4.1-amd64:core-4.1-noarch:cxx-4.1-amd64:cxx-4.1-noarch:desktop-4.1-amd64:desktop-4.1-noarch:languages-4.1-amd64:languages-4.1-noarch:printing-4.1-amd64:printing-4.1-noarch
Distributor ID: CentOS
Description: CentOS Linux release 7.4.1708 (Core)
Release: 7.4.1708
Codename: Core

ip

1
2
3
4
5
6
7
8
9
10
11
12
13
[root@cephL ~]# ip  -h
Usage: ip [ OPTIONS ] OBJECT { COMMAND | help }
ip [ -force ] -batch filename
where OBJECT := { link | address | addrlabel | route | rule | neigh | ntable |
tunnel | tuntap | maddress | mroute | mrule | monitor | xfrm |
netns | l2tp | macsec | tcp_metrics | token }
OPTIONS := { -V[ersion] | -s[tatistics] | -d[etails] | -r[esolve] |
-h[uman-readable] | -iec |
-f[amily] { inet | inet6 | ipx | dnet | bridge | link } |
-4 | -6 | -I | -D | -B | -0 |
-l[oops] { maximum-addr-flush-attempts } |
-o[neline] | -t[imestamp] | -ts[hort] | -b[atch] [filename] |
-rc[vbuf] [size] | -n[etns] name | -a[ll] }

获取系统上所有网络接口的信息

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
44
45
46
47
48
49
[root@cephL ~]# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: enp0s3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
link/ether 08:00:27:3a:98:1d brd ff:ff:ff:ff:ff:ff
3: enp0s8: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
link/ether 08:00:27:52:03:aa brd ff:ff:ff:ff:ff:ff
inet 192.168.56.102/24 brd 192.168.56.255 scope global dynamic enp0s8
valid_lft 945sec preferred_lft 945sec
inet6 fe80::4b2b:b766:22c:f503/64 scope link
valid_lft forever preferred_lft forever
4: enp0s9: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
link/ether 08:00:27:3e:3e:e2 brd ff:ff:ff:ff:ff:ff
5: virbr0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN qlen 1000
link/ether 52:54:00:66:bf:e6 brd ff:ff:ff:ff:ff:ff
inet 192.168.122.1/24 brd 192.168.122.255 scope global virbr0
valid_lft forever preferred_lft forever
6: virbr0-nic: <BROADCAST,MULTICAST> mtu 1500 qdisc pfifo_fast master virbr0 state DOWN qlen 1000
link/ether 52:54:00:66:bf:e6 brd ff:ff:ff:ff:ff:ff

scope解释,ip地址和路由都有一个域的概念,主要是告诉内核他们起作用的上下文。
在linux中,路由的域表明了目的网络和本机的距离。
而ip地址的域说明了这个ip地址的作用域。
在linux中一共有3种作用域,分别是HOST,LINK(对于ip地址来说说明这个地址是只在lan中使用,而对于route来说目的的地址在lan中),Universe/global(广域网的地址,对于route来说要到达这个地址肯定会多于1跳)。
要注意,域的默认值是Universe,也就是说你不显示指明,则默认都是Universe。

查看IP地址
[root@cephL ~]# ip addr show enp0s8
3: enp0s8: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
link/ether 08:00:27:52:03:aa brd ff:ff:ff:ff:ff:ff
inet 192.168.56.102/24 brd 192.168.56.255 scope global dynamic enp0s8
valid_lft 847sec preferred_lft 847sec
inet6 fe80::4b2b:b766:22c:f503/64 scope link
valid_lft forever preferred_lft forever

查看IPv6地址
[root@cephL ~]# ip -6 addr show dev enp0s8
3: enp0s8: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 state UP qlen 1000
inet6 fe80::4b2b:b766:22c:f503/64 scope link
valid_lft forever preferred_lft forever

添加IP地址
[root@cephL ~]# ip addr add 192.168.56.103/24 dev enp0s8
删除IP地址
[root@cephL ~]# ip addr del 192.168.56.103/24 dev enp0s8

路由

1
2
3
4
5
6
7
8
9
10
11
12
13
14
[root@cephL ~]# ip route show
192.168.56.0/24 dev enp0s8 proto kernel scope link src 192.168.56.102 metric 100
192.168.122.0/24 dev virbr0 proto kernel scope link src 192.168.122.1

让kernel报告路由,它会发送一个数据包到指定的地址
[root@cephL ~]# ip route get 61.135.169.125
61.135.169.125 via 10.116.21.254 dev enp0s9 src 10.116.21.135
cache
(解释:61.135.169.125是访问的地址,10.116.21.254是默认路由,10.116.21.135是enp0s9设备IP地址)

添加默认路由
[root@cephL ~]# ip route add default via 10.116.21.253 dev enp0s9
删除默认路由
[root@cephL ~]# ip route del default via 10.116.21.253 dev enp0s9

不同网络接口的统计信息

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
44
45
46
[root@cephL ~]# ip -s link
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT qlen 1
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
RX: bytes packets errors dropped overrun mcast
189813592 61558 0 0 0 0
TX: bytes packets errors dropped carrier collsns
189813592 61558 0 0 0 0
2: enp0s3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP mode DEFAULT qlen 1000
link/ether 08:00:27:3a:98:1d brd ff:ff:ff:ff:ff:ff
RX: bytes packets errors dropped overrun mcast
0 0 0 0 0 0
TX: bytes packets errors dropped carrier collsns
0 0 0 0 0 0
3: enp0s8: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP mode DEFAULT qlen 1000
link/ether 08:00:27:52:03:aa brd ff:ff:ff:ff:ff:ff
RX: bytes packets errors dropped overrun mcast
104188 1104 0 0 0 0
TX: bytes packets errors dropped carrier collsns
159594 673 0 0 0 0
4: enp0s9: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP mode DEFAULT qlen 1000
link/ether 08:00:27:3e:3e:e2 brd ff:ff:ff:ff:ff:ff
RX: bytes packets errors dropped overrun mcast
53777 574 0 0 0 0
TX: bytes packets errors dropped carrier collsns
60106 623 0 0 0 0
5: virbr0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN mode DEFAULT qlen 1000
link/ether 52:54:00:66:bf:e6 brd ff:ff:ff:ff:ff:ff
RX: bytes packets errors dropped overrun mcast
0 0 0 0 0 0
TX: bytes packets errors dropped carrier collsns
0 0 0 0 0 0
6: virbr0-nic: <BROADCAST,MULTICAST> mtu 1500 qdisc pfifo_fast master virbr0 state DOWN mode DEFAULT qlen 1000
link/ether 52:54:00:66:bf:e6 brd ff:ff:ff:ff:ff:ff
RX: bytes packets errors dropped overrun mcast
0 0 0 0 0 0
TX: bytes packets errors dropped carrier collsns
0 0 0 0 0 0

查询特定接口统计信息
[root@cephL ~]# ip -s link ls enp0s9
4: enp0s9: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP mode DEFAULT qlen 1000
link/ether 08:00:27:3e:3e:e2 brd ff:ff:ff:ff:ff:ff
RX: bytes packets errors dropped overrun mcast
54527 583 0 0 0 0
TX: bytes packets errors dropped carrier collsns
60946 633 0 0 0 0

ARP,查看接入的MAC地址

1
2
3
4
5
6
[root@cephL ~]# ip neighbour
192.168.56.1 dev enp0s8 lladdr 0a:00:27:00:00:00 DELAY
10.116.21.254 dev enp0s9 lladdr 00:00:0c:07:ac:0c DELAY
10.116.21.253 dev enp0s9 lladdr b4:de:31:c7:e7:47 STALE
192.168.56.100 dev enp0s8 lladdr 08:00:27:3e:18:34 STALE
10.116.21.252 dev enp0s9 lladdr b4:de:31:c7:d8:e7 STALE

ip工具可以连续监视devices, addresses和routes的状态。

1
2
3
4
5
6
7
[root@cephL ~]# ip monitor all
[nsid current]192.168.56.1 dev enp0s8 lladdr 0a:00:27:00:00:00 REACHABLE
[nsid current]10.116.21.254 dev enp0s9 lladdr 00:00:0c:07:ac:0c STALE
[nsid current]192.168.56.1 dev enp0s8 lladdr 0a:00:27:00:00:00 REACHABLE
[nsid current]10.116.21.254 dev enp0s9 lladdr 00:00:0c:07:ac:0c REACHABLE
[nsid current]3: enp0s8 inet 192.168.56.102/24 brd 192.168.56.255 scope global dynamic enp0s8
valid_lft 1200sec preferred_lft 1200sec

up和down网络设备

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
[root@cephL ~]# ip link set enp0s9 down 
[root@cephL ~]# ip route show
192.168.56.0/24 dev enp0s8 proto kernel scope link src 192.168.56.102 metric 100
192.168.122.0/24 dev virbr0 proto kernel scope link src 192.168.122.1
[root@cephL ~]# ping www.baidu.com
ping: www.baidu.com: 未知的名称或服务

[root@cephL ~]# ip link set enp0s9 up
[root@cephL ~]# ip route show
default via 10.116.21.254 dev enp0s9 proto static metric 100
10.116.20.0/23 dev enp0s9 proto kernel scope link src 10.116.21.135 metric 100
192.168.56.0/24 dev enp0s8 proto kernel scope link src 192.168.56.102 metric 100
192.168.122.0/24 dev virbr0 proto kernel scope link src 192.168.122.1
[root@cephL ~]# ping www.baidu.com
PING www.a.shifen.com (61.135.169.121) 56(84) bytes of data.
64 bytes from 61.135.169.121 (61.135.169.121): icmp_seq=1 ttl=50 time=4.35 ms

获取帮助信息

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
[root@cephL ~]# ip route help
Usage: ip route { list | flush } SELECTOR
ip route save SELECTOR
ip route restore
ip route showdump
ip route get ADDRESS [ from ADDRESS iif STRING ]
[ oif STRING ] [ tos TOS ]
[ mark NUMBER ]
ip route { add | del | change | append | replace } ROUTE
SELECTOR := [ root PREFIX ] [ match PREFIX ] [ exact PREFIX ]
[ table TABLE_ID ] [ proto RTPROTO ]
[ type TYPE ] [ scope SCOPE ]
ROUTE := NODE_SPEC [ INFO_SPEC ]
NODE_SPEC := [ TYPE ] PREFIX [ tos TOS ]
[ table TABLE_ID ] [ proto RTPROTO ]
[ scope SCOPE ] [ metric METRIC ]
INFO_SPEC := NH OPTIONS FLAGS [ nexthop NH ]...
NH := [ via ADDRESS ] [ dev STRING ] [ weight NUMBER ] NHFLAGS
OPTIONS := FLAGS [ mtu NUMBER ] [ advmss NUMBER ]
[ rtt TIME ] [ rttvar TIME ] [reordering NUMBER ]
[ window NUMBER ] [ cwnd NUMBER ] [ initcwnd NUMBER ]
[ ssthresh NUMBER ] [ realms REALM ] [ src ADDRESS ]
[ rto_min TIME ] [ hoplimit NUMBER ] [ initrwnd NUMBER ]
[ features FEATURES ] [ quickack BOOL ] [ congctl NAME ]
[ expires TIME ]
TYPE := { unicast | local | broadcast | multicast | throw |
unreachable | prohibit | blackhole | nat }
TABLE_ID := [ local | main | default | all | NUMBER ]
SCOPE := [ host | link | global | NUMBER ]
NHFLAGS := [ onlink | pervasive ]
RTPROTO := [ kernel | boot | static | NUMBER ]
TIME := NUMBER[s|ms]
BOOL := [1|0]
FEATURES := ecn

yum常用列表

1
yum provides  找到缺少的RPM依赖包,例如yum provides '*/dirent.h'

查看ssh登录信息

1
utmpdump /var/log/wtmp | cat

参考链接

【1】https://linux.cn/article-3144-1.html

【2】https://www.jianshu.com/p/d89cc7ecb305

【3】http://www.pagefault.info/?p=240

近距离探索memcache缓存笔记

课程地址:https://www.imooc.com/learn/527

课程教师:李虎头

memcache解析

1-1内容解析

1
2
3
1.知道什么是Memcache
2.知道在什么时候使用Memcache
3.知道怎样使用Memcache优化网站或API

1-2基础介绍

1
2
3
4
5
6
Memcache介绍
1.什么是Memcache?
分布式高速缓存系统

2.Memcache有什么用?
缓存层,前端频繁操作后端数据库时,减轻后端数据库压力,前端直接访问缓存层

1-3理解Memcache

1
只有一张表的数据库
# 名字 类型 整理
1 key varchar(255) utf8_general_ci
2 value text utf8_general_ci

1-4使用场景

1
2
3
1.非持久化存储:对数据存储要求不高
2.分布式存储:不适合单机使用
3.Key/Value存储:格式简单,不支持List、Array数据格式

memcache的安装

2-1安装前的说明

1
2
3
1.编译安装 Libevent Memcache(需要先安装Libevent依赖)
2.使用依赖管理工具yum、apt-get
-PS:Memcache和Memcached的区别(建议使用Memcached,它是Memcache的升级版)

2-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
30
31
32
33
34
35
36
37
38
39
40
1.编译安装
yum -y install automake libtool wget gcc gcc-c++ && wget https://github.com/libevent/libevent/archive/release-2.1.8-stable.tar.gz && tar zxvf release-2.1.8-stable.tar.gz && cd libevent-release-2.1.8-stable/ && ./autogen.sh && ./configure && make -j 2 && make install

wget http://www.memcached.org/files/memcached-1.5.8.tar.gz && cd memcached-1.5.8 && ./configure && make -j 2 && make install

[root@cephL memcached-1.5.8]# /usr/local/bin/memcached -h
/usr/local/bin/memcached: error while loading shared libraries: libevent-2.1.so.6: cannot open shared object file: No such file or directory
[root@cephL memcached-1.5.8]# ldd /usr/local/bin/memcached
linux-vdso.so.1 => (0x00007ffdd7d77000)
libevent-2.1.so.6 => not found
libpthread.so.0 => /lib64/libpthread.so.0 (0x00007f2d78950000)
libc.so.6 => /lib64/libc.so.6 (0x00007f2d78583000)
/lib64/ld-linux-x86-64.so.2 (0x000055b9e254c000)
[root@cephL memcached-1.5.8]# LD_DEBUG=libs /usr/local/bin/memcached -v
51494: find library=libevent-2.1.so.6 [0]; searching
51494: search cache=/etc/ld.so.cache
51494: search path=/lib64/tls/x86_64:/lib64/tls:/lib64/x86_64:/lib64:/usr/lib64/tls/x86_64:/usr/lib64/tls:/usr/lib64/x86_64:/usr/lib64 (system search path)
51494: trying file=/lib64/tls/x86_64/libevent-2.1.so.6
51494: trying file=/lib64/tls/libevent-2.1.so.6
51494: trying file=/lib64/x86_64/libevent-2.1.so.6
51494: trying file=/lib64/libevent-2.1.so.6
51494: trying file=/usr/lib64/tls/x86_64/libevent-2.1.so.6
51494: trying file=/usr/lib64/tls/libevent-2.1.so.6
51494: trying file=/usr/lib64/x86_64/libevent-2.1.so.6
51494: trying file=/usr/lib64/libevent-2.1.so.6
51494:
/usr/local/bin/memcached: error while loading shared libraries: libevent-2.1.so.6: cannot open shared object file: No such file or directory
[root@cephL memcached-1.5.8]# ll /usr/local/lib/libevent-2.1.so.6
lrwxrwxrwx. 1 root root 21 5月 29 18:48 /usr/local/lib/libevent-2.1.so.6 -> libevent-2.1.so.6.0.2
[root@cephL memcached-1.5.8]# ln -s /usr/local/lib/libevent-2.1.so.6 /usr/lib64/libevent-2.1.so.6
[root@cephL memcached-1.5.8]# /usr/local/bin/memcached -d -l 127.0.0.1 -p 11211 -m 150 -u root
[root@cephL memcached-1.5.8]# ps -ef | grep memcache
root 51810 1 0 19:04 ? 00:00:00 /usr/local/bin/memcached -d -l 127.0.0.1 -p 11211 -m 150 -u root

2.使用yum安装
[root@cephL memcache]# yum install memcached
[root@cephL memcache]# /usr/bin/memcached -d -l 127.0.0.1 -p 11211 -m 150 -u root

[root@cephL memcache]# ps -ef | grep memcache
root 40789 1 0 18:34 ? 00:00:00 /usr/bin/memcached -d -l 127.0.0.1 -p 11211 -m 150 -u root

2-3客户端的安装

1
2
3
4
5
1.安装libmemcached
wget https://launchpad.net/libmemcached/1.0/1.0.18/+download/libmemcached-1.0.18.tar.gz
tar zxvf libmemcached-1.0.18.tar.gz && cd libmemcached-1.0.18
./configure --prefix=/usr/lib/libmemcached
make && make install

最近学习Ceph Erasure code,查阅了网络上有许多资料。Erasure code的概念与理论相对成熟,但目前在Ceph中实现与应用上有诸多困难。所以这里只对Ceph Erasure code应用场景做比较。

使用Erasure code的目的是为了节省存储空间(以牺牲计算资源换取存储资源)。

bluestore OSD

在luminous版本之前,只适用于像RGW那样的应用场景(full object writes and appends),不支持partial writes。

(1)用法一

在luminous版本,为了适用于RBD和CephFS的场景,增加了partial writes功能,但是只有在bluestore OSD上可以启用。

Erasure coded pools不支持omap,因此要将它们与RBD和CephFS一起使用,必须明确指示它们将data存储在ec pool中,将metadata存储在replicated pool中。

对于CephFS,在创建file system时通过file layouts设定一个erasure coded pool作为默认的data pool。

(2)用法二

在erasure coded pool之前设置一个cache tier。

filestore OSD

(1)用法一

Erasure coded pools需要比replicated pools更多的资源,并且缺少一些功能,如omap。为了克服这些限制,可以在erasure coded pool之前设置一个cache tier。

由于使用cache tier并且与Erasure coded相关联,那么Erasure coded的性能同时与cache tier特性相关。这是一个纠结的问题!

Ceph Cache Tiering

如上图,cache tier为客户端读取存储在后端的数据子集提供更好的I/O性能。在创建pool时,Cache Tier层pool作为Storage Tier层pool的缓存。 Ceph objecter handles 负责处理objects放置位置。 tiering agent 决定何时将缓存中的objects刷新到后端存储层。所以cache tier和后端存储层对Ceph clients来说是完全透明的。

但是,管理员可以配置此迁移的发生方式。 主要有两种情况:

Writeback Mode:

当管理员以writeback mode配置tiers时,Ceph clients将数据写入缓存层并从缓存层接收ACK。经过一段时间后,写入缓存层的数据将迁移到存储层,并从缓存层中清除。从概念上讲,缓存层被覆盖在后端存储层的“前面”。当Ceph client需要驻留在存储层中的数据时,cache tiering agent会在读取数据时将数据迁移到缓存层,然后将其发送到Ceph client。此后,Ceph client可以使用缓存层执行I/O,直到数据变为非活动状态。这对于易变数据(例如照片/视频编辑,交易数据等)是理想的。

Read-proxy Mode:

此模式将使用已存在于缓存层中的任何objects,但如果缓存中没有objects,则将请求代理到存储层。这对于从writeback mode转换为禁用缓存非常有用,因为它允许负载在缓存耗尽时正常运行,而无需向缓存中添加任何新objects。

cache tier所有迁移模式:

官方文档明确指出:

A WORD OF CAUTION

Cache tiering会降低大多数workloads的性能。用户在使用此功能之前应特别小心。

Workload dependent:

缓存是否会提高性能,高度依赖于负载。由于将objects移入或移出缓存会产生额外成本,因此只有在数据集中访问存在较大偏差时才会生效,这样大多数请求才会命中少量objects。缓存池应该大到足以捕获你的负载,以避免抖动。

Difficult to benchmark:

使用cache tiering,用户常规衡量性能的基准测试将显得很糟糕,部分原因是由于很少有人将请求集中在一小部分objects上,所以缓存“预热”可能需要很长时间,同时预热可能带来更高的成本。

Usually slower:

对于缓存分层不友好的负载,性能通常比没有设置cache tiering enabled的普通RADOS pool慢。

librados object enumeration:

在这种情况下,librados级别的object enumeration API并不一致。如果您的应用程序直接使用librados并依赖于object enumeration,则缓存分层可能无法按预期工作。

Complexity:

启用缓存分层会带来额外的复杂性。这会增加其他用户尚未遇到的错误的可能性,并且会使您的部署处于更高级别的风险中。

KNOWN GOOD WORKLOADS

RGW time-skewed:

如果RGW负载几乎所有读取操作都针对最近写入的objects,可配置为一段时间后,将最近写入的对象从缓存层迁移到存储层,这种场景可以很好地工作。

KNOWN BAD WORKLOADS

已知下列配置对cache tiering效果不佳。

RBD with replicated cache and erasure-coded base:

这是一个常见的要求,但通常表现不佳。即使合理偏差的负载仍然会向cold objects发送一些small writes操作,由于erasure-coded pool尚不支持small writes操作,因此必须将整个(通常为4 MB)objects迁移到缓存中以满足small write(通常为4 KB)。只有少数用户成功部署了此配置,并且仅适用于他们,因为他们的数据extremely cold(备份)并且对性能没有任何要求。

RBD with replicated cache and base:

具有replicated base tier(存储层)的RBD效果要好于erasure coded base tier(存储层)时的RBD,但它仍高度依赖于负载中的偏差量,而且很难验证。用户需要很好地理解他们的负载,并需要调整缓存分层参数。

总结

1、 架构角度,如果想用Ceph Erasure code,推荐使用bluestore OSD,而不推荐filestore OSD。

抛开bluestore的稳定性不谈(待验证),filestore OSD的Ceph Erasure code依赖Ceph Cache Tiering会带来额外的复杂性,并且限制了应用场景。

摘自李运华:

组件越多,就越有可能其中某个组件出现故障,从而导致系统故障。这个概率可以算出来,假设组件的故障率是10%(有10%的时间不可用),那么有1个组件的系统可用性是(1-10%)=90%,有2个组件的系统的可用性是(1-10%)*(1-10%)=81%,两者的可用性相差9%。

2、如果使用filestore OSD的Ceph Erasure code,推荐应用在RGW time-skewed场景(官方推荐)。而Ceph Cache Tiering据生产环境落地还有一定距离。

3、近来很多公司都在搞云计算、搞研发,有些是自主研发而有些是基于开源定制开发。如果是基于开源,根据之前的经验,代码直接提交到社区根据社区的发布流程会省去很多额外的工作。

自主研发版本控制是痛苦的,需要考虑社区base更新,自主研发的代码移植到社区最新base(查分代码到吐。。。),如果社区框架变动大,还需要调试改代码。如果是聪明的开发会找到一条扩展的路,尽量更改原有逻辑,如果更改原有逻辑,对测试来说是个很大的挑战。

4、对于产品化一个开源项目,如ceph,还是寻找一个稳定的方案,然后再搞研发,至少研发失败还给自己留条后路,因为你背后有一个强大的社区团队。

附录

中文文档,如看不懂请看英语原文

https://lnsyyj.github.io/2018/05/12/CEPH-ERASURE-CODE/

https://lnsyyj.github.io/2018/05/12/CACHE-TIERING/

https://lnsyyj.github.io/2018/05/15/ERASURE-CODE-PROFILES/

https://lnsyyj.github.io/2018/05/16/JERASURE-ERASURE-CODE-PLUGIN/

https://lnsyyj.github.io/2018/05/16/ISA-ERASURE-CODE-PLUGIN/

https://lnsyyj.github.io/2018/05/17/LOCALLY-REPAIRABLE-ERASURE-CODE-PLUGIN/

https://lnsyyj.github.io/2018/05/18/SHEC-ERASURE-CODE-PLUGIN/