【實驗級】Docker-Compose搭建單服務器ELK僞集羣

本文說明

因爲最近在搭ELK的日誌系統,爲了演示方案搭了個單臺服務器的日誌系統,就是前一篇文章中所記,其實這些筆記已經整理很久了,一直在解決各類問題就沒有發出來。在演示過程當中我提到了兩個方案,其中之一來自於【原創】分佈式之elk日誌架構的演進一文中的中級版,另外一天然是使用日誌直接輸出到Kafka.html

爲了讓這個看起來還不錯的方案落地,領導決定把這些中間件,服務等都虛擬化,作成docker容器,如今仍在試驗階段,因此作了有點不合理的設計,把這些容器都佈署在同一臺服務器上!爲了能實現這種假想式的設計,作了這次嘗試,也爲了瞭解這個集羣是否可行性後期拆分參考。你們若是本身電腦內存有16G以上可用的,能夠嘗試下這個腳本,話很少說,把以前準備的腳本和文檔發出來,給你們個參考。前端

本文不包含kafka以前的日誌採集部分,這部分能夠參考使用本人的LogDemo https://github.com/HellxZ/LogDemo.gitnode

聲明

若是有人擅自使用本文內容放到本身公司生產環境中,出現的全部問題,後果自負,一率與本人無關!nginx

環境準備

  • Debain Stretch 9.9 16G內存
  • Docker 18.09.6
  • Docker-Compose 1.17.1
  • Java 8 及以上

文檔部分

服務器環境準備

1.確認端口號是否有衝突git

爲了保證環境一致,請仔細查看以下設置是否與當前服務器端口占用有衝突、映射是否有問題github

服務名 服務功能說明 容器名 端口號
es-master Elasticsearch主節點,不存數據:防止腦裂問題 es-cluster-master 19200
es-slave1 Elasticsearch從節點1,存數據 es-cluster-slave1 19201
es-slave2 Elasticsearch從節點2,存數據 es-cluster-slave2 19202
es-slave3 Elasticsearch從節點3,存數據 es-cluster-slave3 19203
es-balance Elasticsearch鏈接節點,不存數據,供Kibana與Logstash鏈接 es-cluster-balance 19204
kibana Elasticsearch數據可視化前端 kibana 15601
zookeeper 分佈式協調中間件,用於Kafka集羣的master節點的選取 zookeeper 12181
kafka1 Kafka節點,做業務緩衝存,保證服務可靠性、數據不易丟失 kafka1 9091
kafka2 同上 kafka2 9092
kafka3 同上 kafka3 9093
kafka-manager 管理kafka集羣的前端,能夠查看集羣健康狀態等 kafka-manager 19000
logstash1 Logstash節點,日誌數據消費、日誌分詞、轉儲到Elasticsearch集羣 logstash-1 9601
logstash2 同上 logstash-2 9602
logstash3 同上 logstash-3 9603

這裏邊佔用的端口號均爲宿主機的,爲了防止出現衝突,前邊加1都作了處理,若是仍有衝突,請聯繫我chrome

2.肯定docker與docker-compose安裝docker

安裝docker與配置國內鏡像請參閱CentOS安裝Docker-ce並配置國內鏡像json

sudo docker -v #查看docker版本,若是正常說明docker已經安裝,能夠參考把當前登陸用戶加入docker組,來去除sudo

Docker默認使用root用戶權限才能執行,若是想使用普通用戶執行docker還不想用sudo,可使用以下命令bootstrap

sudo usermod -aG docker 要使用的用戶名

如此操做需重啓方可生效

安裝docker-compose

sudo curl -L "https://github.com/docker/compose/releases/download/1.24.0/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose

sudo chmod +x /usr/local/bin/docker-compose #賦執行權限

查看docker-compose是否安裝

docker-compose -v #查看docker-compose版本

3./etc/hosts修改

