基于日志的Openstack的故障监控
2015-06-06 13:43
549 查看
声明:
本博客欢迎转载,但请保留原作者信息
作者:柯晓东
团队:华为杭州OpenStack团队
openstack上线后,剩下的就是解答各种疑问、恢复各种误操作、捕捉各种bug了。虽然ceilometer也做了监控,但是ceilometer里面提取的东西都是其他组件主动报过来的,它获得的信息量远远小于各个组件自身的日志。所以最终看问题,还是要靠日志。分布式系统、松耦合的组件,不对日志进行归档和整理,那么需要到N台机器的M个目录查看“ERROR”关键字,查看哪一个组件因为什么原因出错了,费时费力。因此首先需要对日志进行统一的归档和检索。
日志的统一归档,业界的思路基本都是:(1)通过一个无所不能的日志接收端,对接各种形式的日志。(2)然后交给一个基于apache lucene的搜索引擎去处理。(3)最后通过一个web框架,查询特定的关键字(例如ERROR),再结合上下文的日志来分析和监控日志。
当前有2个框架比较成熟,一个是ELK(elastic-search、logstash、kibana),另一个是SFK(Solr、Flume、Kafka)。
(1)ELK和SFK对比的优缺点
ELK的优点是:对接的文档全、上手快。直接从官网下载文档就能搭好环境。缺点是:elastic-search本身没有安全性设计,闭源的安全插件(shield)是要收费的。
因为ELK的半商业性质,他们有比较多的钱投入宣传。
SFK都是apache的作品,文档多而杂,上手超级慢,但是安全方面作的很好。
(2)ELK配置详情
logstash shipper能够接收syslog-ng、unix socket的日志,这样已经把我们日志大部分都收编了。剩下的部分通过file插件单独一个个地增加到logstash的陪着文件里面。
logstash shipper的输出端当然是他们推荐的redis,再到logstash indexer,最终到elastic-search。
(2.1)elastic-search的配置
elastic-search是搜索引擎,不是数据库,所以在查找时,有很多地方很传统的数据库查找不一样。默认elastic-search里面搜索是不区分大小写的,这样对我们从日志里面查找大写的ERROR非常不方便,因此首先需要切换默认的索引方式。elastic-search的索引是可以配置的,“Index=Tokenizer+Token Filter+Char Filter”
这些属性看名字就能猜到什么意思,如果想了解具体解释,可以看官网的介绍(https://www.elastic.co/guide/en/elasticsearch/reference/current/analysis.html),这里就不多说了。es就是通过组合使用上述3个属性来实现索引的配置。
内置的组合有:
custom:3种都让你自己配置
standard(默认):Standard Tokenizer + Standard Token Filter + Lower Case Token Filter + Stop Token Filter
simple:Lower Case Token Filter
whitespace:Whitespace Tokenizer
stop:Lower Case Token Filter + Stop Token Filter
可以看出默认使用的索引是带着Lower Case Token Filter的,这就是会去掉大小写敏感来建立索引,这就是需要我在我的日志系统里面去掉的。
接着修改elastic-search的配置,在 elasticsearch-1.5.0/config/elasticsearch.yml 文件的最前面加上对默认索引的修改。
同时在这个文件里面,要修改一下集群名字(cluster.name: mycluster),免得加入了局域网里面其他集群中。
这样配置就改完了,可以启动elastic-search了。
启动后,可以用curl命令来测试es是否运行正常:
(2.2)logstash的配置
logstash主要用input和各种日志对接,我这里input直接对接日志文件。output可以先对接redis,再对接es,我这里直接对接es。
这样之后,用这个配置文件启动logstash,就可以把日志导入到es里面了。
(2.3)用python操作elastic-search
首先是从pypi下载对应的依赖包
https://pypi.python.org/pypi/pyelasticsearch/
https://pypi.python.org/pypi/elasticsearch/
在pyelasticsearch的介绍页面里面,已经有很好的python的例子了。不过我们要更直接的,所以我们直接使用elastic-recheck写好的类。
https://github.com/openstack-infra/elastic-recheck/blob/master/elastic_recheck/results.py
为了更好用一点,对代码进行了一点增强:
在web端用web.py实现,可以直接使用上述查询类来对elastic-search进行查询。
(3)ELK的安全增强
ELK的框架中,elastic-search本身没有安全性,安全插件shield需要另外收费(https://www.elastic.co/guide/en/shield/current/index.html);logstash是客户端不用考虑安全;kibana是一个可替换的web端几乎不会使用它;传输层使用的是redis已有很好的安全性。那么问题的关键就是elastic-search如何提升安全性。
从官网说明来看,官方希望把elastic-search部署在防火墙后面,只能内网访问。这种方案在我司是不允许的,因为最近就有某网站被内部人员删库的事情发生,所以内部人员也要防!所以我们需要找它的安全插件。
早在elastic-search 0.20,就有人把组件的serverlet从netty替换为jetty,再利用jetty做安全增强。github上有新的基于elastic-search1.5的jetty插件。该插件只解决了从外访问es的安全问题,没有解决es之间的nodes通讯的加密,所以插件下载量较小。地址如下:
https://github.com/tmayfield/elasticsearch-jetty
还有一个访问量多的全套安全的免费解决方案,地址是:
https://github.com/floragunncom/search-guard
这个插件还没有研究透,还在继续尝试中。
(4)用solr代替ES
既然es安全性不好,那么就使用安全性好的搜索引擎,即apache的solr。日志搜集部分还是使用logstash。
(4.1)修改logstash的配置,在output使用solr_http插件。
当然,上述solr中的core(gettingstarded)需要事先配置好。
(4.2)修改solr的配置
先用java的keytool生成ssl使用的证书和密钥对
keytool -genkeypair -alias solr-ssl -keyalg RSA -keysize 2048 -keypass mysecret -storepass mysecret -validity 9999 -keystore solr-ssl.keystore.jks -ext SAN=DNS:localhost,IP:x.xxx,ip:127.0.0.1 -dname "CN=localhost,OU=Organization al Unit,O=Organization,L=Location,ST=State,C=Country"
keytool -importkeystore -srckeystore solr-ssl.keystone.jks -destkeystore solr-ssl.keystore.p12 -srcstoretype jks -deststoretype pkcs12
openssl pkcs12 -in solr-ssl.keystore.p12 -out solr-ssl.pem
然后打开solr/bin/solr.in.sh里面关于SSL的配置项。
SOLR_SSL_OPTS="-Djavax.net.ssl.keyStore=solr-ssl.keystore.jks -Djavax.net.ssl.keyStorePassword=mysecret -Djavax.net.ssl.trustStore=solr-ssl.keystore.jks -Djavax.net.ssl.trustStorePassword=mysecret"
然后重启solr。
(5)使用日志来作故障检测和恢复
有统一的搜索前,定位问题需要看n个主机的m个日志。有了统一搜索之后,特别是有了python的查询客户端后,就可以用python客户端,将一些先验的知识固化在查询脚本里面。
例如创建虚拟机失败:
(1)首先先查询有没有“Not Valid Host”判断是不是调度失败了,再通过调度器来判断是哪一个资源不够了
(2)查询“ERROR”查看是不是有特定的错误日志。例如libvirt abort,inject fail等,依次判断是发生了哪一个已知问题
(3)如果不是已知的问题,通过ERROR可以找到requestid,再找到对应的action。然后通过ERROR查看调用栈。最后以此推断出现什么未知的问题。
通过提取错误的关键信息,可以得到类似这样的一张表:
分析到原因后,再依据场景作相应的恢复操作。
本博客欢迎转载,但请保留原作者信息
作者:柯晓东
团队:华为杭州OpenStack团队
openstack上线后,剩下的就是解答各种疑问、恢复各种误操作、捕捉各种bug了。虽然ceilometer也做了监控,但是ceilometer里面提取的东西都是其他组件主动报过来的,它获得的信息量远远小于各个组件自身的日志。所以最终看问题,还是要靠日志。分布式系统、松耦合的组件,不对日志进行归档和整理,那么需要到N台机器的M个目录查看“ERROR”关键字,查看哪一个组件因为什么原因出错了,费时费力。因此首先需要对日志进行统一的归档和检索。
日志的统一归档,业界的思路基本都是:(1)通过一个无所不能的日志接收端,对接各种形式的日志。(2)然后交给一个基于apache lucene的搜索引擎去处理。(3)最后通过一个web框架,查询特定的关键字(例如ERROR),再结合上下文的日志来分析和监控日志。
当前有2个框架比较成熟,一个是ELK(elastic-search、logstash、kibana),另一个是SFK(Solr、Flume、Kafka)。
(1)ELK和SFK对比的优缺点
ELK的优点是:对接的文档全、上手快。直接从官网下载文档就能搭好环境。缺点是:elastic-search本身没有安全性设计,闭源的安全插件(shield)是要收费的。
因为ELK的半商业性质,他们有比较多的钱投入宣传。
SFK都是apache的作品,文档多而杂,上手超级慢,但是安全方面作的很好。
(2)ELK配置详情
logstash shipper能够接收syslog-ng、unix socket的日志,这样已经把我们日志大部分都收编了。剩下的部分通过file插件单独一个个地增加到logstash的陪着文件里面。
logstash shipper的输出端当然是他们推荐的redis,再到logstash indexer,最终到elastic-search。
(2.1)elastic-search的配置
elastic-search是搜索引擎,不是数据库,所以在查找时,有很多地方很传统的数据库查找不一样。默认elastic-search里面搜索是不区分大小写的,这样对我们从日志里面查找大写的ERROR非常不方便,因此首先需要切换默认的索引方式。elastic-search的索引是可以配置的,“Index=Tokenizer+Token Filter+Char Filter”
名称 | 说明 | 预设值 |
Tokenizer | 基础索引规则 | standard、edgeNGram、keyword、letter、lowercase、whitespace、pattern等 |
Token Filter | 扩展索引规则 | standard、asciifolding、lowercase、uppercase、stop等 |
Char Filter | 字符处理规则 | mapping、html_strip、pattern_replace等 |
内置的组合有:
custom:3种都让你自己配置
standard(默认):Standard Tokenizer + Standard Token Filter + Lower Case Token Filter + Stop Token Filter
simple:Lower Case Token Filter
whitespace:Whitespace Tokenizer
stop:Lower Case Token Filter + Stop Token Filter
可以看出默认使用的索引是带着Lower Case Token Filter的,这就是会去掉大小写敏感来建立索引,这就是需要我在我的日志系统里面去掉的。
接着修改elastic-search的配置,在 elasticsearch-1.5.0/config/elasticsearch.yml 文件的最前面加上对默认索引的修改。
index: analysis: analyzer: default: type:custom tokenizer:myTokenizer1 filter:[mytokenFilter1, mytokenFilter2] tokenizer: myTokenizer1: type:standard max_token_length:900 filter: mytokenFilter1: type:standard mytokenFilter2: type:stop "stopwords":"_english_"
同时在这个文件里面,要修改一下集群名字(cluster.name: mycluster),免得加入了局域网里面其他集群中。
这样配置就改完了,可以启动elastic-search了。
启动后,可以用curl命令来测试es是否运行正常:
#查看集群状态 curl -XGET http://localhost:9200/_cluster/health?pretty=true #组合条件查询 curl -XGET http://localhost:9200/_search?pretty -d '{"query" :{"bool":{"must":{"match": {"message": "error"}},"must":{"match":{"message":"nova"}}}}}' #多条件查询 curl 'http://localhost:9200/_search?pretty' -d ' { "size": 1000, "sort": [ {"field1":{"order": "desc"}}, {"field2":{"order": "desc"}} ], "query":{ "bool":{ "must":[ {"match" :{"field1": {"query":"value1", "minimum_should_match":"100%", "operator":"and"}}}, {"match" :{"field2": {"query":"value2", "operator":"and"}}}, {"range" :{"field3": {"from":"10", "to":"20"}}}, {"range" :{"field4": {"get":"2015-06-16", "lte": now }}} ] } } }'
(2.2)logstash的配置
logstash主要用input和各种日志对接,我这里input直接对接日志文件。output可以先对接redis,再对接es,我这里直接对接es。
input { file{ path=>"/var/log/nova.log" } file{ path=>"/var/log/neutron.log" } file{ path=>"/var/log/cinder.log" } } output { elasticsearch{ host=>"localhost" cluster=>"mycluster" } }
这样之后,用这个配置文件启动logstash,就可以把日志导入到es里面了。
(2.3)用python操作elastic-search
首先是从pypi下载对应的依赖包
https://pypi.python.org/pypi/pyelasticsearch/
https://pypi.python.org/pypi/elasticsearch/
在pyelasticsearch的介绍页面里面,已经有很好的python的例子了。不过我们要更直接的,所以我们直接使用elastic-recheck写好的类。
https://github.com/openstack-infra/elastic-recheck/blob/master/elastic_recheck/results.py
为了更好用一点,对代码进行了一点增强:
import calendar import copy import datetime import pprint import dateutil.parser as dp import pyelasticsearch import pytz pp = pprint.PrettyPrinter() class SearchEngine(object): def __init__(self, url): self._url = url def search(self, query, size=1000): es = pyelasticsearch.ElasticSearch(self._url) args = {'size': size} results = es.search(query, **args) return ResultSet(results) def search_keyword(self, keyword1, keyword2 = None, size = 1000): must_list = [] dict = {"match":{"message":{"query":keyword1, "operator":"and"}}} must_list.append(dict) if keyword2 != None: dict = {"match":{"message":{"query":keyword2, "operator":"and"}}} must_list.append(dict) query={"sort":{"@timestamp":{"order":"desc"}},"query":{"bool":{"must":must_list}}} return self.search(query, size) class ResultSet(list): def __init__(self, results={}): self._results = results if 'hits' in results: self._parse_hits(results['hits']) def _parse_hits(self, hits): # why, oh why elastic search hits = hits['hits'] for hit in hits: list.append(self, Hit(hit)) def __getattr__(self, attr): if attr in self._results: return self._results[attr] class Hit(object): def __init__(self, hit): self._hit = hit def index(self): return self._hit['_index'] def __getitem__(self, key): return self.__getattr__(key) @property def id(self): return self._hit['_id'] @property def type(self): return self._hit['_type'] @property def timestamp(self): return self._hit['_source']['@timestamp'] @property def host(self): return self._hit['_source']['_host'] def __getattr__(self, attr): def first(item): if type(item) == list: return item[0] return item result = None at_attr = "@%s" % attr if attr in self._hit['_source']: result = first(self._hit['_source'][attr]) elif at_attr in self._hit['_source']: result = first(self._hit['_source'][at_attr]) elif attr in self._hit['_source']['@fields']: result = first(self._hit['_source']['@fields'][attr]) return result def __repr__(self): return pp.pformat(self._hit)
在web端用web.py实现,可以直接使用上述查询类来对elastic-search进行查询。
(3)ELK的安全增强
ELK的框架中,elastic-search本身没有安全性,安全插件shield需要另外收费(https://www.elastic.co/guide/en/shield/current/index.html);logstash是客户端不用考虑安全;kibana是一个可替换的web端几乎不会使用它;传输层使用的是redis已有很好的安全性。那么问题的关键就是elastic-search如何提升安全性。
从官网说明来看,官方希望把elastic-search部署在防火墙后面,只能内网访问。这种方案在我司是不允许的,因为最近就有某网站被内部人员删库的事情发生,所以内部人员也要防!所以我们需要找它的安全插件。
早在elastic-search 0.20,就有人把组件的serverlet从netty替换为jetty,再利用jetty做安全增强。github上有新的基于elastic-search1.5的jetty插件。该插件只解决了从外访问es的安全问题,没有解决es之间的nodes通讯的加密,所以插件下载量较小。地址如下:
https://github.com/tmayfield/elasticsearch-jetty
还有一个访问量多的全套安全的免费解决方案,地址是:
https://github.com/floragunncom/search-guard
这个插件还没有研究透,还在继续尝试中。
(4)用solr代替ES
既然es安全性不好,那么就使用安全性好的搜索引擎,即apache的solr。日志搜集部分还是使用logstash。
(4.1)修改logstash的配置,在output使用solr_http插件。
input { file{ path=>"/var/log/nova.log" } file{ path=>"/var/log/neutron.log" } file{ path=>"/var/log/cinder.log" } } output{ solr_http{ codec=>"plain" document_id=>nil flush_size=>100 idle_flush_time=>1 solr_url=>"http://localhost:8983/solr/gettingstarded" workers=>1 } }
当然,上述solr中的core(gettingstarded)需要事先配置好。
(4.2)修改solr的配置
先用java的keytool生成ssl使用的证书和密钥对
keytool -genkeypair -alias solr-ssl -keyalg RSA -keysize 2048 -keypass mysecret -storepass mysecret -validity 9999 -keystore solr-ssl.keystore.jks -ext SAN=DNS:localhost,IP:x.xxx,ip:127.0.0.1 -dname "CN=localhost,OU=Organization al Unit,O=Organization,L=Location,ST=State,C=Country"
keytool -importkeystore -srckeystore solr-ssl.keystone.jks -destkeystore solr-ssl.keystore.p12 -srcstoretype jks -deststoretype pkcs12
openssl pkcs12 -in solr-ssl.keystore.p12 -out solr-ssl.pem
然后打开solr/bin/solr.in.sh里面关于SSL的配置项。
SOLR_SSL_OPTS="-Djavax.net.ssl.keyStore=solr-ssl.keystore.jks -Djavax.net.ssl.keyStorePassword=mysecret -Djavax.net.ssl.trustStore=solr-ssl.keystore.jks -Djavax.net.ssl.trustStorePassword=mysecret"
然后重启solr。
(5)使用日志来作故障检测和恢复
有统一的搜索前,定位问题需要看n个主机的m个日志。有了统一搜索之后,特别是有了python的查询客户端后,就可以用python客户端,将一些先验的知识固化在查询脚本里面。
例如创建虚拟机失败:
(1)首先先查询有没有“Not Valid Host”判断是不是调度失败了,再通过调度器来判断是哪一个资源不够了
(2)查询“ERROR”查看是不是有特定的错误日志。例如libvirt abort,inject fail等,依次判断是发生了哪一个已知问题
(3)如果不是已知的问题,通过ERROR可以找到requestid,再找到对应的action。然后通过ERROR查看调用栈。最后以此推断出现什么未知的问题。
通过提取错误的关键信息,可以得到类似这样的一张表:
错误信息 | 原因 |
Not Valid Host | 资源不足 |
unexpected vif_type=binding_failed | 网口配置不对 |
unsupported configuration | libvirt的xml产生的有问题 |
error injecting data into image | 镜像不支持注入文件到指定分区 |
。。。 |
相关文章推荐
- Linux 下鼠标对应的文件
- linux-进程监控
- Win7下安装Hadoop
- php-wamp滴定仪网站的根目录
- 用函数fopen_s打开数据文件
- 大型网站技术架构
- 学习docker
- shell变量详解
- OpenCms 9.5.1 新建一个站点
- Centos的安装
- Tomcat学习之Wrapper
- 《Unix环境高级编程第3版》apue.3e在Linux上无法安装的问题
- window nginx 启动无提示错误,却没有listen 80端口
- ecshop、织梦、discuz、wordpress比较
- TopCoder SRM 660 Div2 Problem 500 - PrivateD2party (贪心)
- 21讲项目实战CMS-wordpress主题网站模板制作
- 30讲项目实战:网站面包屑导航+表单功能开发
- 28讲项目实战:网站搜索功能+单页面开发
- 29讲项目实战:404页面制作+网站友情链接调用
- 讲项目实战:网站会员功能开发+登录/注册表单