[集群搭建]记录使用docker搭建elasticsearch集群

来源:互联网 发布:手机淘宝无法登录 编辑:程序博客网 时间:2024/05/23 11:49

本文记录使用docker搭建elasticsearch集群的整个过程(文中使用的2.1.2举例),过程亲测同样适用于elasticsearch2.x,5.x,后续作者将继续深入研究es,下一步准备基于此集群对源生elasticsearch(以下简称es)做改造测试。


1、 环境介绍

本文运行环境 ubuntu16.04 + docker17.05 + 官网上下载的elasticsearch2.1.2,另外docker环境为openjdk:8-jre-alpine。(使用alpine的原因就是没有太多不必要的组件和命令,docker内部也不需要太多组件)
es源码下载地址

1.1 ubuntu

$ cat /proc/versionLinux version 4.4.0-46-generic (buildd@lcy01-10) (gcc version 5.4.0 20160609 (Ubuntu 5.4.0-6ubuntu1~16.04.2) ) #67-Ubuntu SMP Thu Oct 20 15:05:12 UTC 2016

1.2 docker

$ docker -vDocker version 17.05.0-ce, build 89658be

1.3 elasticsearch(版本忽略)

$ ./elasticsearch -versionVersion: 2.1.2, Build: c849dd1/2017-04-24T16:18:17Z, JVM: 1.8.0_101

2、 部署过程中遇到的问题

2.1 主要就是docker的网络配置,默认是桥接网络,不知为何多个node启动来之后无法互相发现。

解决方案:修改elasticsearch.yml配置。

2.2 每次重启docker实例docker自动会重新分配ip。

未解决。


3、 部署过程

3.1 制作生成es的dockerfile.

参照dockerfile的git地址,如下图。

图 es-dockerfile

3.2 在es源文件中为es安装head插件。

$ plugin install mobz/elasticsearch-head

3.3 生成es的docker镜像

镜像名称为psiitoy/elasticsearch:2.1.2

$ docker build -t psiitoy/elasticsearch:2.1.2 .

3.4 查看已有网桥信息。

docker 默认使用docker0作为网桥

$ brctl showbridge name bridge id       STP enabled interfacesdocker0     8000.0242552a7fb0   no      vetha061837

3.5 查看网桥对应网段地址。

发现网段为172.17.0.x

$ ip addr show docker04: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default     link/ether 02:42:55:2a:7f:b0 brd ff:ff:ff:ff:ff:ff    inet 172.17.0.1/16 scope global docker0       valid_lft forever preferred_lft forever    inet6 fe80::42:55ff:fe2a:7fb0/64 scope link        valid_lft forever preferred_lft forever

3.6 修改elasticsearch.yml配置。

避免docker容器es服务之间无法互相发现导致的脑裂。
参照Elasticsearch部分节点不能发现集群(脑裂)问题处理

network.host: 0.0.0.0discovery.zen.ping.multicast.enabled: falsediscovery.zen.ping_timeout: 120sdiscovery.zen.minimum_master_nodes: 2 #至少要发现集群可做master的节点数,client.transport.ping_timeout: 60sdiscovery.zen.ping.unicast.hosts: ["172.17.0.2", "172.17.0.3"]

3.7 创建docker容器x5。

docker run 参数介绍:
在使用 -v 参数时,代表把本地目录挂载到镜像里,我们可以在本机查看容器中的/usr/share/elasticsearch/logs目录。
在使用 -d 参数时,容器启动后会进入后台。

$ docker run -d -v ~/usr/share/elasticsearch/logs:/usr/share/elasticsearch/logs psiitoy/elasticsearch:2.1.266ca0270ef44$ docker run -d -v ~/usr/share/elasticsearch/logs:/usr/share/elasticsearch/logs psiitoy/elasticsearch:2.1.2ddfbb7ef65bc

3.8 若想进入容器可以执行 docker exec -it $CONTAINER_ID

在使用 -i 参数时,打开STDIN,用于控制台交互
在使用 -t 参数时,分配tty设备,该可以支持终端登录,默认为false

$ docker exec -it 66ca0270ef44 /bin/bashbash-4.3#

3.9 查看集群状态

curl http://ip:port/_cat/health?v,也可以用health?pretty
我们看到集群有5个节点加入了,实验成功!

$ curl http://172.17.0.2:9200/_cat/health?vepoch      timestamp cluster       status node.total node.data shards pri relo init unassign pending_tasks max_task_wait_time active_shards_percent 1497352537 11:15:37  elasticsearch green           5         5      0   0    0    0        0             0                  -                100.0% 

3.10 测试一下用客户端创建索引

创建一个 number_of_shards为8,number_of_replicas为1 的名叫twitter的index。
参照testClient的git地址