因爲Kafka須要進行域名映射,而咱們使用服務的時候頗有多是內網,因此,這裏咱們經過修改hosts配置文件,來達到局域網內其它服務的訪問

sudo vim /etc/hosts
#追加以下內容
#kafka hosts
本機ip    kafka1
本機ip    kafka2
本機ip    kafka3

其中本機ip是當前主機的內網ip,若是微服務與其它服務不在同一臺服務器,咱們還須要配置nginx使用stream監聽指定端口, IP也變成了外網的ip,此條待測

4.Centos7修改systemd的配置文件

vim /etc/systemd/system.conf
#添加如下內容
DefaultLimitNOFILE=65536
DefaultLimitNPROC=32000
DefaultLimitMEMLOCK=infinity

修改此處的目的在於須要對Elasticsearch內存進行限制,在systemd管理下若是不設置elasticsearch的限制,有很大可能出現內存溢出與服務器宕機

5.減小swap分區的使用與生產環境es配置

sudo echo "vm.swappiness=0" >> /etc/sysctl.conf #追加盡少使用swap配置
grep vm.max_map_count /etc/sysctl.conf #查看內存權限大小,若是低於262144,須要設置爲最小262144
sudo sysctl -p #使配置文件當即生效

減小swap分區使用,而不是禁用,此方式可使elasticsearch與kafka的性能保持穩定

配置文件準備

1.複製elk-docker配置文件夾到當前用戶有讀寫權限的目錄中

複製elk-docker文件夾到啓動docker用戶可訪問的目錄

sudo chown -R 當前用戶:當前用戶組 elk-docker  #賦權訪問

2.修改文件夾下的logstash/config下的兩個文件內容

如你所見,此文件夾下有logstash.conf 與logstash.yml兩個文件,下邊分別進行修改

修改logstash.yml文件

修改xpack.monitoring.elasticsearch.hosts中的ip爲當前內網ip

修改logstash.conf文件

找到output/elasticsearch下的hosts,把這個ip地址也改爲當前內網ip

3..env文件的使用

爲了便於運維和實施,在與此文檔同級的目錄下有一個配置文件名爲.env,這個文件是經過運維實施人員修改配置之用,下邊對裏邊須要用到的參數一一說明

  • HOST_IP: 設置宿主機內網ip,爲kibana提供鏈接,須要改
  • ES_JVM_OPTS: 每一個Elasticsearch實例的jvm啓動參數,可指定啓動內存與最大內存,默認-Xms256m -Xmx256m,能夠不改,但不能再改小了
  • ES_MASTER_DATA_DIR:Elasticsearch master節點的數據目錄
  • ES_SLAVE1_DATA_DIR:Elasticsearch slave1節點的數據目錄
  • ES_SLAVE2_DATA_DIR:Elasticsearch slave2節點的數據目錄
  • ES_SLAVE3_DATA_DIR:Elasticsearch slave3節點的數據目錄
  • ES_BALANCE_DATA_DIR:Elasticsearch balance節點的數據目錄
  • LOGSTASH_CONFIG_DIR: Logstash的配置文件目錄,無需改

上邊提到的ES開頭變量的指向的是宿主機目錄,若是自行指定,雖然啓動集羣時自動建立目錄,可是沒法正確訪問的,緣由是建立這些文件夾的是root用戶,而es使用的是啓動docker的帳戶,固然了,若是都是在root用戶下執行天然沒問題,可使用ls -alh查看,不推薦在正式環境中直接使用root用戶

啓動集羣服務

啓動前請確保es的數據目錄能夠被docker用戶訪問,正確建立

sudo docker-compose up -d #項目後臺啓動,沒有報錯,正確輸出多個服務

docker&docker-compose經常使用命令

#查看各服務日誌
docker logs -f 容器名或容器id
#查看當前運行中的容器
docker ps
#關閉docker-compose全部服務
cd docker-compose.yml所在的目錄
docker-compose down #關閉該文件中定義的全部服務 並 移除集羣的虛擬網卡
#強制刪除全部容器,不管是開着的仍是已經關閉的
docker rm -f $(docker ps -qa)
#進入正在運行的容器中
docker exec -it 容器名或容器id bash   #使用bash打開

