0%

所有Ceph集群都至少需要一个monitor,并且至少需要与群集上存储的对象的副本一样多的OSD。 Bootstrapping the initial monitor(s) 是部署Ceph存储集群的第一步。Monitor部署还为整个群集设置了重要的标准,例如池副本的数量,每个OSD的placement groups数量,心跳间隔,是否需要身份验证等。大多数这些值是默认设置的,因此在生产环境设置集群时了解这些值是有用的。

按照与Installation (Quick)http://docs.ceph.com/docs/master/start/相同的配置,我们将建立一个集群,node1为monitor节点,node2和node3为OSD节点。

MONITOR BOOTSTRAPPING

Bootstrapping a monitor(Ceph存储集群,理论上)需要一些东西:

  • Unique Identifier: fsid是集群的唯一标识符,当Ceph存储集群主要用于Ceph Filesystem时,代表从日期生成的File System ID
  • Cluster Name: Ceph集群有一个集群名称,这是一个没有空格的简单字符串。默认群集名称是ceph,但是您可以指定不同的群集名称。当您使用多个群集时,您需要清楚地了解您正在使用哪个群集,这时覆盖默认的集群名称特别有用。例如,当您在federated architecture中运行多个群集时,群集名称(例如,us-west,us-east)标识当前CLI会话的群集。注:要在命令行接口上标识集群名称,请指定具有群集名称的Ceph配置文件(例如,ceph.conf,us-west.conf,us-east.conf等)。另请参阅CLI使用(ceph –cluster {cluster-name})。
  • Monitor Name: 群集中的每个monitor实例都有唯一的名称。通常情况下,Ceph Monitor名称是主机名(我们推荐每个单独的主机使用一个Ceph Monitor,Ceph OSD Daemons不能混合部署Ceph Monitors)。您可以通过hostname -s检索short hostname。
  • Monitor Map: Bootstrapping the initial monitor(s)需要您生成一个monitor map。monitor map需要fsid,群集名称(或使用默认值)以及至少一个主机名和它的IP地址。
  • Monitor Keyring: Monitors通过secret key相互通信。当bootstrapping the initial monitor(s)时,您必须生成一个带有monitor secret的keyring并提供它。
  • Administrator Keyring: 要使用ceph CLI工具,你必须有一个client.admin user。因此,您必须生成admin user和keyring,并且还必须将client.admin user添加到monitor keyring中。

上述要求并不意味着一个Ceph配置文件的建立。但是,作为最佳做法,我们建议创建一个Ceph配置文件并使用fsid,mon initial members和mon host配置填充它。

您也可以在运行时获取并设置所有的monitor settings。但是,Ceph配置文件可能只包含那些覆盖默认值的settings。将settings添加到Ceph配置文件时,这些settings会覆盖默认settings。在Ceph配置文件中维护这些settings可以更容易地维护集群。

步骤如下:

1、登录到initial monitor node(s):

ssh {hostname}

For example:

ssh node1

2、确保你有一个Ceph配置文件的目录。默认情况下,Ceph使用/etc/ceph。安装ceph时,安装程序将自动创建/etc/ceph目录。

ls /etc/ceph

注意:清除群集时,部署工具可能会删除此目录(例如,ceph-deploy purgedata {node-name}, ceph-deploy purge {node-name})。

3、创建一个Ceph配置文件。默认情况下,Ceph使用ceph.conf,其中ceph反映了集群名称。

sudo vim /etc/ceph/ceph.conf

4、为您的群集生成一个唯一的ID(即fsid)。

uuidgen

5、添加唯一的ID到您的Ceph配置文件。

fsid = {UUID}

For example:

fsid = a7f64266-0894-4f1e-a635-d0aeaca0e993

6、将initial monitor(s)添加到您的Ceph配置文件中。

mon initial members = {hostname}[,{hostname}]

For example:

mon initial members = node1

7、将initial monitor(s)的IP地址添加到您的Ceph配置文件并保存该文件。

mon host = {ip-address}[,{ip-address}]

For example:

mon host = 192.168.0.1

注意:您可以使用IPv6地址而不是IPv4地址,但必须将ms bind ipv6设置为true。有关网络配置的详情,请参阅Network Configuration Referencehttp://docs.ceph.com/docs/master/rados/configuration/network-config-ref/

8、为您的群集创建一个keyring并生成一个monitor secret key。

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

9、生成一个administrator keyring,生成一个client.admin user并将user添加到该keyring中。

sudo ceph-authtool --create-keyring /etc/ceph/ceph.client.admin.keyring --gen-key -n client.admin --set-uid=0 --cap mon 'allow *' --cap osd 'allow *' --cap mds 'allow *' --cap mgr 'allow *'

10、生成一个bootstrap-osd keyring,生成一个client.bootstrap-osd user并将user添加到该keyring。

sudo ceph-authtool --create-keyring /var/lib/ceph/bootstrap-osd/ceph.keyring --gen-key -n client.bootstrap-osd --cap mon 'profile bootstrap-osd'

11、将生成的keys添加到ceph.mon.keyring。

sudo ceph-authtool /tmp/ceph.mon.keyring --import-keyring /etc/ceph/ceph.client.admin.keyring
sudo ceph-authtool /tmp/ceph.mon.keyring --import-keyring /var/lib/ceph/bootstrap-osd/ceph.keyring

12、使用hostname(s), host IP address(es)和FSID生成monitor map。 将其另存为/tmp/monmap:

monmaptool --create --add {hostname} {ip-address} --fsid {uuid} /tmp/monmap

For example:

monmaptool --create --add node1 192.168.0.1 --fsid a7f64266-0894-4f1e-a635-d0aeaca0e993 /tmp/monmap

13、在monitor host(s)上创建一个默认数据目录(或多个目录)。

sudo mkdir /var/lib/ceph/mon/{cluster-name}-{hostname}

For example:

sudo -u ceph mkdir /var/lib/ceph/mon/ceph-node1

有关详细信息,请参阅Monitor Config Reference - Data http://docs.ceph.com/docs/master/rados/configuration/mon-config-ref/#data

14、向monitor daemon(s)填充monitor map 和 keyring。

sudo -u ceph ceph-mon [--cluster {cluster-name}] --mkfs -i {hostname} --monmap /tmp/monmap --keyring /tmp/ceph.mon.keyring

For example:

sudo -u ceph ceph-mon --mkfs -i node1 --monmap /tmp/monmap --keyring /tmp/ceph.mon.keyring

15、考虑配置Ceph configuration file。 常用settings包括以下内容:

[global]
fsid = {cluster-id}
mon initial members = {hostname}[, {hostname}]
mon host = {ip-address}[, {ip-address}]
public network = {network}[, {network}]
cluster network = {network}[, {network}]
auth cluster required = cephx
auth service required = cephx
auth client required = cephx
osd journal size = {n}
osd pool default size = {n}  # Write an object n times.
osd pool default min size = {n} # Allow writing n copies in a degraded state.
osd pool default pg num = {n}
osd pool default pgp num = {n}
osd crush chooseleaf type = {n}

在前面的示例中,配置的[global]部分可能如下所示:

[global]
fsid = a7f64266-0894-4f1e-a635-d0aeaca0e993
mon initial members = node1
mon host = 192.168.0.1
public network = 192.168.0.0/24
auth cluster required = cephx
auth service required = cephx
auth client required = cephx
osd journal size = 1024
osd pool default size = 3
osd pool default min size = 2
osd pool default pg num = 333
osd pool default pgp num = 333
osd crush chooseleaf type = 1

16、touch the done 文件。
标记monitor已被创建并准备好启动:

sudo touch /var/lib/ceph/mon/ceph-node1/done

17、启动monitor(s).
对于大多数发行版,现在通过systemd启动服务:

sudo systemctl start ceph-mon@node1

对于Ubuntu Trusty,请使用Upstart:

sudo start ceph-mon id=node1 [cluster={cluster-name}]

在这种情况下,要在每次重新启动时启动守护进程,必须创建两个空文件,如下所示:

sudo touch /var/lib/ceph/mon/{cluster-name}-{hostname}/upstart

For example:

sudo touch /var/lib/ceph/mon/ceph-node1/upstart

对于以前的Debian/CentOS/RHEL,使用sysvinit:

sudo /etc/init.d/ceph start mon.node1

