在 Elastic Stack 的使用中,我们会经常使用到复杂均衡。如果我们不考虑到这点,那么当我们的一个环节出现问题的话,那么就可能造成 Single point of failure,也就是整个数据的采集就不能工作。还有在多个实例部署的情况下,如何做到负载均衡更好地利用现有的资源。在今天的文章中,我们来讲述如何在数据采集或访问中,采用负载均衡。
我们先来看一下如下的一个典型的 Elastic Stack 图:
在上面,我们可以看到 Beats 可以直接连接到 Logstash,然后由 Logstash 帮我们加工数据,并最终导入到 Elasticsearch 中。
在没有负载均衡的情况下,是这样的:
我们通常可以在 beats 中这样配置:
output:
logstash.hosts: ["mylogstash"]
在没有任何事情发生的时候,一旦建立了这种 TCP 连接,这是一种非常可靠的连接。但是有一种情况就是,当我们的 Logstash 挂掉的话,那么我们可能就会有麻烦。这也就是我们上面提到的单点故障。如果有很多的 beats 都连到一个 Logstash 上的话,那么所有的数据采集将受到影响。
那么我们如和避免这种情况的发生呢?
解决方案是,我们多添加一个 Logstash 的服务器,把配置变为:
在上面,我们多添加了一个 Logstash 的服务器。在我们的实际的使用中如果其中的一个 Logstash 死掉的话,我们可以通过另外一个 Logstash 的服务器完成我们的数据采集的工作。那么我们如何在我们的 beats 中进行配置呢?
我们在 beats 的配置文件中这么配置:
output:
logstash.hosts: ["Logstash1", "Logstash2"]
在这种配置中,beats 在每次发送数据时,随机地挑出一个 Logstash 进行发送数据。如果其中的一个发生错误,那么 beats 将会挑另外一个进行发送。这种方式,没有使用到负载均衡。
在这种情况下,我们将使用负载均衡配置。我可以参阅文章https://www.elastic.co/guide/en/beats/filebeat/master/load-balancing.html
output:
logstash.hosts: ["logstash1", "logstash2"]
logstash.loadbalance: true
目前针对Filebeat, 负载均衡选项可用于 Redis,Logstash 和 Elasticsearch 输出。 Kafka 输出在内部处理负载平衡。
Beats 在这种情况下,根据负载的情况,均匀地向其中的 Logstash 发送数据。如果其中的一个连接断掉的话,那么 beats 将把它从它的资源池中除去,从而不再使用,直至再次连接成功为止。以指数后退重试以重新连接。
在上面的方法中,有一个很大的问题就是。当我们新增加一个 Logstash 的话,我们需要不停地修改我们的配置文件,从而使得我们的 Beats 能够知道它的存在。在或者,如果我们删除其中的一个 Logstash 的话,那么我们也同样需要来修改我们的 beats 的配置文件。如果我们只是维护一个或两个 beats 的话,那么这个可能并不是问题,毕竟工作量并不大。
但是,问题来了,假如我们有很多很多的 beats,这个工作量将是非常大的。我们该如何操作呢?
随着 beats 的数量越来越多,一种可行的办法就是使用专有的负载均衡:
如上面所示,我们可以让每个 beat 把数据发向一个专业的负载均衡器,再由它发送至 Logstash。通过这样的改造后,我们的 beat 的输出就变得非常简单:
output:
logstash.hosts: ["loadbalancer"]
在这里,每当我们添加一个新的 beat 后,或者我们增加一个新的 Logstash,我们都不需要再次维护 beats 段的修改。所有的配置都在负载均衡的地方完成。
在我们的实践中,我采用如下的配置:
负载均衡图:
在上面,beats 收集的数据发送到 Nginx,然后再发送至 Logstash,再传入到 Elasticsearch,并最终在 Kibana 中展示。
如果你还没有安装好自己的Elasticsearch,请参阅我之前的文章“如何在Linux,MacOS及Windows上进行安装Elasticsearch”来安装好自己的Elasticsearch。为了能够使得我们能够让 Ubunutu OS 中的 Logstash 也能访问到 Elasticsearch,我们对 config/elasticsearch.yml 文件做如下的修改:
network.host: 0.0.0.0
discovery.type: single-node
这样我们使得 Elasticsearch 绑定于 Mac OS 上的每一个网路接口上。我们可以分别在 http://localhost:9200/ 地址及 http://192.168.0.3:9200/ 都能看到输出:
如果你还没有安装好自己的Kibana,请参阅我之前的文章“如何在Linux,MacOS及Windows上安装Elastic栈中的Kibana”安装好自己的Kibana。我们可以不做任何的修改。安装完后,在浏览器中输入地址http://localhost:5601/
Nginx在Ubuntu的默认存储库中可用,因此安装非常简单。
由于这是我们在此会话中与apt打包系统的第一次交互,因此我们将更新本地包索引,以便我们可以访问最新的包清单。 之后,我们可以安装nginx:
sudo apt-get update
sudo apt-get install nginx
一旦nginx被成功安装,我们可以通过如下的命令来查看nginx服务是否已经被成功启动:
sudo service nginx status
$ sudo service nginx status
● nginx.service - nginx - high performance web server
Loaded: loaded (/lib/systemd/system/nginx.service; enabled; vendor preset: enable>
Active: active (running) since Wed 2020-06-17 16:44:00 CST; 5h 5min ago
Docs: http://nginx.org/en/docs/
Process: 1761 ExecStart=/usr/sbin/nginx -c /etc/nginx/nginx.conf (code=exited, sta>
Main PID: 1781 (nginx)
Tasks: 2 (limit: 18985)
Memory: 3.7M
CGroup: /system.slice/nginx.service
├─1781 nginx: master process /usr/sbin/nginx -c /etc/nginx/nginx.conf
└─1782 nginx: worker process
上面显示 nginx 已经被成功安装并正在运行。
为了能够把 nginx 设置为一个负载均衡器,我们对 /etc/nginx/nginx/conf 做如下的配置:
/etc/nginx/nginx.conf
user nginx;
worker_processes 1;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
stream {
upstream stream_backend {
server 192.168.0.4:5044;
}
server {
listen 12345;
proxy_pass stream_backend;
}
}
这里的 192.168.0.4 是 Ubuntu OS 的地址。 上面的意思是侦听端口12345,并把它转发至 192.168.0.4:5044。配置好我们的 nginx.conf,我们重新启动 nginx 服务:
sudo service nginx restart
我们安装我之前文章 “如何安装Elastic栈中的Logstash” 来安装 Logstash。按照上面的配置,我们在 Ubuntu OS 的电脑上安装 Logstash2。针对我们的情况,我们可以直接采用下载本地,并加压缩文件的方式来进行安装:
tar xzf logstash-7.7.1.tar.gz
cd logstash-7.7.1/
接下来,我们创建如下的 logstash.conf 配置文件:
logstash.conf
input {
beats {
port => 5044
}
}
output {
stdout {
codec => dots
}
}
在上面,Logstash 侦听端口 5044。如果有数据,我们直接显示 dot,也就是点。
我们使用如下的方式来启动 Logstash:
./bin/logstash -f logstash.conf
在接下来的练习中,我们还要安装 Logstash1。
我们可以打开 Kibana:
点击 Add mertic data:
选择 System metrics
然后根据自己的平台来进行安装。我们需要对 merticbeat.yml 进行修改。
我们启动 metricbeat:
./metricbeat -e
上面显示,metricbeat 和 nginx 的连接是成功的。
我们再回到 Logstash 运行的 console 里查看:
我们看到很多的点出现。这个说明,数据从 metricbeat 到 nginx,再传入到 Logstash 是成功的。
在 Mac OS 上的 Logstash1 的安装其实和 Ubuntu OS 上的 Logstash2 安装是一样的。我们也同样建立一个如下的配置文件:
logstash.conf
input {
beats {
port => 5044
}
}
output {
stdout {
codec => dots
}
}
我们运行这个 Logstash:
./bin/logstash -f logstash.conf
我们虽然已经把 Logstash1 已经运行起来了,但是,我们还没通知 nginx 向这个 Logstash 进行转发。我们重新打开 nginx.conf 文件,并添加 Mac OS 的 IP 地址信息:
/etc/nginx/nginx.conf
user nginx;
worker_processes 1;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
stream {
upstream stream_backend {
server 192.168.0.4:5044;
server 192.168.0.3:5044;
}
server {
listen 12345;
proxy_pass stream_backend;
}
}
请注意上面添加的一行:
server 192.168.0.3:5044;
也就是说,端口 12345 的信息会负载均衡发送到 192.168.0.3 及 192.168.0.4 两个 Logstash。
经过上面的修,我们重新启动 nginx:
sudo service nginx restart
这个时候,我们回到 Mac OS 的 Logstash1的 console 中进行查看,其实,我们会发现,没有任何的输出。难道是我们的配置有问题吗?其实答案很简单。nginx 和 metricbeat 之间的连接是一种 TCP/IP 的连接。一旦连接上,就不会断开。nginx 也不会重新作负载均衡。我们需要对 metricbeat 做一些配置。我们按照如下的方式来重新作练习:
1)在 /etc/nginx/nginx.conf 中去掉 server 192.168.0.3:5044; 然后重新启动 nginx
2) 停止 metricbeat,编辑 metricbeat.yml,并在 output.logstash 的配置部分添加 TTL:
output.logstash:
# The Logstash hosts
hosts: ["192.168.0.4:12345"]
ttl: "30s"
pipelining: 0
重新启动 metricbeat:
./metricbeat -e
3) 现在应该是和之前一样的效果,只有在 Logstash2 上能看到输出。而在 Logstash1 中没有点输出。
4)重新修改 /etc/nginx/nginx.conf 文件,并添加 server 192.168.0.3:5044;
stream {
upstream stream_backend {
server 192.168.0.4:5044;
server 192.168.0.3:5044;
}
server {
listen 12345;
proxy_pass stream_backend;
}
}
修改完后,重新启动 nginx 服务:
sudo service nginx restart
5) 我们再重新查看 Logstash1 的 console:
这个时候,我们可以看到有一些点开始出现了。这说明我们的 nginx 负载均衡已经起作用了。而且如果按照我们刚才对 metricbeat 的那样配置的话,每当我们添加一个新的 Logstash,我们不需要对任何的 beat 进行额外的配置。负载均衡会自动起做作用。
在我们的练习中,我没有在 Logstash 的 output 中添加 Elasticsearch。这个就留给你们了。