集羣管理與功能使用

Elasticsearch-head插件

安裝chrome插件elasticsearch-head,鏈接到主機的19200端口,進行查看,除些以外,能夠經過當前ip:19200/_cat/health來查看當前集羣狀態

添加完成後,點擊圖標,以下圖

其中green說明集羣健康徹底可用。yellow說明有節點掛了,部分可用。red集羣不可用

除了直接能夠看到的,咱們還能夠

  • 經過索引來查看當前es索引庫中有哪些索引
  • 經過基本查詢使用簡單查詢功能,須要簡單查詢語法瞭解
  • 經過複合查詢使用複合查詢功能,固然使用這個功能須要瞭解複合查詢語法

查詢功能可使用kibana進行查詢,那個更方便一些

查看索引數據,點擊右側指定的名稱便可查看保存的源數據

Kafka-Manager

使用主機ip:1900,如圖添加集羣

拖到最下方,點save.以下圖添加成功

點擊Go to cluster view 當即查看集羣

點擊左上方Clusters也能夠看到集羣以下圖,之後進來也是這個界面。點擊集羣名便可查看,如上圖示

具體使用kafkaManager請參考官方github: https://github.com/yahoo/kafka-manager

Kibana

訪問kibana服務器ip:15601/app/kibana#/discover?_g=()

咱們能夠在Filters處直接搜索要找的日誌,固然也可使用kql,詳情見官網。

添加篩選能夠爲咱們提供更準確的日誌搜索,好比當前咱們用message就是日誌的內容,能夠以下操做

咱們還能夠經過時間來過濾日誌

kibana左下角有個隱藏按鈕,咱們打開看看

ps: 暫時咱們用到的也就是開始的時候建立索引,以及後續用的Discover與開發工具

腳本部分

這裏先把腳本與文件結構先列出來

elk-docker/
├── docker-compose.yml
├── .env
├── es-data
│   ├── es-balance-data
│   ├── es-master-data
│   ├── es-slave1-data
│   ├── es-slave2-data
│   └── es-slave3-data
├── logstash
│   └── config
│       ├── logstash.conf
│       └── logstash.yml
└── ReadMeFirst.md

8 directories, 5 files

這裏es-data下的全部都是文件夾,logstash文件夾爲配置文件夾(官網沒給Docker設置的部分),docker-compose.yml就是咱們的腳本,ReadMeFirst.md就是上邊的文檔部分,分別貼出來,好像git不會提交空文件夾,這裏就不放github上了。

這裏有一個.env文件是用來設置傳入參數的,docker-compose若是想一會兒跑起來集羣,是不能傳參的,不過.env提供了默認的參數,在docker-compose.yml 中能夠很方便的取到

具體須要改的地方,請參見上邊文檔部分吧。

.env

# .env file for docker-compose default. please be careful.

# kibana use HOST_IP to connect to elasticsearch, need to change it to host machine intranet ip
HOST_IP=10.2.114.110

# elasticsearch's JVM args setting, for every elasticsearch instance.
# -Xms is es boostrap occupied memory size
# -Xmx is the biggest memory es can use.
ES_JVM_OPTS=-Xms256m -Xmx256m

# WARNINGS: after you set elasticsearch data dirs, you must mkdirs with login user.
# because the es-cluster need to save data to dirs. if you use root to create folders, they can not save data then cluster down.

# the es-master data mount dir set
ES_MASTER_DATA_DIR=./es-data/es-master-data
# the es-slave1 data mount dir set
ES_SLAVE1_DATA_DIR=./es-data/es-slave1-data
# the es-slave2 data mount dir set
ES_SLAVE2_DATA_DIR=./es-data/es-slave2-data
# the es-slave3 data mount dir set
ES_SLAVE3_DATA_DIR=./es-data/es-slave3-data
# the es-balance data mount dir set, ofcourse this node have no data but node info.
ES_BALANCE_DATA_DIR=./es-data/es-balance-data