18、确认monitor正在运行。

ceph -s

您应该看到monitor已启动并正在运行的输出,并且您应该看到一个health error,指出placement groups处于非活动状态(inactive)。它应该看起来像这样:

cluster:
  id:     a7f64266-0894-4f1e-a635-d0aeaca0e993
  health: HEALTH_OK

services:
  mon: 1 daemons, quorum node1
  mgr: node1(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并启动它们后,placement group health errors应该消失。 有关详细信息,请参阅Adding OSDshttp://docs.ceph.com/docs/master/install/manual-deployment/#adding-osds

MANAGER DAEMON CONFIGURATION

在运行ceph-mon daemon的每个node上,也应该设置一个ceph-mgr daemon。
请参阅ceph-mgr administrator’s guidehttp://docs.ceph.com/docs/master/mgr/administrator/#mgr-administrator-guide

ADDING OSDS

一旦你的initial monitor(s)运行,你就应该添加OSD。除非有足够的OSD来处理对象的副本数(例如,osd pool default size = 2至少需要两个OSD),否则您的集群无法达到active + clean状态。在bootstrapping你的monitor之后,您的群集有一个默认的CRUSH map; 然而,CRUSH map没有任何Ceph OSD Daemons映射到Ceph节点。

SHORT FORM

Ceph提供了ceph-disk实用程序,它可以用于Ceph的prepare disk,partition或directory。ceph-disk实用程序通过incrementing the index来创建OSD ID。 另外,ceph-disk会将新的OSD添加到主机下的CRUSH map中。执行ceph-disk -h获取CLI详细信息。ceph-disk实用程序可以自动执行下面的Long Formhttp://docs.ceph.com/docs/master/install/manual-deployment/#long-form的步骤。要使用short form的过程创建前两个OSD,请在node2和node3上执行以下操作:

1、Prepare the OSD

ssh {node-name}
sudo ceph-disk prepare --cluster {cluster-name} --cluster-uuid {uuid} {data-path} [{journal-path}]

For example:

ssh node1
sudo ceph-disk prepare --cluster ceph --cluster-uuid a7f64266-0894-4f1e-a635-d0aeaca0e993 --fs-type ext4 /dev/hdd1

2、Activate the OSD:

sudo ceph-disk activate {data-path} [--activate-key {path}]

For example:

sudo ceph-disk activate /dev/hdd1

注意:如果Ceph Node上没有/var/lib/ceph/bootstrap-osd/{cluster}.keyring副本,请使用–activate-key参数。

LONG FORM
没有任何帮助工具的好处,使用以下过程创建一个OSD并将其添加到群集和CRUSH map。要使用long form过程创建前两个OSD,请为每个OSD执行以下步骤。
注意:这个过程没有描述利用dm-crypt ‘lockbox’部署dm-crypt。
1、Connect to the OSD host and become root.

ssh {node-name}
sudo bash

2、生成OSD的UUID。

UUID=$(uuidgen)

3、为OSD生成一个cephx key。

OSD_SECRET=$(ceph-authtool --gen-print-key)

4、创建OSD。请注意,如果您需要重新使用以前销毁的OSD ID,OSD ID可以作为ceph osd的附加参数提供。我们假设client.bootstrap-osd key存在于机器上。您也可以在存在该密钥的其他主机上以client.admin身份执行此命令:

ID=$(echo "{\"cephx_secret\": \"$OSD_SECRET\"}" | \
   ceph osd new $UUID -i - \
   -n client.bootstrap-osd -k /var/lib/ceph/bootstrap-osd/ceph.keyring)

5、在新的OSD上创建默认目录。

mkdir /var/lib/ceph/osd/ceph-$ID

6、如果OSD用于OS drive以外的drive(驱动器),准备与Ceph一起使用,并将其mount到您刚刚创建的目录中。

mkfs.xfs /dev/{DEV}
mount /dev/{DEV} /var/lib/ceph/osd/ceph-$ID

7、将secret(密钥)写入OSD keyring文件。

ceph-authtool --create-keyring /var/lib/ceph/osd/ceph-$ID/keyring \
     --name osd.$ID --add-key $OSD_SECRET

8、初始化OSD数据目录。

ceph-osd -i $ID --mkfs --osd-uuid $UUID

9、Fix ownership.

chown -R ceph:ceph /var/lib/ceph/osd/ceph-$ID

10、将OSD添加到Ceph后,OSD将处于您的配置中。 但是,它还没有运行。在它接收数据之前您必须先启动新的OSD。

For modern systemd distributions:

systemctl enable ceph-osd@$ID
systemctl start ceph-osd@$ID

For example:

systemctl enable ceph-osd@12
systemctl start ceph-osd@12

ADDING MDS

在下面的说明中,{id}是一个任意的名字,比如机器的主机名。
1、创建mds数据目录:

mkdir -p /var/lib/ceph/mds/{cluster-name}-{id}

2、创建一个keyring

ceph-authtool --create-keyring /var/lib/ceph/mds/{cluster-name}-{id}/keyring --gen-key -n mds.{id}

3、导入keyring并设置caps

ceph auth add mds.{id} osd "allow rwx" mds "allow" mon "allow profile mds" -i /var/lib/ceph/mds/{cluster}-{id}/keyring

4、添加到ceph.conf

[mds.{id}]
host = {id}

5、手动启动daemon

ceph-mds --cluster {cluster-name} -i {id} -m {mon-hostname}:{mon-port} [-f]

6、以正确的方式启动daemon(使用ceph.conf entry)

service ceph start

7、如果启动daemon失败并出现此错误

mds.-1.0 ERROR: failed to authenticate: (22) Invalid argument

确保在ceph.conf中的global部分没有设置keyring; 将其移动到client部分; 或添加keyring setting到特定mds daemon。并验证您看到的key与mds数据目录和ceph auth获取的mds.{id}输出相同。

8、现在你已经准备好创建一个Ceph filesystemhttp://docs.ceph.com/docs/master/cephfs/createfs/了。

SUMMARY

一旦启动并运行了monitor和两个OSD,您可以通过执行以下操作来观看placement groups peer:

ceph -w

要查看tree,请执行以下操作:

ceph osd tree

你应该看到如下所示的输出:

id    weight  type name       up/down reweight
-1      2       root default
-2      2               host node1
0       1                       osd.0   up      1
-3      1               host node2
1       1                       osd.1   up      1

要添加(或删除)其他monitors,请参阅Add/Remove Monitorshttp://docs.ceph.com/docs/master/rados/operations/add-or-rm-mons/。要添加(或删除)其他Ceph OSD Daemons,请参阅Add/Remove OSDshttp://docs.ceph.com/docs/master/rados/operations/add-or-rm-osds/

CEPH MANAGER DAEMON - RESTful plugin- RESTFUL PLUGIN

RESTful module通过SSL-secured连接提供REST API对cluster状态的访问。

ENABLING

restful模块启用:

ceph mgr module enable restful

在API endpoint 可用之前,您还需要配置SSL certificate(证书)。默认情况下,module将在主机上所有IPv4和IPv6地址的8003端口上接受HTTPS请求。

SECURING

所有的restful连接都通过SSL安全保护。您可以使用以下命令生成自签名证书:

ceph restful create-self-signed-cert

请注意,对于self-signed certificate(自签名证书),大多数客户端将需要一个flag(标志)来允许连接and/or禁止警告消息。例如,如果ceph-mgr daemon在同一主机上,则:

curl -k https://localhost:8003/

为了更安全的部署,应使用由组织认证机构签发的证书。例如,可以使用类似于以下的命令来生成密钥对:

openssl req -new -nodes -x509 \
  -subj "/O=IT/CN=ceph-mgr-restful" \
  -days 3650 -keyout restful.key -out restful.crt -extensions v3_ca

然后restful.crt应由您的organization的CA(证书颁发机构)签名。一旦完成,您可以将其设置为:

ceph config-key set mgr/restful/$name/crt -i restful.crt
ceph config-key set mgr/restful/$name/key -i restful.key

其中$name是ceph-mgr实例的名称(通常是主机名)。如果所有manager实例要共享相同的证书,则可以忽略$name部分:

ceph config-key set mgr/restful/crt -i restful.crt
ceph config-key set mgr/restful/key -i restful.key

CONFIGURING IP AND PORT

像任何其他RESTful API endpoint一样,restful绑定IP和port。默认情况下,当前active的ceph-mgr daemon将绑定主机上任何可用的IPv4或IPv6地址的8003端口。
由于每个ceph-mgr都拥有自己的restful实例,因此也可能需要单独配置它们。IP和端口可以通过配置key facility进行更改:

ceph config set mgr mgr/restful/$name/server_addr $IP
ceph config set mgr mgr/restful/$name/server_port $PORT

其中$name是ceph-mgr守护进程的ID(通常是hostname)。
这些设置也可以在集群范围内配置,而不是manager 指定的。例如:

ceph config set mgr mgr/restful/server_addr $IP
ceph config set mgr mgr/restful/server_port $PORT

如果端口没有配置,restful将默认绑定到8003端口。
如果没有配置IP地址,restful将绑定到::,这对应于所有可用的IPv4和IPv6地址。

CREATING AN API USER

要创建API用户,请运行以下命令:

1
ceph restful create-key <username>

<username>替换为所需的用户名。 例如,创建一个名为api的用户:

1
2
$ ceph restful create-key api
52dffd92-a103-4a10-bfce-5b60f48f764e

从ceph restful create-key api生成的UUID作为用户的密钥。

要列出所有API密钥,请运行以下命令:

1
ceph restful list-keys

ceph restful list-keys命令将以JSON输出:

1
2
3
{
"api": "52dffd92-a103-4a10-bfce-5b60f48f764e"
}

可以使用curl来测试您的API用户。 例如:

1
curl -k https://api:52dffd92-a103-4a10-bfce-5b60f48f764e@<ceph-mgr>:<port>/server

在上述情况下,我们使用GET从服务器endpoint获取信息。

LOAD BALANCER

请注意,restful只会在当前处于active状态的manager启动。查询Ceph集群状态来查看哪个manager处于active状态(例如,ceph mgr dump)。为了使API可通过一致的URL访问,无论哪个管理器daemon当前处于active状态,您可能需要在前端设置一个负载平衡器,以将流量引导至任何可用的manager endpoint。

AVAILABLE METHODS

您可以导航到/doc endpoint,以获取可用endpoints的完整列表以及为每个endpoints实现的HTTP方法。

例如,使用/osd/<id> endpoint的PATCH method设置OSD id 1,则可以使用以下curl命令:

1
echo -En '{"up": true}' | curl --request PATCH --data @- --silent --insecure --user <user> 'https://<ceph-mgr>:<port>/osd/1'

或者您可以使用python这样做:

1
2
3
4
5
6
7
8
$ python
>> import requests
>> result = requests.patch(
'https://<ceph-mgr>:<port>/osd/1',
json={"up": True},
auth=("<user>", "<password>")
)
>> print result.json()

restful module中实现的其他一些endpoints包括

  • /config/cluster: GET
  • /config/osd: GET, PATCH
  • /crush/rule: GET
  • /mon: GET
  • /osd: GET
  • /pool: GET, POST
  • /pool/<arg>: DELETE, GET, PATCH
  • /request: DELETE, GET, POST
  • /request/<arg>: DELETE, GET
  • /server: GET

THE /REQUEST ENDPOINT

您可以使用/request endpoint DELETE, POST or PATCH method轮询请求状态。这些方法默认情况下是异步的,因为它们可能需要更长的时间才能完成执行。您可以通过将?wait=1附加到请求url来修改此行为。

localpool插件可以自动创建本地化为整个集群子集的RADOS pool。例如,默认情况下,它将为集群中的每个不同rack创建一个pool。对于某些希望在本地以及整个集群内分布一些数据的部署可能非常有用。
(个人理解这里的本地有可能是不同RULE下的pool,不同RULE下是否同名pool没有验证是否允许)

ENABLING

localpool模块启用:

ceph mgr module enable localpool

CONFIGURING

localpool模块可以支持以下选项:

  • subtree(default: rack): 为哪个CRUSH subtree type模块创建一个池
  • failure_domain (default: host) : 我们应该在哪个故障域中分隔数据副本
  • pg_num (default: 128) : 为每个pool创建PG的数量
  • num_rep (default: 3) : 每个pool的副本数。(目前,pool只支持replicated模式)
  • min_size (default: none) : 设置min_size值(如果没有设置此选项,则不会改变Ceph的默认值)
  • prefix (default: by-$subtreetype-) : pool名的prefix(前缀)

通过config-key接口设置这些选项。例如,设置复制2副本,64PG

ceph config-key set mgr/localpool/num_rep 2
ceph config-key set mgr/localpool/pg_num 64

CEPH MANAGER DAEMON - Dashboard plugin - DASHBOARD PLUGIN
Dashboard 插件使用ceph-mgr托管的Web server,可以可视化集群的统计信息。

ENABLING
dashboard模块启用:

ceph mgr module enable dashboard

CONFIGURATION

像大多数Web应用程序一样,dashboard 绑定到主机名和端口。默认情况下,ceph-mgr daemon托管的dashboard(即当前active manager)将绑定到主机上任何可用的IPv4或IPv6地址的7000端口。
由于每个ceph-mgr都拥有自己的dashboard instance,因此可能需要单独配置它们。hostname 和port 可以通过配置key facility进行更改:

ceph config-key set mgr/dashboard/$name/server_addr $IP
ceph config-key set mgr/dashboard/$name/server_port $PORT

其中$name是托管此dashboard Web应用程序的ceph-mgr的ID。
这些设置也可以在集群范围内配置,而不是管理员特定的。 例如:
ceph config-key set mgr/dashboard/server_addr $IP
ceph config-key set mgr/dashboard/server_port $PORT
如果未配置端口,则Web应用程序将绑定到7000端口。
如果未配置地址,则Web应用将绑定到::,其对应于所有可用的IPv4和IPv6地址。

您可以为所有URLs配置prefix:

ceph config-key set mgr/dashboard/url_prefix $PREFIX

所以你可以访问dashboard http://$IP:$PORT/$PREFIX/.

LOAD BALANCER
请注意,dashboard 将只在当时处于active状态的管理器上启动。查询Ceph集群状态以查看哪个管理器处于active状态(例如,ceph mgr dump)。为了使仪表板可通过一致的URL访问,无论哪个管理器daemon当前处于active状态,您可能需要在前端设置一个负载平衡器,以将流量引导至任何可用的管理器endpoint。 如果你使用HTTP反向代理转发到dashboard的subpath,则需要配置url_prefix(请参见上文)。

CEPH MANAGER DAEMON - Installation and Configuration - CEPH-MGR ADMINISTRATOR’S GUIDE

MANUAL SETUP

通常,你可以使用ceph-ansible这样的工具来建立一个ceph-mgr守护进程。 下面这些说明描述了如何手动设置ceph-mgr守护进程。

首先,为守护进程创建一个身份验证密钥:

ceph auth get-or-create mgr.$name mon 'allow profile mgr' osd 'allow *' mds 'allow *'

该密钥放置到mgr数据路径中,对于集群名“ceph”和mgr $name为“foo”,该路径将是/var/lib/ceph/mgr/ceph-foo。

启动ceph-mgr守护进程:

ceph-mgr -i $name

通过查看ceph状态的输出来检查mgr是否已经出现,它现在应该包含一个mgr状态行:

mgr active: $name

CLIENT AUTHENTICATION

manager是一个新的守护进程,需要新的CephX功能。 如果您从旧版本的Ceph升级集群,或者使用默认安装/部署工具,则admin client应该自动获得此功能。如果您使用其他地方的工具,则在调用某些ceph集群命令时可能会收到EACCES错误。为了解决这个问题,可以通过修改用户权限来为client的cephx功能添加一个“mgr allow *”。

http://docs.ceph.com/docs/master/rados/operations/user-management/#modify-user-capabilities)

HIGH AVAILABILITY

一般来说,你应该在每台运行ceph-mon守护进程的主机上设置一个ceph-mgr来达到相同的可用性。默认情况下,首先启动的ceph-mgr实例将被monitors设置为active,而其他的则是standbys。ceph-mgr守护进程中不需要仲裁。如果 active daemon在mon_mgr_beacon_grace(default 30s)规定时间内发送beacon到monitors失败,standby会替代当前active。如果要抢先进行故障切换,可以使用命令ceph mgr fail 明确标记ceph-mgr daemon失败。

USING MODULES

使用命令ceph mgr module ls查看哪些模块可用,哪些是当前启用的。使用命令ceph mgr module enable 和ceph mgr module disable 分别启用模块和禁用模块。
如果启用了一个模块,则active ceph-mgr daemon将加载并执行它。当模块在加载时发布它的IP地址,如HTTP server。要查看这些模块的地址,请使用命令ceph mgr services。
一些模块也可以实现一个特殊的standby模式,它在standby ceph-mgr daemons以及active daemon。如果client尝试连接到standby,这使得提供服务的模块能够将其client重定向到active daemon。
有关每个模块提供的功能的更多信息,请参阅个别管理器模块的文档页面。

以下是启用dashboard模块的示例:

$ ceph mgr module ls
{
        "enabled_modules": [
                "restful",
                "status"
        ],
        "disabled_modules": [
                "dashboard"
        ]
}

$ ceph mgr module enable dashboard
$ ceph mgr module ls
{
        "enabled_modules": [
                "restful",
                "status",
                "dashboard"
        ],
        "disabled_modules": [
        ]
}

$ ceph mgr services
{
        "dashboard": "http://myserver.com:7789/",
        "restful": "https://myserver.com:8789/"
}

CALLING MODULE COMMANDS

在模块实现command line hooks的情况下,这些commands将作为普通的Ceph命令来访问:

ceph <command | help>

如果你想查看manager处理的命令列表(标准ceph help将显示所有的mon和mgr命令),你可以直接发送一个命令到manager daemon:

ceph tell mgr help

注意,没有必要去访问一个特定的mgr instance,mgr将自动选择当前的active daemon。

CONFIGURATION

OPTION(mgr_module_path, OPT_STR, CEPH_PKGLIBDIR “/mgr”) // 从哪里加载python模块

mgr module path
Description:    Path to load modules from
Type:    String
Default:    "<library dir>/mgr"

mgr data
Description:    Path to load daemon data (such as keyring)
Type:    String
Default:    "/var/lib/ceph/mgr/$cluster-$id"

mgr tick period
Description:    How many seconds between mgr beacons to monitors, and other periodic checks.
Type:    Integer
Default:    5

mon mgr beacon grace
Description:    How long after last beacon should a mgr be considered failed
Type:    Integer
Default:    30

[root@centos001 vdbench]# lsb_release -a
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.3.1611 (Core)
Release: 7.3.1611
Codename: Core

vdbench单机测试

1、下载vdbench50406.zip

2、解压vdbench50406.zip

3、安装java,jdk
[root@centos001 ~]# yum install java-1.8.0-openjdk unzip net-tools iotop -y
[root@yujiangcontrol ~]# java -version
openjdk version “1.8.0_144”
OpenJDK Runtime Environment (build 1.8.0_144-b01)
OpenJDK 64-Bit Server VM (build 25.144-b01, mixed mode)

4、配置vdbench
[root@centos001 ~]# unzip vdbench50406.zip
[root@centos001 ~]# ./vdbench -t

5、配置文件
[root@centos001 ~]# vi yujiang
sd=sd1,lun=/dev/sdb,openflags=o_direct
wd=wd1,sd=sd1,seekpct=random,rdpct=0,xfersize=8192
rd=rd1,wd=wd*,elapsed=120,interval=10,iorate=max
openflags=o_direct 直接对块设备进行读写

6、执行配置文件
[root@centos001 ~]# sudo ./vdbench -f yujiang

vdbench多机测试

[root@centos001 vdbench]# cat /etc/hosts
192.168.30.100 centos001 centos001.test.com
192.168.30.103 plana003 plana003.test.com
192.168.30.104 plana004 plana004.test.com
192.168.30.105 plana005 plana005.test.com

1、生成sshkey
[root@centos001 vdbench]# ssh-keygen
与其他slave节点做ssh互信
[root@centos001 vdbench]# ssh-copy-id plana003
[root@centos001 vdbench]# ssh-copy-id plana004
[root@centos001 vdbench]# ssh-copy-id plana005
[root@centos001 vdbench]# ssh plana003.test.com
[root@centos001 vdbench]# ssh plana004.test.com
[root@centos001 vdbench]# ssh plana005.test.com

2、把vdbench拷贝到每台slave节点,包括master节点,路径相同
/root/vdbench

3、每台slave机监听,ssh不用监听
[root@plana003 vdbench]# ./vdbench rsh
[root@plana004 vdbench]# ./vdbench rsh
[root@plana005 vdbench]# ./vdbench rsh

备注:
Host Definition (HD)
These parameters are ONLY needed when running Vdbench in a multi-host environment or if you want to override the number of JVMs used in a single-host environment.
See also Host Definition parameter detail.

hd=default Sets defaults for all HDs that are entered later
hd=localhost Sets values for the current host
hd=host_label Specify a host label.
system=host_name Host IP address or network name, e.g. xyz.customer.com
vdbench=vdbench_dir_name Where to find Vdbench on a remote host if different from current.
jvms=nnn How many slaves to use. See Multi JVM execution.
shell=rsh | ssh | vdbench How to start a Vdbench slave on a remote system.
user=xxxx Userid on remote system Required.
clients=nn This host will simulate the running of multiple ‘clients’. Very useful if you want to simulate numerous clients for file servers without having all the hardware.
mount=”mount xxx …” This mount command is issued on the target host after the possibly needed mount directories have been created.
rg=name Unique name for this Replay Group (RG).
devices=(xxx,yyy,….) The device numbers from Swat’s flatfile.bin.gz to be replayed.

Storage Definition (SD)
See also Storage Definition Parameter Detail.
This set of parameters identifies each physical or logical volume manager volume or file system file used in the requested workload. Of course, with a file system file, the file system takes the responsibility of all I/O: reads and writes can and will be cached (see also openflags=) and Vdbench will not have control over physical I/O. However, Vdbench can be used to test file system file performance (See also File system testing).
Example: sd=sd1,lun=/dev/rdsk/cxt0d0s0,threads=8

sd=default Sets defaults for all SDs that are entered later.
sd=name Unique name for this Storage Definition (SD).
host=name Name of host where this SD can be found. Default ‘localhost’
lun=lun_name Name of raw disk or file system file.
align=nnn Generate logical byte address in ‘nnn’ byte boundaries, not using default ‘xfersize’ boundaries.
count=(nn,mm) Creates a sequence of SD parameters.
hitarea=nn See read hit percentage for an explanation. Default 1m.
journal=xxx Directory name for journal file for data validation
offset=nnn At which offset in a lun to start I/O.
openflags=(flag,..) Pass specific flags when opening a lun or file
range=(nn,mm) Use only a subset ‘range=nn’: Limit Seek Range of this SD.
replay=(group,..) Replay Group(s) using this SD.
replay=(nnn,..) Device number(s) to select for Swat Vdbench replay
resetbus=nnn Issue ioctl (USCSI_RESET_ALL) every nnn seconds. Solaris only
resetlun=nnn Issue ioctl (USCSI_RESET) every nnn seconds. Solaris only
size=nn Size of the raw disk or file to use for workload. Optional unless you want Vdbench to create a disk file for you.
streams=(nn,mm) Create independent sequential streams on the same device.
threads=nn Maximum number of concurrent outstanding I/O for this SD. Default 8

Workload Definition (WD)
See also Workload Definition Parameter Detail.
The Workload Definition parameters describe what kind of workload must be executed using the storage definitions entered.
Example: wd=wd1,sd=(sd1,sd2),rdpct=100,xfersize=4k

wd=default Sets defaults for all WDs that are entered later.
wd=name Unique name for this Workload Definition (WD)
sd=xx Name(s) of Storage Definition(s) to use
host=host_label Which host to run this workload on. Default localhost.
iorate=nn Requested fixed I/O rate for this workload.
openflags=(flag,..) Pass specific flags when opening a lun or file.
priority=nn I/O priority to be used for this workload.
range=(nn,nn) Limit seek range to a defined range within an SD.
rdpct=nn Read percentage. Default 100.
rhpct=nn Read hit percentage. Default 0.
seekpct=nn Percentage of random seeks. Default seekpct=100 or seekpct=random.
skew=nn Percentage of skew that this workload receives from the total I/O rate.
stride=(min,max) To allow for skip-sequential I/O.
threads=nn Only available during SD concatenation.
whpct=nn Write hit percentage. Default 0.
xfersize=nn Data transfer size. Default 4k.
xfersize=(n,m,n,m,..) Specify a distribution list with percentages.
xfersize=(min,max,align) Generate xfersize as a random value between min and max.

Run Definition (RD)
See also Run Definition Parameter Detail.
The Run Definition parameters define which of the earlier defined workloads need to be executed, what I/O rates need to be generated, and how long the workload will run. One Run Definition can result in multiple actual workloads, depending on the parameters used.
Example: rd=run1,wd=(wd1,wd2),iorate=1000,elapsed=60,interval=5
There is a separate list of RD parameters for file system testing.

rd=default Sets defaults for all RDs that are entered later.
rd=name Unique name for this Run Definition (RD).
wd=xx Workload Definitions to use for this run.
sd=xxx Which SDs to use for this run (Optional).
curve=(nn,nn,..) Data points to generate when creating a performance curve.
distribution=(x[,variable] I/O inter arrival time calculations: exponential, uniform, or deterministic. Default exponential.
elapsed=nn Elapsed time for this run in seconds. Default 30 seconds.
maxdata=nnn Stop the run after nnn bytes have been read or written, e.g.
maxdata=200g. Vdbench will stop at the lower of elapsed= and maxdata=.
endcmd=cmd Execute command or script at the end of the last run
(for)compratio=nn Multiple runs for each compression percentage.
(for)hitarea=nn Multiple runs for each hit area size.
(for)hpct=nn Multiple runs for each read hit percentage.
(for)rdpct=nn Multiple runs for each read percentage.
(for)seekpct=nn Multiple runs for each seek percentage.
(for)threads=nn Multiple runs for each thread count.
(for)whpct=nn Multiple runs for each write hit percentage.
(for)xfersize=nn Multiple runs for each data transfer size.
Most forxxx parameters may be abbreviated to their regular name, e.g. xfersize=(..,..)
interval=nn Reporting interval in seconds. Default ‘min(elapsed/2,60)’
iorate=(nn,nn,nn,…) One or more I/O rates.
iorate=curve Create a performance curve.
iorate=max Run an uncontrolled workload.
iorate=(nn,ss,…) nn,ss: pairs of I/O rates and seconds of duration for this I/O rate. See also ‘distribution=variable’.
openflags=xxxx Pass specific flags when opening a lun or file
pause=nn Sleep ‘nn’ seconds before starting next run.
replay=(filename,split=split_dir,repeat=nn)
-‘filename’: Replay file name used for Swat Vdbench replay

  • ‘split_dir’: directory used to do the replay file split.
  • ‘nn’: how often to repeat the replay.
    startcmd=cmd Execute command or script at the beginning of the first run
    warmup=nn Override warmup period.

1、多slave host不同块设备
For instance if a lun is /dev/rdsk/a on hosta but it is named /dev/rdsk/b on hostb then you’ll have to tell Vdbench about it.
sd=sd1,lun=/dev/rdsk/a,host=hosta,lun=/dev/rdsk/b,host=hostb
By default Vdbench assumes that the lun names on each host are identical.

2、
[root@centos001 vdbench]# cat example5
hd=default,vdbench=/root/vdbench,user=root,shell=ssh
hd=plana003,system=plana003.test.com
hd=plana004,system=plana004.test.com
hd=plana005,system=plana005.test.com

sd=sd1,host=,lun=/dev/sdb,size=10m,openflags=o_direct
wd=wd1,sd=sd
,rdpct=100,xf=4k
rd=rd1,wd=wd1,el=3,in=1,io=10,warmup=30
解释:
hd=default以下hd都使用后面的默认值
vdbench到每台slave机的相同目录寻找vdbench程序
user以root用户登录远程slave机
shell以ssh协议登录
hd=plana003远程slave机标签
system=plana003.test.com ip地址或者配置hosts文件,用来ssh连接slave机

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
91
92
93
94
95
96
97
98
99
100
101
root@node1:/home/simth/config# cat vdbenchcase1.config
hd=default,vdbench=/home/simth,user=root,shell=ssh
hd=hd1,system=node1
hd=hd2,system=node2
hd=hd3,system=node3

fsd=sd1,anchor=/home/node-1/node-1-rbd-1,openflags=o_direct,depth=3,width=3,files=3300,size=(2M,100),shared=yes
fsd=sd2,anchor=/home/node-1/node-1-rbd-2,openflags=o_direct,depth=3,width=3,files=3300,size=(2M,100),shared=yes
fsd=sd3,anchor=/home/node-1/node-1-rbd-3,openflags=o_direct,depth=3,width=3,files=3300,size=(2M,100),shared=yes
fsd=sd4,anchor=/home/node-1/node-1-rbd-4,openflags=o_direct,depth=3,width=3,files=3300,size=(2M,100),shared=yes
fsd=sd5,anchor=/home/node-1/node-1-rbd-5,openflags=o_direct,depth=3,width=3,files=3300,size=(2M,100),shared=yes
fsd=sd6,anchor=/home/node-1/node-1-rbd-6,openflags=o_direct,depth=3,width=3,files=3300,size=(2M,100),shared=yes
fsd=sd7,anchor=/home/node-1/node-1-rbd-7,openflags=o_direct,depth=3,width=3,files=3300,size=(2M,100),shared=yes
fsd=sd8,anchor=/home/node-1/node-1-rbd-8,openflags=o_direct,depth=3,width=3,files=3300,size=(2M,100),shared=yes
fsd=sd9,anchor=/home/node-1/node-1-rbd-9,openflags=o_direct,depth=3,width=3,files=3300,size=(2M,100),shared=yes
fsd=sd10,anchor=/home/node-1/node-1-rbd-10,openflags=o_direct,depth=3,width=3,files=3300,size=(2M,100),shared=yes

fwd=wd1,fsd=sd*,hd=hd1,operation=write,threads=1,fileio=sequential,fileselect=random,xfersize=16k
fwd=wd2,fsd=sd*,hd=hd2,operation=write,threads=1,fileio=sequential,fileselect=random,xfersize=16k
fwd=wd3,fsd=sd*,hd=hd3,operation=write,threads=1,fileio=sequential,fileselect=random,xfersize=16k

rd=rd1,fwd=wd*,fwdrate=max,format=clean,interval=1
rd=rd2,fwd=wd*,fwdrate=122,format=restart,elapse=3600,maxdata=1800G,interval=5,warmup=30




hd=default,vdbench=/home/simth,user=root,shell=ssh
hd=hd1,system=node1
hd=hd2,system=node2
hd=hd3,system=node3

fsd=sd1,anchor=/home/node-1/node-1-rbd-1,openflags=o_direct,depth=3,width=3,files=3300,size=(2M,100),shared=yes
fsd=sd2,anchor=/home/node-1/node-1-rbd-2,openflags=o_direct,depth=3,width=3,files=3300,size=(2M,100),shared=yes
fsd=sd3,anchor=/home/node-1/node-1-rbd-3,openflags=o_direct,depth=3,width=3,files=3300,size=(2M,100),shared=yes
fsd=sd4,anchor=/home/node-1/node-1-rbd-4,openflags=o_direct,depth=3,width=3,files=3300,size=(2M,100),shared=yes
fsd=sd5,anchor=/home/node-1/node-1-rbd-5,openflags=o_direct,depth=3,width=3,files=3300,size=(2M,100),shared=yes
fsd=sd6,anchor=/home/node-1/node-1-rbd-6,openflags=o_direct,depth=3,width=3,files=3300,size=(2M,100),shared=yes
fsd=sd7,anchor=/home/node-1/node-1-rbd-7,openflags=o_direct,depth=3,width=3,files=3300,size=(2M,100),shared=yes
fsd=sd8,anchor=/home/node-1/node-1-rbd-8,openflags=o_direct,depth=3,width=3,files=3300,size=(2M,100),shared=yes
fsd=sd9,anchor=/home/node-1/node-1-rbd-9,openflags=o_direct,depth=3,width=3,files=3300,size=(2M,100),shared=yes
fsd=sd10,anchor=/home/node-1/node-1-rbd-10,openflags=o_direct,depth=3,width=3,files=3300,size=(2M,100),shared=yes

fwd=wd1,fsd=sd*,hd=hd1,operation=read,threads=1,fileio=sequential,fileselect=random,xfersize=1024k
fwd=wd2,fsd=sd*,hd=hd2,operation=read,threads=1,fileio=sequential,fileselect=random,xfersize=1024k
fwd=wd3,fsd=sd*,hd=hd3,operation=read,threads=1,fileio=sequential,fileselect=random,xfersize=1024k

*rd=rd1,fwd=wd*,fwdrate=max,format=clean,interval=1
rd=rd2,fwd=wd*,fwdrate=690,format=restart,elapse=3600,maxdata=1800G,interval=5,warmup=30




hd=default,vdbench=/home/simth,user=root,shell=ssh
hd=hd1,system=node1
hd=hd2,system=node2
hd=hd3,system=node3

fsd=sd1,anchor=/home/node-1/node-1-rbd-1,openflags=o_direct,depth=3,width=3,files=3300,size=(2M,100),shared=yes
fsd=sd2,anchor=/home/node-1/node-1-rbd-2,openflags=o_direct,depth=3,width=3,files=3300,size=(2M,100),shared=yes
fsd=sd3,anchor=/home/node-1/node-1-rbd-3,openflags=o_direct,depth=3,width=3,files=3300,size=(2M,100),shared=yes
fsd=sd4,anchor=/home/node-1/node-1-rbd-4,openflags=o_direct,depth=3,width=3,files=3300,size=(2M,100),shared=yes
fsd=sd5,anchor=/home/node-1/node-1-rbd-5,openflags=o_direct,depth=3,width=3,files=3300,size=(2M,100),shared=yes
fsd=sd6,anchor=/home/node-1/node-1-rbd-6,openflags=o_direct,depth=3,width=3,files=3300,size=(2M,100),shared=yes
fsd=sd7,anchor=/home/node-1/node-1-rbd-7,openflags=o_direct,depth=3,width=3,files=3300,size=(2M,100),shared=yes
fsd=sd8,anchor=/home/node-1/node-1-rbd-8,openflags=o_direct,depth=3,width=3,files=3300,size=(2M,100),shared=yes
fsd=sd9,anchor=/home/node-1/node-1-rbd-9,openflags=o_direct,depth=3,width=3,files=3300,size=(2M,100),shared=yes
fsd=sd10,anchor=/home/node-1/node-1-rbd-10,openflags=o_direct,depth=3,width=3,files=3300,size=(2M,100),shared=yes

fwd=wd1,fsd=sd*,hd=hd1,operation=write,fileio=random,threads=8,fileselect=random,xfersize=8k
fwd=wd2,fsd=sd*,hd=hd2,operation=write,fileio=random,threads=8,fileselect=random,xfersize=8k
fwd=wd3,fsd=sd*,hd=hd3,operation=write,fileio=random,threads=8,fileselect=random,xfersize=8k

*rd=rd1,fwd=wd*,fwdrate=max,format=clean,interval=1
rd=rd2,fwd=wd*,fwdrate=1014,format=restart,elapse=3600,maxdata=1800G,interval=5,warmup=30




hd=default,vdbench=/home/simth,user=root,shell=ssh
hd=hd1,system=node1
hd=hd2,system=node2
hd=hd3,system=node3

fsd=sd1,anchor=/home/node-1/node-1-rbd-1,openflags=o_direct,depth=3,width=3,files=3300,size=(2M,100),shared=yes
fsd=sd2,anchor=/home/node-1/node-1-rbd-2,openflags=o_direct,depth=3,width=3,files=3300,size=(2M,100),shared=yes
fsd=sd3,anchor=/home/node-1/node-1-rbd-3,openflags=o_direct,depth=3,width=3,files=3300,size=(2M,100),shared=yes
fsd=sd4,anchor=/home/node-1/node-1-rbd-4,openflags=o_direct,depth=3,width=3,files=3300,size=(2M,100),shared=yes
fsd=sd5,anchor=/home/node-1/node-1-rbd-5,openflags=o_direct,depth=3,width=3,files=3300,size=(2M,100),shared=yes
fsd=sd6,anchor=/home/node-1/node-1-rbd-6,openflags=o_direct,depth=3,width=3,files=3300,size=(2M,100),shared=yes
fsd=sd7,anchor=/home/node-1/node-1-rbd-7,openflags=o_direct,depth=3,width=3,files=3300,size=(2M,100),shared=yes
fsd=sd8,anchor=/home/node-1/node-1-rbd-8,openflags=o_direct,depth=3,width=3,files=3300,size=(2M,100),shared=yes
fsd=sd9,anchor=/home/node-1/node-1-rbd-9,openflags=o_direct,depth=3,width=3,files=3300,size=(2M,100),shared=yes
fsd=sd10,anchor=/home/node-1/node-1-rbd-10,openflags=o_direct,depth=3,width=3,files=3300,size=(2M,100),shared=yes

fwd=wd1,fsd=sd*,hd=hd1,operation=read,fileio=random,threads=8,fileselect=random,xfersize=8k
fwd=wd2,fsd=sd*,hd=hd2,operation=read,fileio=random,threads=8,fileselect=random,xfersize=8k
fwd=wd3,fsd=sd*,hd=hd3,operation=read,fileio=random,threads=8,fileselect=random,xfersize=8k

*rd=rd1,fwd=wd*,fwdrate=max,format=clean,interval=1
rd=rd2,fwd=wd*,fwdrate=11826,format=restart,elapse=3600,maxdata=1800G,interval=5,warmup=30

ElasticSearch入门
笔记来自:http://www.imooc.com/video/15762

ElasticSearch简介

1、什么是ElasticSearch?

基于Apache Lucene构建的开源搜索引擎
采用Java编写,提供简单易用的RESTFul API
轻松的横向扩展,可支持PB级的结构化或非结构化数据处理

2、应用场景

海量数据分析引擎
站内搜索引擎
数据仓库

3、一线公司实际应用场景

英国卫报 - 实时分析公众对文章的回应
维基百科、GitHub - 站内实时搜索
百度 - 实时日志监控平台
等等...

4、前置知识

熟悉用Maven构建项目
了解Spiring Boot的基本使用

5、环境要求

IDE工具 IntelliJ IDEA、Eclipse等常规用IDE即可
Java JDK1.8
其他依赖 Maven、NodeJs(6.0以上)

6、课程简介

安装
基础概念
基本用法
高级查询
实战演练
课程总结

安装

1、版本问题

版本历史 1.x->2.x->5.x
版本选择 5.x

2、单实例安装
(1)官网下载elasticsearch

https://www.elastic.co/cn/

yujiang@ubuntu001:~$ wget https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-5.6.0.tar.gz

(2)解压并修改配置文件

yujiang@ubuntu001:~$ tar zxvf elasticsearch-5.6.0.tar.gz

yujiang@ubuntu001:~$ cd elasticsearch-5.6.0/

yujiang@ubuntu001:~/elasticsearch-5.6.0$ vi config/elasticsearch.yml
添加
network.host: 192.168.30.134

(3)启动elasticsearch

yujiang@ubuntu001:~$ sudo sysctl -w vm.max_map_count=262144
或
yujiang@ubuntu001:~$ sudo vi /etc/sysctl.conf
vm.max_map_count=262144

yujiang@ubuntu001:~/elasticsearch-5.6.0$ sh ./bin/elasticsearch

(4)打开浏览器

http://192.168.30.134:9200/

3、实用插件Head安装
(1)安装nodejs

yujiang@ubuntu001:~$ wget https://nodejs.org/dist/v6.11.3/node-v6.11.3-linux-x64.tar.xz
yujiang@ubuntu001:~$ xz -d node-v6.11.3-linux-x64.tar.xz 
yujiang@ubuntu001:~$ tar -xvf node-v6.11.3-linux-x64.tar 
yujiang@ubuntu001:~$ sudo ln -s /home/yujiang/node-v6.11.3-linux-x64/bin/node  /usr/bin/node 
yujiang@ubuntu001:~$ sudo ln -s /home/yujiang/node-v6.11.3-linux-x64/bin/npm  /usr/bin/npm 

(2)修改ElasticSearch配置文件,支持跨域,并在后台运行ElasticSearch

yujiang@ubuntu001:~/elasticsearch-5.6.0$ vi config/elasticsearch.yml
添加
http.cors.enabled: true
http.cors.allow-origin: "*"
yujiang@ubuntu001:~/elasticsearch-5.6.0$ sh ./bin/elasticsearch -d

(3)运行elasticsearch-head

https://github.com/mobz/elasticsearch-head
yujiang@ubuntu001:~$ wget https://github.com/mobz/elasticsearch-head/archive/master.zip
yujiang@ubuntu001:~$ unzip master.zip
yujiang@ubuntu001:~$ cd elasticsearch-head-master/
yujiang@ubuntu001:~/elasticsearch-head-master$ npm install
yujiang@ubuntu001:~/elasticsearch-head-master$ npm run start

(4)打开浏览器

http://192.168.30.134:9100/

web页面输入
http://192.168.30.134:9200/

4、分布式安装

(1)master节点修改配置文件

yujiang@ubuntu001:~/elasticsearch-5.6.0$ vi config/elasticsearch.yml
添加 
cluster.name: escluster
node.name: master
node.master: true

(2)slave节点修改配置文件

cluster.name: escluster
node.name: slave1
network.host: 192.168.30.135
#http.port: 8200
discovery.zen.ping.unicast.hosts: ["192.168.30.134"]
yujiang@ubuntu002:~/elasticsearch-5.6.0$ sh ./bin/elasticsearch

(3)安装java jdk

yujiang@ubuntu002:~$ sudo add-apt-repository ppa:openjdk-r/ppa
yujiang@ubuntu002:~$ sudo apt-get update 
yujiang@ubuntu002:~$ sudo apt-get install -f openjdk-8-jdk
yujiang@ubuntu002:~$ java -version
openjdk version "1.8.0_131"
OpenJDK Runtime Environment (build 1.8.0_131-8u131-b11-2ubuntu1.16.04.3-b11)
OpenJDK 64-Bit Server VM (build 25.131-b11, mixed mode)

ElasticSearch基础概念

集群和节点

master + slave1 + slave2 + slave...n

索引

含有相同属性的文档集合

类型

索引可以定义一个或多个类型,文档必须属于一个类型

文档

文档是可以被索引的基本数据单位

分片

每个索引都有多个分片,每个分片是一个Lucene索引
分片的好处,加入一个索引的数据量很大,就会造成硬盘压力很大,就会出现搜索瓶颈,可以将索引分成多个分片,从而分担压力,还允许用户进行水平的扩展和拆分,及分布式的操作,可以提高搜索和其他操作的效率

备份

拷贝一份分片就完成了分片的备份
当一个主分片失败或者出现问题时,备份分片可以代替工作,从而提高了es的可用性。备份的分片还可以执行搜索的操作,以分摊搜索的压力。es在创建索引时会创建5和分片和1个备份,数量可以修改,分片只有在创建索引的时候指定而不能在后期进行修改,备份是可以动态修改的

ElasticSearch的基本用法

RESTFul API

(1)API基本格式

http://<ip>:<port>/<索引>/<类型>/<文档id>

(2)常用HTTP动词

GET/PUT/POST/DELETE

C++11 introduced lambdas, allowing the definition of inline functionality, which can be used as a parameter or a local object.Lambdas change the way the C++ standard library is used.

Syntax of Lambdas
A lambda is a definition of functionality that can be defined inside statements and expressions. Thus, you can use a lambda as an inline function.
The minimal lambda function has no parameters and simply does something. For example:

1
2
3
[] {
std::cout << "hello lambda" << std::endl;
}

You can call it directly: mutable_opt throwSpec_opt->retType_opt{…}

1
2
3
[] {
std::cout << "hello lambda" << std::endl;
} (); // prints ‘‘hello lambda’’

or pass it to objects to get called:

1
2
3
4
5
auto l = [] {
std::cout << "hello lambda" << std::endl;
};
...
l(); // prints ‘‘hello lambda’’

lambda introducer,capture to access nonstatic outside objects inside the lambda.static objects such as std::cout can be used
|
mutable_opt throwSpec_opt->retType_opt
|
all of them are optional,bug if one of them occurs,the parentheses for the parameters are mandatory
mutable关系到[…]中的数据是否可以被改写(objects are passed by value,but inside the function object defined by the lambda, you have write access to the passed value.),可以取用外部变量
(…)函数的参数
retType,without any specific definition of the return type, it is deduced from the return value.
you can specify a capture to access data of outer scope that is not passed as an argument:
[=]means that the outer scope is passed to the lambda by value.
[&]means that the outer scope is passed to the lambda by reference.

1
2
3
4
Ex:
int x=0;
int y=42;
auto qqq=[x,&y]{...} //[=,&y]to pass y by reference and all other objects by value.y是by reference并且允许使用所有objects by value
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
//The type of a lambda is an anouymous function object (or functor)
int id = 0;
//objects are passed by value, but inside the functionnn object defined by the lambda, you have write access to the passed value.
auto f = [id]()mutable {
cout << "id: " << id << endl;
++id; //如果没写mutable,难道不能++id;吗?
};
id = 42;
f(); //0
f(); //1
f(); //2
cout << id << endl; //42

//等同于
class Functor {
private:
int id; //copy of outside id
public:
void operator()(){
cout << "id: " << id << endl;
++id; //OK
}
};
Functor f;

//[&id]
int id = 0;
auto f = [&id](int param) {
cout << "id: " << id << endl;
cout << "param: " << param << endl;
++id;
++param;
};
id = 42;
f(7); //id:42,param:7
f(7); //id:43,param:7
f(7); //id:44,param:7
cout << id << endl; //id:45

//无mutable,[Error] increment of read-only variable 'id'
int id = 0;
auto f = [id]() {
cout << "id: " << id << endl;
++id;
};
id = 42;
f();
f();
f();
cout << id << endl;

//
int id = 0;
auto f = [id]()mutable {
cout << "id: " << id << endl;
++id;
static int x = 5; //可以声明变量
int y = 6;
return id; //可以返回数值
};
f();

Here is what compiler generates for lambda’s:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
1
int tobefound = 5;
auto lambda1 = [tobefound](int val){return val == tobefound;};
2
class UnNamedLocalFunction{
private:
int localVar;
public:
UnNamedLocalFunction(int var):localVar(var){}
bool operator()(int val){
return val == localVar;
}
};
UnNamedLocalFunction lambda2(tobefound);
bool b1 = lambda1(5);
bool b2 = lambda2(5);

Spaces in Template Expressions

The requirement to put a space between two closing template expressions has gone

1
2
vector<list<int> >; // OK in each C++ version
vector<list<int>>; // OK since C++11

nullptr and std::nullptr_t

C++11 lets you use nullptr instead of 0 or NULL to specify that a pointer refers to no value (which differs from having an undefined value). This new feature especially helps to avoid mistakes that occurred when a null pointer was interpreted as an integral value. For example:

1
2
3
4
5
void f(int);
void f(void*);
f(0); // calls f(int)
f(NULL); // calls f(int) if NULL is 0, ambiguous otherwise
f(nullptr); // calls f(void*)

nullptr is a new keyword. It automatically converts into each pointer type but not to any integral type. It has type std::nullptr_t, defined in (see Section 5.8.1, page 161), so you can now even overload operations for the case that a null pointer is passed. Note that std::nullptr_t counts as a fundamental data type (see Section 5.4.2, page 127).

Automatic Type Deduction with auto

With C++11, you can declare a variable or an object without specifying its specific type by using auto.
For example:

1
2
3
auto i = 42; // i has type int
double f();
auto d = f(); // d has type double

The type of a variable declared with auto is deduced from its initializer. Thus, an initialization is required: auto i; // ERROR: can’t dedulce the type of i Additional qualifiers are allowed.
For example:

1
static auto vat = 0.19;

Using auto is especially useful where the type is a pretty long and/or complicated expression.
For example:

1
2
3
4
5
6
vector<string> v;
...
auto pos = v.begin(); // pos has type vector<string>::iterator
auto l = [] (int x) -> bool { // l has the type of a lambda
..., // taking an int and returning a bool
};

The latter is an object, representing a lambda

Uniform Initialization and Initializer Lists

Before C++11, programmers, especially novices, could easily become confused by the question of how to initialize a variable or an object. Initialization could happen with parentheses, braces, and/or assignment operators.
For this reason, C++11 introduced the concept of uniform initialization, which means that for any initialization, you can use one common syntax. This syntax uses braces, so the following is possible now:

1
2
3
4
5
6
int values[] { 1, 2, 3 };
std::vector<int> v { 2, 3, 5, 7, 11, 13, 17 };
std::vector<std::string> cities {
"Berlin", "New York", "London", "Braunschweig", "Cairo", "Cologne"
};
std::complex<double> c{4.0,3.0}; // equivalent to c(4.0,3.0)

其实是利用一个事实:编译器看到{t1,t2…tn}便做出一个关联至一个initializer_list,它关联至一个array<T,n>。调用函数(例如ctor)时该array内的元素可被编译器分解逐一传给函数。但若函数参数是个initializer_list,调用者却不能给予数个T参数然后以为它们会被自动转为一个initializer_list传入)

std::vectorstd::string cities {“Berlin”, “New York”, “London”, “Braunschweig”, “Cairo”, “Cologne”};,这形成一个initializer_list,背后有个array<string,6>。调用vectorctors时编译器找到一个vectorctor接受initializer_list。所有容器皆有类似于此ctor。

std::complex c{4.0,3.0}; // equivalent to c(4.0,3.0)
这形成一个initializer_list,背后有个array<double,2>。调用complexctor时该array内的2个元素被分解传给ctor。complex并无任何ctor接受initializer_list

An initializer list forces so-called value initialization, which means that even local variables of fundamental data types, which usually have an undefined initial value, are initialized by zero (or nullptr, if it is a pointer):

1
2
3
4
int i; // i has undefined value
int j{}; // j is initialized by 0
int* p; // p has undefined value
int* q{}; // q is initialized by nullptr

Note, however, that narrowing initializations — those that reduce precision or where the supplied value gets modified— are not possible with braces. For example:

1
2
3
4
5
6
7
8
int x1(5.3); // OK, but OUCH: x1 becomes 5
int x2 = 5.3; // OK, but OUCH: x2 becomes 5
int x3{5.0}; // ERROR: narrowing
int x4 = {5.3}; // ERROR: narrowing
char c1{7}; // OK: even though 7 is an int, this is not narrowing
char c2{99999}; // ERROR: narrowing (if 99999 doesn’t fit into a char)
std::vector<int> v1 { 1, 2, 4, 5 }; // OK
std::vector<int> v2 { 1, 2.3, 4, 5.6 }; // ERROR: narrowing doubles to ints

To support the concept of initializer lists for user-defined types, C++11 provides the class template std::initializer_list<>. It can be used to support initializations by a list of values or in any other place where you want to process just a list of values. For example:

1
2
3
4
5
6
7
8
9
void print (std::initializer_list<int> vals)
{
for (auto p=vals.begin(); p!=vals.end(); ++p) { // process a list of values
std::cout << *p << "\n";
}
}

print ({12,3,5,7,11,13,17}); // pass a list of values to print()
传给initializer_list者,一定必须也是个initializer_list(or{}形式)

cpp1.0(none explicit one argument ctor 才可以做隐式转换)
explicit for ctors taking one argument
cpp2.0
explicit for ctors taking more than one argument

range-based for statement

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
for ( decl : coll ) {
statement
}

for ( int i : { 2,3,4,5,6} ) {
cout << i << endl;
}

vector<double> vec;
...
for ( auto elem : vec ) {
cout << elem << endl;
}

for ( auto& elem : vec ) {
elem *= 3;
}

Note that no explicit type conversions are possible when elements are initialized as decl inside the for loop. Thus, the following does not compile:

1
2
3
4
5
6
7
8
9
10
class C
{
public:
explicit C(const std::string& s); // explicit(!) type conversion from strings
...
};
std::vector<std::string> vs;
for (const C& elem : vs) { // ERROR, no conversion from string to C defined
std::cout << elem << std::endl;
}

=default,=delete

如果你自行定义了一个ctor,那么编译器就不会再给你一个default ctor。
如果你强制加上=default,就可以重新获得并使用default ctor。

Alias Template ( template typedef )

1
2
3
4
5
template<typename T>
using Vec = std::vector<T,MyAlloc<T>>; //standard vector using own allocator
Vec<int> coll;
is equivalent to std::vector<int,MyAlloc<int>> coll;
It is not possible to partially or explicitly specialize an alias template.

Type Alias (similar to typedef)

1
2
3
4
5
6
//type alias,identical to
//typedef void (*func)(int,int);
using func = void(*)(int,int);

//the name 'func' now denotes a pointer to function: void example(int,int){}
func fn = example;

noexcept

1
void foo() noexcept;   ==>   void foo() noexcept(true);

declares that foo() won’t throw. If an exception is not handled locally inside foo() — thus, if foo() throws — the program is terminated, calling std::terminate(), which by default calls std::abort().

You can even specify a condition under which a function throws no exception. For example, for any type Type, the global swap() usually is defined as follows:

1
2
3
4
void swap (Type& x, Type& y) noexcept(noexcept(x.swap(y)))
{
x.swap(y);
}

Here, inside noexcept(…), you can specify a Boolean condition under which no exception gets thrown: Specifying noexcept without condition is a short form of specifying noexcept(true).

https://stackoverflow.com/questions/8001823/how-to-enforce-move-semantics-when-a-vector-grows

override

告诉编译器,子类要override父类的成员函数,让编译器帮助检查

1
2
3
4
5
6
7
8
struce Base{
virtual void vfunc(float){}
};

struct Derived2 : Base {
virtual void vfunc(int) override{} //[Error] marked override,bug does not override
virtual void vfunc(float) override{}
};

final

1
2
3
4
5
6
7
8
9
struct Base1 final{};
struct Derived1 : Base1{};//[Error] cannot derive from 'final' base 'Base1' in derived type 'Derived1'

struct Base2{
virtual void f() final;
};
struct Derived2 : Base2{
void f();//[Error] overriding final function 'virtual void Base2::f()'
};

decltype

By using the new decltype keyword, you can let the compiler find out the type of an expression. This is the realization of the often requested typeof feature. However, the existing typeof implementations were inconsistent and incomplete, so C++11 introduced a new keyword. For example:
GNU C++中的typeof并不是标准库的一部分

1
2
3
4
5
map<string, float> coll;
decltype(coll)::value_type elem;

这样写(before C++11
map<string, float>::value_type elem;

One application of decltype is to declare return types (see below). Another is to use it in metaprogramming (see Section 5.4.1, page 125) or to pass the type of a lambda (see Section 10.3.4, page 504).

defines a type equivalent to the type of an expression

应用:
1、decltype,used to declare return types
Sometimes, the return type of a function depends on an expression processed with the arguments.
However, something like

1
2
template <typename T1, typename T2>
decltype(x+y) add(T1 x, T2 y);

was not possible before C++11, because the return expression uses objects not introduced or in scope yet.
But with C++11, you can alternatively declare the return type of a function behind the parameter list:

1
2
template <typename T1, typename T2>
auto add(T1 x, T2 y) -> decltype(x+y);

This uses the same syntax as for lambdas to declare return types
[…] (…) mutable_opt throwSpec_opt ->retType_opt {…}
2、decltype, to used in metaprogramming
3、decltype, pass the type of a lambda
面对lambda,我们手上往往只有object,没有type。要获得其type就得借助于decltype。

1
2
3
4
5
6
7
auto cmp = [](const Persion& p1, const Person& p2) {
return p1.lastname() < p2.lastname() ||
(p1.lastname() == p2.lastname() &&
p1.firstname() < p2.firstname());
}

set<Person, decltype(cmp)>coll(cmp);

笔记来自 http://boolan.com/ 侯捷C++新标准C++11/14
内容引自《The C++ standard Library A Tutorial and reference》

数量不定的模板参数

1
2
3
4
5
6
7
首先确定编译器是否支持C++11
#include <iostream>
int main(int argc, char** argv) {
std::cout << __cplusplus << std::endl;
return 0;
}

VariadicTemplates特性最大的特点是可以用在函数递归(函数自己调用自己才叫recursive递归),tuple的做法