Configure an ELK cluster in docker containers - elasticsearch

I'm trying to configure an ELK cluster using 2 docker containers.
I'm using the following image:
es241_l240_k461: Elasticsearch 2.4.1, Logstash 2.4.0, and Kibana 4.6.1. (reference: https://hub.docker.com/r/sebp/elk/ )
I have created 2 docker containers for that image with docker-compose; each works perfectly in standalone mode.
I want to link the 2 ELK nodes between each other in way to create the cluster, but I haven't found a proper solution.
The Elasticsearch node in container1 doesn't communicate with the Elasticsearch node in container2.
These are the two docker-compose.yml:
CONTAINER1:
version: '2'
services:
elasticsearch01:
image: sebp/elk:es241_l240_k461
ports:
- "5601:5601"
- "9200:9200"
- "9300:9300"
- "5044:5044"
volumes:
- /opt/ELK1/logstash/conf.d:/etc/logstash/conf.d
privileged: true
CONTAINER2:
version: '2'
services:
elasticsearch02:
image: sebp/elk:es241_l240_k461
ports:
- "5602:5601"
- "9201:9200"
- "9301:9300"
- "5045:5044"
volumes:
- /opt/ELK2/logstash/conf.d:/etc/logstash/conf.d
privileged: true
I'have configured the elasticsearch.yml inside the docker containers in this way:
NODE IN CONTAINER1:
cluster.name: elasticsearchcluster
node.name: node1
network.host: 0.0.0.0
network.bind_host: 0.0.0.0
discovery.zen.ping.unicast.hosts: ["127.0.0.1", "172.21.0.2"]
discovery.zen.minimum_master_nodes: 1
NODE IN CONTAINER2:
cluster.name: elasticsearchcluster
node.name: node2
network.host: 0.0.0.0
network.bind_host: 0.0.0.0
discovery.zen.ping.unicast.hosts: ["127.0.0.1", "172.22.0.2"]
discovery.zen.minimum_master_nodes: 1
The key is the discovery.zen.ping.unicast.hosts parameter: I don't have the real IP address, because it's a docker container.
I tried docker inspect elasticsearch01, I have the following "IPAddress" property:
"NetworkSettings": {
...
"Networks": {
"ELK1_default": {
...
"Gateway": "172.22.0.1",
"IPAddress": "172.22.0.2",
...
}
}
}
But it doesn't work if I set that IP address.
How to configure the cluster properly?
EDIT
Trying the host ip-address and the port, the node 1 starts, the node 2 fails with no errors.
discovery.zen.ping.unicast.hosts: ["127.0.0.1", "192.168.0.1:9300"] -> OK
discovery.zen.ping.unicast.hosts: ["127.0.0.1", "192.168.0.2:9300"] -> FAILS with no errors

Instead of using a prepared docker file with ELK stack, you could go for something like this:
version: '3'
services:
elasticsearch:
image: elasticsearch:2.4.1
ports:
- 9200:9200
networks:
- elk
elasticsearch_slave:
image: elasticsearch:2.4.1
networks:
- elk
depends_on:
- elasticsearch
command: elasticsearch --discovery.zen.ping.unicast.hosts=elasticsearch
logstash:
image: logstash:2.3.3
hostname: logstash
networks:
- elk
volumes:
- ./logstash.conf:/config/logstash.conf
depends_on:
- elasticsearch
ports:
- 5044:5044
command: logstash -f /config/logstash.conf
kibana:
image: kibana:4.5.1
hostname: kibana
networks:
- elk
depends_on:
- elasticsearch
- logstash
ports:
- 5601:5601
networks:
elk:
driver: bridge
Once you start your images using docker-compose up -d, then you can scale slaves using following command docker-compose scale elasticsearch_slave=5
Once that's done - you'll have 5 slaves + client node that opens up port 9200 as a gateway to the whole cluster.
For instance, after doing that, http://localhost:9200/_cat/nodes?v displays following:

Thanks to Evaldas Buinauskas, I've found the solution with the stack!
First, we need only one docker-compose.yml.
In that file we need to configure two services (one for each container to create), and a network to be shared between the two services.
This is the new docker-compose.yml:
version: '2'
services:
elk1:
environment:
- bootstrap.memory_lock=true
- "ES_JAVA_OPTS=-Xms2048m -Xmx2048m"
image: sebp/elk:es241_l240_k461
networks:
- elk_net
ports:
- "5601:5601"
- "9200:9200"
- "9300:9300"
- "5044:5044"
volumes:
- /opt/elk/logstash/conf.d:/etc/logstash/conf.d
privileged: true
elk2:
environment:
- bootstrap.memory_lock=true
- "ES_JAVA_OPTS=-Xms2048m -Xmx2048m"
image: sebp/elk:es241_l240_k461
networks:
- elk_net
ports:
- "5602:5601"
- "9201:9200"
- "9301:9300"
- "5045:5044"
depends_on:
- elk1
volumes:
- /opt/elk/logstash/conf.d:/etc/logstash/conf.d
privileged: true
networks:
elk_net:
driver: bridge
The command docker-compose up will create 3 elements:
the container elk1
the container elk2
the network elk_net
With the docker network inspect elk_net command we can view the (docker) ip addresses assigned to the 2 containers.
The elasticsearch.yml files have to be configured as follows:
cluster.name: elasticsearchcluster
node.name: node1
network.host: 0.0.0.0
network.bind_host: 0.0.0.0
network.publish_host: ${IP_ADDRESS_ELK1}
discovery.zen.ping.unicast.hosts: ["${IP_ADDRESS_ELK2}"]
discovery.zen.minimum_master_nodes: 1
cluster.name: elasticsearchcluster
node.name: node2
network.host: 0.0.0.0
network.bind_host: 0.0.0.0
network.publish_host: ${IP_ADDRESS_ELK2}
discovery.zen.ping.unicast.hosts: ["${IP_ADDRESS_ELK1}"]
discovery.zen.minimum_master_nodes: 1
With this configuration, the cluster works perfectly: the two nodes are merged correctly and the Http get to each elasticsearch server returns all the documents saved in the 2 nodes.

Related

Could not communicate to Elasticsearch

I am trying to send my node app logs to fluentd to elasticsearch to kibana, but having a problem connecting fluentd with elasticsearch with docker. I want to dockerize this efk stack.
I have attached the folder structure and shared relevant files.
Following is the folder structure:
Error
Could not communicate to Elasticsearch, resetting connection and trying again. Connection refused - connect(2) for 172.20.0.2:9200 (Errno::ECONNREFUSED)
fluent.conf:
#type forward
port 24224
bind 0.0.0.0
</source>
<match *.**>
#type copy
<store>
#type elasticsearch
host elasticsearch
port 9200
user elastic
password pass
</store>
</match>
DockerFile
FROM fluent/fluentd:v1.15-1
USER root
RUN gem install elasticsearch -v 7.6.0
# RUN gem install fluent-plugin-elasticsearch -v 7.6.0
RUN gem install fluent-plugin-elasticsearch -v 4.1.1
RUN gem install fluent-plugin-rewrite-tag-filter
RUN gem install fluent-plugin-multi-format-parser
USER fluent
Docker-compose.yml
version: '3'
services:
fluentd:
build: ./fluentd
container_name: loggingFluent
volumes:
- ./fluentd/conf:/fluentd/etc
# - ./fluentd/conf/fluent.conf:/fluentd/etc/fluent.conf
ports:
- "24224:24224"
- "24224:24224/udp"
links:
- elasticsearch
depends_on:
- elasticsearch
- kibana
elasticsearch:
image: docker.elastic.co/elasticsearch/elasticsearch:7.8.1
container_name: elasticsearch-Logging
ports:
- 9200:9200
expose:
- 9200
environment:
discovery.type: 'single-node'
ES_JAVA_OPTS: '-Xms1024m -Xmx1024m'
xpack.security.enabled: 'true'
ELASTIC_PASSWORD: 'pass'
kibana:
image: docker.elastic.co/kibana/kibana:7.8.1
container_name: kibana-Logging
volumes:
- ./kibana.yml:/usr/share/kibana/config/kibana.yml
ports:
- 5601:5601
depends_on:
- elasticsearch
links:
- elasticsearch
Maybe I am missing some with docker networking because I am using docker for the first time I have checked the ports exposed by docker containers and they are fine. I have done this without docker and have used the same settings but having a problem doing it with docker. Looking forward to seeing your responses. Thank you very much.
Adding a username to the elastic search environment solved the issue :
elasticsearch-environment
environment:
discovery.type: 'single-node'
ES_JAVA_OPTS: '-Xms1024m -Xmx1024m'
xpack.security.enabled: 'true'
ELASTIC_PASSWORD: 'pass'
ELASTIC_USERNAME: 'elastic'

Nginx cannot connect fluentd in EFK stack

I am setting up a stack with an application consisting of nginx, redis, mysql, myapp. Nginx proxies requests to myapp. I want to send logs from nginx to EFK stack, but an error occurs when starting the nginx service:
Error response from daemon: dial tcp 127.0.0.1:24224: connect: connection refused
docker-compose.yml for stack with myapp
version: "3.8"
services:
nginx:
image: nginx:alpine
deploy:
mode: replicated
replicas: 2
labels:
- traefik.enable=true
- traefik.http.routers.node1.rule=Host(`${NODE1}`)
- traefik.http.routers.node1.service=nginx
- traefik.http.routers.node2.rule=Host(`${NODE2}`)
- traefik.http.routers.node2.service=nginx
- traefik.http.routers.node3.rule=Host(`${NODE3}`)
- traefik.http.routers.node3.service=nginx
- traefik.http.services.nginx.loadbalancer.server.port=80
placement:
constraints:
- node.role == manager
logging:
driver: fluentd
options:
fluentd-address: localhost:24224
tag: nginx-
volumes:
- ./nginx/default.conf:/etc/nginx/conf.d/default.conf
ports:
- 80:80
depends_on:
- myapp
networks:
- traefik-public
...
All stacks are in the same traefik-public network, if you make ping fluentd from any container, fluentd responds
Part of efk.yml
version: "3.7"
services:
fluentd:
image: registry.rebrainme.com/docker_users_repos/3912/dkr-30-voting/fluentd
deploy:
mode: global
volumes:
- /mnt/fluent.conf:/fluentd/etc/fluent.conf
ports:
- "24224:24224"
- "24224:24224/udp"
depends_on:
- elasticsearch
- kibana
networks:
- traefik-public
...
fluent.conf
<source>
#type forward
port 24224
bind localhost
</source>
<match *.**>
#type copy
<store>
#type elasticsearch
host elasticsearch
port 9200
logstash_format true
logstash_prefix fluentd
logstash_dateformat %Y%m%d
include_tag_key true
type_name access_log
tag_key #log_name
flush_interval 1s
</store>
<store>
#type stdout
</store>
</match>
I ask for help
Tldr;
Because you are using 2 compose files. docker-compose.yml and efk.yml They are not sharing the same value for the network.
To Fix
Combine both file in a single one.
To Fix (with still 2 files separated)
You should first off all create a network.
docker network create traefik-public
Then update both compose file with
networks:
default:
external:
name: traefik-public
This should make it work.
In order for there to be a connection between the efk stack and the application stack, it is necessary to bind the fluentd port to the host port
version: "3.7"
services:
fluentd:
image: my_fluentd_image:latest
deploy:
mode: global
configs:
- source: fluent-conf
target: /fluentd/etc/fluent.conf
ports:
- target: 24224
published: 24224
protocol: tcp
mode: host
depends_on:
- elasticsearch
- kibana
networks:
- traefik-public

Why elasticsearch on docker swarm requires a transport.host=localhost setting?

I'm trying to run Elasticsearch on an docker swarm. It works as a single node cluster for now, but only when the transport.host=localhost setting is included. Here is main part of docker-compose.yml:
version: "3"
services:
elasticsearch:
image: "elasticsearch:7.4.1" #(base version)
hostname: elasticsearch
ports:
- "9200:9200"
environment:
- cluster.name=elasticsearch
- bootstrap.memory_lock=true
- ES_JAVA_OPTS=-Xms512m -Xmx512m
- transport.host=localhost
volumes:
- "./elasticsearch/volumes:/usr/share/elasticsearch/data"
networks:
- logger_net
volumes:
logging:
networks:
logger_net:
external: true
Above configuration results in the yellow cluster state (because some indexes require additional replica).
Elasticsearch status page is unavailable when I'm using IP of the elasticsearch docker container in a transport.host setting or without a transport.host=localhost setting.
I think that using a transport.host=localhost setting is wrong. Is proper configuration of Elasticsearch in docker swarm available?

How to use the official docker elasticsearch container?

I have the following Dockerfile:
FROM docker.elastic.co/elasticsearch/elasticsearch:5.4.0
RUN elasticsearch
EXPOSE 80
I think the 3rd line is never reached.
When I try to access the dockercontainer from my local machine through:
172.17.0.2:9300
I get nothing, what am I missing? I want to access elasticsearch from the local host machine.
I recommend using docker-compose (which makes lot of things much easier) with following configuration.
Configuration (for development)
Configuration starts 3 services: elastic itself and extra utilities
for development like kibana and head plugin (these could be omitted, if you don't need them).
In the same directory you will need three files:
docker-compose.yml
elasticsearch.yml
kibana.yml
With following contents:
docker-compose.yml
version: '2'
services:
elasticsearch:
image: docker.elastic.co/elasticsearch/elasticsearch:5.4.0
container_name: elasticsearch_540
environment:
- http.host=0.0.0.0
- transport.host=0.0.0.0
- "ES_JAVA_OPTS=-Xms1g -Xmx1g"
volumes:
- esdata:/usr/share/elasticsearch/data
- ./elasticsearch.yml:/usr/share/elasticsearch/config/elasticsearch.yml
ports:
- 9200:9200
- 9300:9300
ulimits:
memlock:
soft: -1
hard: -1
nofile:
soft: 65536
hard: 65536
mem_limit: 2g
cap_add:
- IPC_LOCK
kibana:
image: docker.elastic.co/kibana/kibana:5.4.0
container_name: kibana_540
environment:
- SERVER_HOST=0.0.0.0
volumes:
- ./kibana.yml:/usr/share/kibana/config/kibana.yml
ports:
- 5601:5601
headPlugin:
image: mobz/elasticsearch-head:5
container_name: head_540
ports:
- 9100:9100
volumes:
esdata:
driver: local
elasticsearch.yml
cluster.name: "chimeo-docker-cluster"
node.name: "chimeo-docker-single-node"
network.host: 0.0.0.0
http.cors.enabled: true
http.cors.allow-origin: "*"
http.cors.allow-headers: "Authorization"
kibana.yml
server.name: kibana
server.host: "0"
elasticsearch.url: http://elasticsearch:9200
elasticsearch.username: elastic
elasticsearch.password: changeme
xpack.monitoring.ui.container.elasticsearch.enabled: true
Running
With above three files in the same directory and that directory set as current working directory you do (could require sudo, depends how you have your docker-compose set up):
docker-compose up
It will start up and you will see logs from three different services: elasticsearch_540, kibana_540 and head_540.
After initial start up you will have your elastic cluster available for http under 9200 and for tcp under 9300. Validate with following curl if the cluster started up:
curl -u elastic:changeme http://localhost:9200/_cat/health
Then you can view and play with your cluster using either kibana (with credentials elastic / changeme):
http://localhost:5601/
or head plugin:
http://localhost:9100/?base_uri=http://localhost:9200&auth_user=elastic&auth_password=changeme
Your container is auto exiting because of insufficient virtual memory, by default to run an elastic search container your memory should be a min of 262144 but if you run this command sysctl vm.max_map_countand see it will be around 65530. Please increase your virtual memory count by using this command sysctl -w vm.max_map_count=262144 and run the container again docker run IMAGE IDthen you should have your container running and you should be able to access elastic search at port 9200 or 9300
edit : check this link https://www.elastic.co/guide/en/elasticsearch/reference/5.0/vm-max-map-count.html#vm-max-map-count
Best would be to follow the official elasticsearch documentation which has a nice section on single node elasticsearch cluster Also running a multi-node elasticsearch cluster using docker-compose.
Please refer to version specific documentation, which can be accessed in the version drop-down present in elasticsearch official documentation.

Docker scale and elasticsearch

The public docker image for elasticsearch is on docker hub
https://hub.docker.com/_/elasticsearch/
If i defined my own docker-compose file with elasticsearch, how would i scale up elasticsearch so that the ports don't collide?
version: '2'
services:
elasticsearch:
image: elasticsearch:latest
ports:
- "9200:9200"
- "9300:9300"
kibana:
image: kibana
ports:
- 5601:5601
environment:
- ELASTICSEARCH_URL=http://elasticsearch:9200
How could i scale this up, similar to the command below?
docker-compose scale elasticsearch=3
I am running docker beta for mac version 1.12.
Thanks,
Shane.
If you just want the ports don't collide, we should use "automatic port mapping" with docker-compose.yml as below:
version: '2'
services:
elasticsearch:
image: elasticsearch:latest
ports:
- 9200
- 9300
So Docker will automatically map ports 9200 and 9300 to random ports in range 32xxx.

Resources