# logstash config dir mount set. change inside dir config file to change logstash cluster settings.
# default use relation path. don't change if you don't know what means.
LOGSTASH_CONFIG_DIR=./logstash/config

# kafka bootstrap create topic name
# by default is TOPIC_NAME=all_logs:1:1, "all_logs" is topic's name, first "1" means have one partition, last 1 means have one replicas.
# it's also can set TOPIC_NAME=topicName:patitionSum:replicasNum:cleanupPolicy, e.g. "Topic1:1:3:compact", and that can also set multiple topics,such as "Topic1:1:3,Topic2:2:4:compact"
# the multiple topics separator default is "," you can set new separator by "KAFKA_CREATE_TOPICS_SEPARATOR".
KAFKA_BOOTSTRAP_CREATE_TOPICS=all_logs:1:1

docker-compose.yml

version: "3"
services:
    es-master: # use to be Tribe Node & Master Node, with no data save.
        image:  elasticsearch:7.1.0
        container_name: es-cluster-master
        environment: # setting container env
            - cluster.name=es-cluster
            - node.name=es-master
            - cluster.initial_master_nodes=es-master
            - node.master=true   # specific this node is master node.
            - node.data=false    # master node don't save data to prevent cluster down.
            - http.cors.enabled=true    # solve cross origin
            - http.cors.allow-origin=*
            - bootstrap.memory_lock=true    # lock bootstrap memory.
            - ES_JAVA_OPTS=${ES_JVM_OPTS}   # set es bootstrap jvm args
        ports:
            - "19200:9200"
        expose: # expose ports let other containers link it
            - "9200"    # let kibana connect this port. 
            - "9300"    # use this port let cluster other nodes to discovery.
        restart: always
        volumes:        # mount host's dirs
            - ${ES_MASTER_DATA_DIR}:/usr/share/elasticsearch/data:rw
        networks: 
            - elk-network
    es-slave1:
        image:  elasticsearch:7.1.0
        container_name: es-cluster-slave1
        depends_on:
            - es-master
        environment: # setting container env
            - cluster.name=es-cluster
            - node.name=slave1
            - node.master=false # no master and saving data
            - node.data=true
            - cluster.initial_master_nodes=es-master # point to init master node name.
            - discovery.zen.ping.unicast.hosts=es-master # unique master         
            - bootstrap.memory_lock=true    # lock bootstrap memory.
            - ES_JAVA_OPTS=${ES_JVM_OPTS}
        ports:
            - "19201:9200"
        expose: # expose ports let other containers link it
            - "9300"
        restart: always
        volumes:        # mount host's dirs to save data, has read and write privilege
            - ${ES_SLAVE1_DATA_DIR}:/usr/share/elasticsearch/data:rw
        networks: 
            - elk-network
    es-slave2:
        image:  elasticsearch:7.1.0
        container_name: es-cluster-slave2
        depends_on:
            - es-master
        environment: # setting container env
            - cluster.name=es-cluster
            - node.name=slave2
            - node.master=false
            - node.data=true
            - cluster.initial_master_nodes=es-master
            - discovery.zen.ping.unicast.hosts=es-master           
            - bootstrap.memory_lock=true    # lock bootstrap memory.
            - ES_JAVA_OPTS=${ES_JVM_OPTS}
        ports:
            - "19202:9200"
        expose: # expose ports let other containers link it
            - "9300"
        labels:         # add description
            com.jiuqi.description: "elk-cluster-slave2 on docker"
        restart: always
        volumes:        # mount host's dirs
            - ${ES_SLAVE2_DATA_DIR}:/usr/share/elasticsearch/data:rw 
        networks: 
            - elk-network
    es-slave3:
        image:  elasticsearch:7.1.0
        container_name: es-cluster-slave3
        depends_on:
            - es-master
        environment: # setting container env
            - cluster.name=es-cluster
            - node.name=slave3
            - node.master=false
            - node.data=true
            - cluster.initial_master_nodes=es-master
            - discovery.zen.ping.unicast.hosts=es-master
            - bootstrap.memory_lock=true    # lock bootstrap memory.
            - ES_JAVA_OPTS=${ES_JVM_OPTS}
        ports:
            - "19203:9200"
        expose: # expose ports let other containers link it
            - "9300"
        restart: always
        volumes:        # mount host's dirs
            - ${ES_SLAVE3_DATA_DIR}:/usr/share/elasticsearch/data:rw 
        networks: 
            - elk-network
    es-balance:
        image:  elasticsearch:7.1.0
        container_name: es-cluster-balance
        depends_on:
            - es-master
        environment: # setting container env
            - cluster.name=es-cluster
            - node.name=balance
            - node.master=false # the balance is no master and no data save. 
            - node.data=false
            - cluster.initial_master_nodes=es-master
            - discovery.zen.ping.unicast.hosts=es-master
            - bootstrap.memory_lock=true    # lock bootstrap memory.
            - ES_JAVA_OPTS=${ES_JVM_OPTS}
        ports:
            - "19204:9200"
        expose: # expose ports let other containers link it
            - "9300"
        restart: always
        volumes:        # mount host's dirs
            - ${ES_BALANCE_DATA_DIR}:/usr/share/elasticsearch/data:rw 
        networks: 
            - elk-network
    kibana:
        image: kibana:7.1.0
        container_name: kibana
        depends_on:
            - es-master
        environment:
            - ELASTICSEARCH_HOSTS=http://${HOST_IP}:19204 # connect the es-balance node
            - I18N_LOCALE=zh-CN
        ports:
            - "15601:5601"
        networks:
            - elk-network
    zookeeper:
        image: zookeeper:3.5.5
        restart: always
        container_name: zookeeper
        ports:
            - "12181:2181"
        expose:
            - "2181"    #let kafka manager connect.
        networks:
            - elk-network
    kafka1:
        image: wurstmeister/kafka:2.12-2.2.1
        restart: always
        container_name: kafka1
        ports:
            - "9091:9091"
        environment:
            - KAFKA_BROKER_ID=1
            - KAFKA_LISTENERS=PLAINTEXT://kafka1:9091
            - KAFKA_ADVERTISED_LISTENERS=PLAINTEXT://kafka1:9091
            - KAFKA_ZOOKEEPER_CONNECT=zookeeper:2181
            - KAFKA_MESSAGE_MAX_BYTES=2000000
            - KAFKA_CREATE_TOPICS=${KAFKA_BOOTSTRAP_CREATE_TOPICS}
        expose:
            - "9091"
        depends_on:
            - zookeeper
        networks:
            - elk-network
    kafka2:
        image: wurstmeister/kafka:2.12-2.2.1
        restart: always
        container_name: kafka2
        ports:
            - "9092:9092"
        environment:
            - KAFKA_BROKER_ID=2
            - KAFKA_LISTENERS=PLAINTEXT://kafka2:9092
            - KAFKA_ADVERTISED_LISTENERS=PLAINTEXT://kafka2:9092
            - KAFKA_ZOOKEEPER_CONNECT=zookeeper:2181
            - KAFKA_MESSAGE_MAX_BYTES=2000000
            - KAFKA_CREATE_TOPICS=${KAFKA_BOOTSTRAP_CREATE_TOPICS}
        expose:
            - "9092"
        depends_on:
            - zookeeper
        networks:
            - elk-network
    kafka3:
        image: wurstmeister/kafka:2.12-2.2.1
        restart: always
        container_name: kafka3
        ports:
            - "9093:9093"
        environment:
            - KAFKA_BROKER_ID=3
            - KAFKA_LISTENERS=PLAINTEXT://kafka3:9093
            - KAFKA_ADVERTISED_LISTENERS=PLAINTEXT://kafka3:9093
            - KAFKA_ZOOKEEPER_CONNECT=zookeeper:2181
            - KAFKA_MESSAGE_MAX_BYTES=2000000
            - KAFKA_CREATE_TOPICS=${KAFKA_BOOTSTRAP_CREATE_TOPICS}
        expose:
            - "9093"
        depends_on:
            - zookeeper
        networks:
            - elk-network
    kafka-manager:
        image: sheepkiller/kafka-manager
        container_name: kafka-manager
        ports:
            - "19000:9000"
        environment:
            ZK_HOSTS: zookeeper:2181
            APPLICATION_SECRET: "admin"
        depends_on:
            - zookeeper
        networks:
            - elk-network
    logstash1:
        image: logstash:7.1.0
        container_name: logstash-1
        ports:
            - "9601:9600"
        environment:
            - XPACK_MONITORING_ENABLED=true
        volumes:
            - ${LOGSTASH_CONFIG_DIR}/logstash.conf:/usr/share/logstash/pipeline/logstash.conf:rw
            - ${LOGSTASH_CONFIG_DIR}/logstash.yml:/usr/share/logstash/config/logstash.yml:rw
        depends_on:
            - kafka1
            - kafka2
            - kafka3
            - es-master
            - es-slave1
            - es-slave2
            - es-slave3
        networks:
            - elk-network     
    logstash2:
        image: logstash:7.1.0
        container_name: logstash-2
        ports:
            - "9602:9600"
        environment:
            - XPACK_MONITORING_ENABLED=true
        volumes:
            - ${LOGSTASH_CONFIG_DIR}/logstash.conf:/usr/share/logstash/pipeline/logstash.conf:rw
            - ${LOGSTASH_CONFIG_DIR}/logstash.yml:/usr/share/logstash/config/logstash.yml:rw
        depends_on:
            - kafka1
            - kafka2
            - kafka3
            - es-master
            - es-slave1
            - es-slave2
            - es-slave3
        networks:
            - elk-network
    logstash3:
        image: logstash:7.1.0
        container_name: logstash-3
        ports:
            - "9603:9600"
        environment:
            - XPACK_MONITORING_ENABLED=true
        volumes:
            - ${LOGSTASH_CONFIG_DIR}/logstash.conf:/usr/share/logstash/pipeline/logstash.conf:rw
            - ${LOGSTASH_CONFIG_DIR}/logstash.yml:/usr/share/logstash/config/logstash.yml:rw
        depends_on:
            - kafka1
            - kafka2
            - kafka3
            - es-master
            - es-slave1
            - es-slave2
            - es-slave3
        networks:
            - elk-network
networks:
    elk-network: 
        driver: bridge

logstash/config/logstash.yml

http.host: "0.0.0.0"
xpack.monitoring.elasticsearch.hosts: [ "http://10.2.114.110:19204" ]

logstash/config/logstash.conf

input {
  kafka {
    bootstrap_servers => "kafka1:9091,kafka2:9092,kafka3:9093"
    topics => ["all_logs"]
    group_id => "logstash"
    codec => json
  }
}

filter {

}

output {
  elasticsearch {
    hosts => ["10.2.114.110:19204"]
    index => "all-logs-%{+YYYY.MM.dd}"
    #user => "elastic"
    #password => "changeme"
  }
  stdout {
    codec => rubydebug
  }
}

結束語

本文只是爲了驗證方案的可行性,並無考慮生產環境中的負載狀況,因此不適合放到生產環境中使用。

僅用於提供一個思路,正確按照文檔操做是不會有問題的。若是有,請在下方評論,我會盡快改正。

聲明:原創文章禁止轉載

相關文章
相關標籤/搜索