public class ClientTest {    private static Client client = null;//client一定要是单例,单例,单例!不要在应用中构造多个客户端!    public static void main(String[] args) {        try {            client = getClient("elasticsearch", "172.17.0.3", 9300);//client一定要是单例,单例,单例!不要在应用中构造多个客户端!            createIndex("twitter", "tweet");            System.out.println("#" + client);        } catch (Exception e) {            e.printStackTrace();        } finally {            if (client != null) {                client.close();            }        }    }    /**     * 创建es client 一定要是单例,单例,单例!不要在应用中构造多个客户端!     * clusterName:集群名字     * nodeIp:集群中节点的ip地址     * nodePort:节点的端口     *     * @return     * @throws UnknownHostException     */    public static synchronized Client getClient(String clusterName, String nodeIp, int nodePort) throws UnknownHostException {        //设置集群的名字        Settings settings = Settings.settingsBuilder()                .put("cluster.name", clusterName)                .put("client.transport.sniff", false)//                .put("number_of_shards", 1)//                .put("number_of_replicas", 0)                .build();        //创建集群client并添加集群节点地址        Client client = TransportClient.builder().settings(settings).build()//                .addTransportAddress(new InetSocketTransportAddress("192.168.200.195", 9370))//                .addTransportAddress(new InetSocketTransportAddress("192.168.200.196", 9370))//                .addTransportAddress(new InetSocketTransportAddress("192.168.200.197", 9370))//                .addTransportAddress(new InetSocketTransportAddress("192.168.200.198", 9370))                .addTransportAddress(                        new InetSocketTransportAddress(InetAddress.getByName(nodeIp),                                nodePort));        return client;    }    /**     * 创建索引     * 注意:在生产环节中通知es集群的owner去创建index     * @param indexName     * @param documentType     * @throws IOException     */    private static void createIndex(String indexName, String documentType) throws IOException {        final IndicesExistsResponse iRes = client.admin().indices().prepareExists(indexName).execute().actionGet();        if (iRes.isExists()) {            client.admin().indices().prepareDelete(indexName).execute().actionGet();        }        client.admin().indices().prepareCreate(indexName).setSettings(Settings.settingsBuilder().put("number_of_shards", 8).put("number_of_replicas", 1)).execute().actionGet();        XContentBuilder mapping = jsonBuilder()                .startObject()                .startObject(documentType)//                     .startObject("_routing").field("path","tid").field("required", "true").endObject()                .startObject("_source").field("enabled", "true").endObject()                .startObject("_all").field("enabled", "false").endObject()                .startObject("properties")                .startObject("user")                .field("store", true)                .field("type", "string")                .field("index", "not_analyzed")                .endObject()                .startObject("message")                .field("store", true)                .field("type","string")                .field("index", "analyzed")                .field("analyzer", "standard")                .endObject()                .startObject("price")                .field("store", true)                .field("type", "float")                .endObject()                .startObject("nv1")                .field("store", true)                .field("type", "integer")                .field("index", "no")                .field("null_value", 0)                .endObject()                .startObject("nv2")                .field("store", true)                .field("type", "integer")                .field("index", "not_analyzed")                .field("null_value", 10)                .endObject()                .startObject("tid")                .field("store", true)                .field("type", "string")                .field("index", "not_analyzed")                .endObject()//                               .startObject("location")//                                    .field("store", true)//                                  .field("type", "geo_point")//                                  .field("lat_lon", true)//                                  .field("geohash", true)//                                  .field("geohash_prefix", true)//                                  .field("geohash_precision", 7)//                               .endObject()//                               .startObject("shape")//                                    .field("store", true)//                                  .field("type", "geo_shape")//                                  .field("geohash", true)//                                  .field("geohash_prefix", false)//                                  .field("geohash_precision", 7)//                               .endObject()                .startObject("endTime")                .field("type", "date")                .field("store", true)                .field("index", "not_analyzed")                //2015-08-21T08:35:13.890Z                .field("format", "yyyy-MM-dd HH:mm:ss||yyyy-MM-dd'T'HH:mm:ss.SSSZ")                .endObject()                .startObject("date")                .field("type", "date")//                                  .field("store", true)//                                  .field("index", "not_analyzed")                //2015-08-21T08:35:13.890Z//                                  .field("format", "yyyy-MM-dd HH:mm:ss||yyyy-MM-dd'T'HH:mm:ss.SSSZ")                .endObject()                .endObject()                .endObject()                .endObject();        client.admin().indices()                .preparePutMapping(indexName)                .setType(documentType)                .setSource(mapping)                .execute().actionGet();    }}

3.11 查看head集群信息,成功了。

图 es-head-cluster

3.12 停止并删除所有docker容器

-f参数强制停止删除

$ docker rm -f $(docker ps -aq)b1b17d0f41eb55d9259ff921ff4d4257521366ca0270ef44ddfbb7ef65bc

原创粉丝点击