我刚打酱油去了,不好意思

如何修改kibana的默认主页

点火三周 发表了文章 • 3 个评论 • 8005 次浏览 • 2019-01-18 15:34 • 来自相关话题

在6.0版本以前,登录kibana之后,默认会路由到app/kibana下的discover应用。
在6.3版本以后,新增了一个home路径/app/kibana#/home?_g=h@44136fa,访问根路径\会直接跳到以上路径。

希望在kibana上做更多定制化开发的同学,或许会有需求在登录kibana之后能够跳转到自己的页面。

要完成以上需求,只需要在kibana的配置文件里面增加一行:
<br /> server.defaultRoute: /app/system_portal<br />
以上例子,我让kibana登录之后直接跳到我自己的app插件system_portal

配置默认路由的文件, src/server/http/get_default_route.js
js<br /> import _ from 'lodash';<br /> <br /> export default _.once(function (kbnServer) {<br /> const {<br /> config<br /> } = kbnServer;<br /> // 根目录basePath加上defaultRoute<br /> return `${config.get('server.basePath')}${config.get('server.defaultRoute')}`;<br /> });<br />

默认路由就是定义在server.defaultRoute中,默认值是app/kibana,可查看src/server/config/schema.js:
``js<br /> import Joi from 'joi';<br /> import { constants as cryptoConstants } from 'crypto';<br /> import os from 'os';<br /> <br /> import { fromRoot } from '../../utils';<br /> import { getData } from '../path';<br /> <br /> export default async () => Joi.object({<br /> pkg: Joi.object({<br /> version: Joi.string().default(Joi.ref('$version')),<br /> branch: Joi.string().default(Joi.ref('$branch')),<br /> buildNum: Joi.number().default(Joi.ref('$buildNum')),<br /> buildSha: Joi.string().default(Joi.ref('$buildSha')),<br /> }).default(),<br /> <br /> env: Joi.object({<br /> name: Joi.string().default(Joi.ref('$env')),<br /> dev: Joi.boolean().default(Joi.ref('$dev')),<br /> prod: Joi.boolean().default(Joi.ref('$prod'))<br /> }).default(),<br /> <br /> dev: Joi.object({<br /> basePathProxyTarget: Joi.number().default(5603),<br /> }).default(),<br /> <br /> pid: Joi.object({<br /> file: Joi.string(),<br /> exclusive: Joi.boolean().default(false)<br /> }).default(),<br /> <br /> cpu: Joi.object({<br /> cgroup: Joi.object({<br /> path: Joi.object({<br /> override: Joi.string().default()<br /> })<br /> })<br /> }),<br /> <br /> cpuacct: Joi.object({<br /> cgroup: Joi.object({<br /> path: Joi.object({<br /> override: Joi.string().default()<br /> })<br /> })<br /> }),<br /> <br /> server: Joi.object({<br /> uuid: Joi.string().guid().default(),<br /> name: Joi.string().default(os.hostname()),<br /> host: Joi.string().hostname().default('localhost'),<br /> port: Joi.number().default(5601),<br /> maxPayloadBytes: Joi.number().default(1048576),<br /> autoListen: Joi.boolean().default(true),<br /> defaultRoute: Joi.string().default('/app/kibana').regex(/^\//,start with a slash),<br /> basePath: Joi.string().default('').allow('').regex(/(^$|^\/.*[^\/]$)/,start with a slash, don't end with one`),
rewriteBasePath: Joi.boolean().when('basePath', {
is: '',
then: Joi.default(false).valid(false),
otherwise: Joi.default(false),
}),
customResponseHeaders: Joi.object().unknown(true).default({}),
ssl: Joi.object({
enabled: Joi.boolean().default(false),
redirectHttpFromPort: Joi.number(),
certificate: Joi.string().when('enabled', {
is: true,
then: Joi.required(),
}),
key: Joi.string().when('enabled', {
is: true,
then: Joi.required()
}),
keyPassphrase: Joi.string(),
certificateAuthorities: Joi.array().single().items(Joi.string()).default(),
supportedProtocols: Joi.array().items(Joi.string().valid('TLSv1', 'TLSv1.1', 'TLSv1.2')),
cipherSuites: Joi.array().items(Joi.string()).default(cryptoConstants.defaultCoreCipherList.split(':'))
}).default(),
cors: Joi.when('$dev', {
is: true,
then: Joi.object().default({
origin: ['://localhost:9876'] // karma test server
}),
otherwise: Joi.boolean().default(false)
}),
xsrf: Joi.object({
disableProtection: Joi.boolean().default(false),
whitelist: Joi.array().items(
Joi.string().regex(/^\//, 'start with a slash')
).default(),
token: Joi.string().optional().notes('Deprecated')
}).default(),
}).default(),

logging: Joi.object().keys({
silent: Joi.boolean().default(false),

quiet: Joi.boolean()
.when('silent', {
is: true,
then: Joi.default(true).valid(true),
otherwise: Joi.default(false)
}),

verbose: Joi.boolean()
.when('quiet', {
is: true,
then: Joi.valid(false).default(false),
otherwise: Joi.default(false)
}),

events: Joi.any().default({}),
dest: Joi.string().default('stdout'),
filter: Joi.any().default({}),
json: Joi.boolean()
.when('dest', {
is: 'stdout',
then: Joi.default(!process.stdout.isTTY),
otherwise: Joi.default(true)
}),

useUTC: Joi.boolean().default(true),
})
.default(),

ops: Joi.object({
interval: Joi.number().default(5000),
}).default(),

plugins: Joi.object({
paths: Joi.array().items(Joi.string()).default(),
scanDirs: Joi.array().items(Joi.string()).default(),
initialize: Joi.boolean().default(true)
}).default(),

path: Joi.object({
data: Joi.string().default(getData())
}).default(),

optimize: Joi.object({
enabled: Joi.boolean().default(true),
bundleFilter: Joi.string().default('!tests'),
bundleDir: Joi.string().default(fromRoot('optimize/bundles')),
viewCaching: Joi.boolean().default(Joi.ref('$prod')),
watch: Joi.boolean().default(false),
watchPort: Joi.number().default(5602),
watchHost: Joi.string().hostname().default('localhost'),
watchPrebuild: Joi.boolean().default(false),
watchProxyTimeout: Joi.number().default(5
60000),
useBundleCache: Joi.boolean().default(Joi.ref('$prod')),
unsafeCache: Joi.when('$prod', {
is: true,
then: Joi.boolean().valid(false),
otherwise: Joi
.alternatives()
.try(
Joi.boolean(),
Joi.string().regex(/^\/.+\/$/)
)
.default(true),
}),
sourceMaps: Joi.when('$prod', {
is: true,
then: Joi.boolean().valid(false),
otherwise: Joi
.alternatives()
.try(
Joi.string().required(),
Joi.boolean()
)
.default('#cheap-source-map'),
}),
profile: Joi.boolean().default(false)
}).default(),
status: Joi.object({
allowAnonymous: Joi.boolean().default(false)
}).default(),
map: Joi.object({
manifestServiceUrl: Joi.string().default(' https://catalogue.maps.elastic.co/v2/manifest'),
emsLandingPageUrl: Joi.string().default('https://maps.elastic.co/v2'),
includeElasticMapsService: Joi.boolean().default(true)
}).default(),
tilemap: Joi.object({
url: Joi.string(),
options: Joi.object({
attribution: Joi.string(),
minZoom: Joi.number().min(0, 'Must be 0 or higher').default(0),
maxZoom: Joi.number().default(10),
tileSize: Joi.number(),
subdomains: Joi.array().items(Joi.string()).single(),
errorTileUrl: Joi.string().uri(),
tms: Joi.boolean(),
reuseTiles: Joi.boolean(),
bounds: Joi.array().items(Joi.array().items(Joi.number()).min(2).required()).min(2)
}).default()
}).default(),
regionmap: Joi.object({
includeElasticMapsService: Joi.boolean().default(true),
layers: Joi.array().items(Joi.object({
url: Joi.string(),
format: Joi.object({
type: Joi.string().default('geojson')
}).default({
type: 'geojson'
}),
meta: Joi.object({
feature_collection_path: Joi.string().default('data')
}).default({
feature_collection_path: 'data'
}),
attribution: Joi.string(),
name: Joi.string(),
fields: Joi.array().items(Joi.object({
name: Joi.string(),
description: Joi.string()
}))
}))
}).default(),

i18n: Joi.object({
defaultLocale: Joi.string().default('en'),
}).default(),

// This is a configuration node that is specifically handled by the config system
// in the new platform, and that the current platform doesn't need to handle at all.
__newPlatform: Joi.any(),

}).default();

如何让kibana零等待时间升级插件(前后端分离的部署)

点火三周 发表了文章 • 1 个评论 • 3026 次浏览 • 2019-01-11 10:30 • 来自相关话题


正如官方文档所自豪宣称的那样。Kibana更多的是一个平台,一个可以让插件独立开发,“独立部署”的可扩展性平台,可以让我们自由的发挥自己的想象力和能力,根据自己的需求往上添加原生Kibana所不提供的功能。你可以开发一个新的app,也可以只部署一个后台服务,也可以是一个隐藏的跳转页面,这些,都有赖于plugin的方式,自由的在kibana上install, update和remove。

问题描述

以上。看起来是比较美好的,但硬币的反面是kibana作为一个单页应用,任何都其他功能都是"/"路径下都一个子path,任何插件的安装(除非是一个纯后台的服务,但我没有测试)都需要和主页面、所有已安装都插件产生联系,即每次插件都变动,都需要将所有的页面和js重新bundle一次。这个捆绑不是简单的捆绑,而是经过优化后的打包操作,相当耗时。重点是,按照目前的方式,optimize(bundle)的过程必须是现场的,即必须在正在运行的kibana服务器上进行,因此在以下情况下你可能会遇到麻烦:

  • 你的kibana服务作为一个生产服务,不能停
  • 你没有给kibana做双活
  • 因为只是一个前端,你给kibana分配的硬件资源很少(单核2G,双核4G)
  • 你使用的是6.3之后的版本,kibana已经默认安装了xpack。或者你是之前的版本,自己手动安装了xpack

    这时,你若是安装或者更新插件(包括remove插件),都可能会因为optimize过程占用大量的cpu和内存资源,而造成kibana停止服务响应。

    这里有一个小tips,如果你开发了多个插件,需要同时更新当时候,安装当时候请使用命令kibana-plugin install --no-optimize file:///path_to_your_file,当全部的插件都安装完了之后,再重启kibana,一次性的执行optimize流程,或者通过bin/kibana --optimize命令触发

    Kibana架构简述

    如果我们的目标是让kibana零等待时间升级插件,找到解决方案的前提是我们能够了解Kibana的软件架构和部署方式。

    首先,我们需要知道的是Kibana是一个基于node的web应用,前端后端都主要使用的javascript。web后端使用的hapi作为web服务器应用程序。并且node无需安装,已经包含在了kibana目录下。(node目录)

    以下是kibana的目录,所有的插件都安装在plugins目录,而所有打包后的内容都放在optimize目录。
    shell<br /> ├── LICENSE.txt<br /> ├── NOTICE.txt<br /> ├── README.txt<br /> ├── bin<br /> ├── config<br /> ├── data<br /> ├── node<br /> ├── node_modules<br /> ├── optimize<br /> ├── package.json<br /> ├── plugins<br /> ├── src<br /> └── webpackShims<br />
    plugins目录(这里,我有两个插件):
    shell<br /> .<br /> ├── kibana_auth_plugin<br /> │ ├── index.js<br /> │ ├── node_modules<br /> │ ├── package.json<br /> │ ├── public<br /> │ ├── server<br /> │ └── yarn.lock<br /> └── system_portal<br /> ├── index.js<br /> ├── node_modules<br /> ├── package.json<br /> ├── public<br /> ├── server<br /> └── yarn.lock<br />
    每个插件都是类似的目录结构。public目录存放的是前端的页面和js,server目录存放的是后端的js。这里最终要的信息是,插件的开发其实也是一种 前后端分离的架构 。插件安装后后端主程序会调用server目录下的文件,而前端public目录下的文件会被压缩后打包到optimize目录,详见如下。

    optimize目录:
    shell<br /> ├── bundles<br /> │ ├── 176bcca991b07a6ec908fc4d36ac5ae0.svg<br /> │ ├── 45c73723862c6fc5eb3d6961db2d71fb.eot<br /> │ ├── 4b5a84aaf1c9485e060c503a0ff8cadb.woff2<br /> │ ├── 69d89e51f62b6a582c311c35c0f778aa.svg<br /> │ ├── 76a4f23c6be74fd309e0d0fd2c27a5de.svg<br /> │ ├── 7c87870ab40d63cfb8870c1f183f9939.ttf<br /> │ ├── apm.bundle.js<br /> │ ├── apm.entry.js<br /> │ ├── apm.style.css<br /> │ ├── kibana-auth-plugin.bundle.js<br /> │ ├── kibana-auth-plugin.entry.js<br /> │ ├── kibana-auth-plugin.style.css<br /> │ ├── canvas.bundle.js<br /> │ ├── canvas.entry.js<br /> │ ├── canvas.style.css<br /> │ ├── cc17a3dbad9fc4557b4d5d47a38fcc56.svg<br /> │ ├── commons.bundle.js<br /> │ ├── commons.style.css<br /> │ ├── dashboardViewer.bundle.js<br /> │ ├── dashboardViewer.entry.js<br /> │ ├── dashboardViewer.style.css<br /> │ ├── dfb02f8f6d0cedc009ee5887cc68f1f3.woff<br /> │ ├── fa0bbd682c66f1187d48f74b33b5bbd0.svg<br /> │ ├── graph.bundle.js<br /> │ ├── graph.entry.js<br /> │ ├── graph.style.css<br /> │ ├── infra.bundle.js<br /> │ ├── infra.entry.js<br /> │ ├── infra.style.css<br /> │ ├── kibana.bundle.js<br /> │ ├── kibana.entry.js<br /> │ ├── kibana.style.css<br /> │ ├── ml.bundle.js<br /> │ ├── ml.entry.js<br /> │ ├── ml.style.css<br /> │ ├── monitoring.bundle.js<br /> │ ├── monitoring.entry.js<br /> │ ├── monitoring.style.css<br /> │ ├── space_selector.bundle.js<br /> │ ├── space_selector.entry.js<br /> │ ├── space_selector.style.css<br /> │ ├── src<br /> │ ├── stateSessionStorageRedirect.bundle.js<br /> │ ├── stateSessionStorageRedirect.entry.js<br /> │ ├── stateSessionStorageRedirect.style.css<br /> │ ├── status_page.bundle.js<br /> │ ├── status_page.entry.js<br /> │ ├── status_page.style.css<br /> │ ├── system_portal.bundle.js<br /> │ ├── system_portal.entry.js<br /> │ ├── system_portal.style.css<br /> │ ├── timelion.bundle.js<br /> │ ├── timelion.entry.js<br /> │ ├── timelion.style.css<br /> │ ├── vendors.bundle.js<br /> │ └── vendors.style.css<br />
    前端浏览器在访问"/"目录的时候会最先获取到kibana.*.js相关的文件。我们看一下
    kibana.entry.js, 里面是包含了所有插件的信息的,即,每次插件的变动,这些文件也会跟着跟新
    ```js
    /**

  • Kibana entry file
    *
  • This is programmatically created and updated, do not modify
    *
  • context: ä
    "env": "production",
    "kbnVersion": "6.5.0",
    "buildNum": 18730,
    "plugins": Ä
    "apm",
    "apm_oss",
    "beats_management",
    "kibana_auth_plugin",
    "canvas",
    "cloud",
    "console",
    "console_extensions",
    "dashboard_mode",
    "elasticsearch",
    "graph",
    "grokdebugger",
    "index_management",
    "infra",
    "input_control_vis",
    "inspector_views",
    "kbn_doc_views",
    "kbn_vislib_vis_types",
    "kibana",
    "kuery_autocomplete",
    "license_management",
    "logstash",
    "markdown_vis",
    "metric_vis",
    "metrics",
    "ml",
    "monitoring",
    "notifications",
    "region_map",
    "reporting",
    "rollup",
    "searchprofiler",
    "spaces",
    "state_session_storage_redirect",
    "status_page",
    "system_portal",
    "table_vis",
    "tagcloud",
    "tile_map",
    "tilemap",
    "timelion",
    "vega",
    "watcher",
    "xpack_main"
    Å
    å
    */

    // import global polyfills before everything else
    import 'babel-polyfill';
    import 'custom-event-polyfill';
    import 'whatwg-fetch';
    import 'abortcontroller-polyfill';
    import 'childnode-remove-polyfill';

    import ä i18n å from 'Ékbn/i18n';
    import ä CoreSystem å from 'kibanaCore'

    const injectedMetadata = JSON.parse(document.querySelector('kbn-injected-metadata').getAttribute('data'));
    i18n.init(injectedMetadata.legacyMetadata.translations);

    new CoreSystem(ä
    injectedMetadata,
    rootDomElement: document.body,
    requireLegacyFiles: () => ä
    require('plugins/kibana/kibana');
    å
    å).start()
    ```

    优化部署的方案(前后端分离的部署)

    我们已经初步了解了kibana和kibana plugins的架构。那kibana插件的安装方案是怎么样的呢?
    kibana为了简化我们的工作,只需要我们将打包好的源码丢给kibana,然后执行命令:kibana-plugin install file:///path_to_your_file,这样貌似省事,但也把所有的工作都丢给了kibana服务器去完成。
    在kibana服务器性能不佳的情况下,这部分工作可能会造成服务中断。因此,我们要代替kibana服务器完成这部分工作,做一个前后端分离的部署

    后端部署

    后端部署的速度是极快的,只需要把文件解压缩到具体目录就可以:
    <br /> `kibana-plugin install --no-optimize file:///path_to_your_file`<br />

    这里特别要注意: --no-optimize参数是必须的,这时,插件的安装只是一个解压的过程,不会让kibana服务器去做繁重的optimize工作。

    注意,执行这一步之后,不能重启kibana服务器,否则会自动做optimize

    前端部署

    这里说的前端,主要是指bundle之后的内容。在你的开发环境上,安装插件。当插件安装完成后,把bundles目录整体打包(bundles.zip)。将打包好之后的内容,上传到kibana服务器,删除旧的optimize/bundles目录,把打包好的bundles目录解压到optimize目录下
    注意,这里开发环境上的kibana版本,和kibana安装的插件必须是和生产环境上是一致的,否则会造成无法启动或者自动重做optimize

    重启kibana服务器

    当以上两步完成之后,重启kibana service即可,你会发现,内容已经更新,但是不会触发任何的optimize过程。

    参考示例

    以下是该过程的一个ansible playbook供大家参考

    ```yaml
    ---


    • name: deploy bundles zip
      copy: src=bundles.zip dest={{kibana_home}}/optimize force=yes mode={{file_mask}}

    • name: deploy system plugins zip
      copy: src=system_portal-0.0.0.zip dest={{kibana_home}}/ force=yes mode={{file_mask}}

    • name: deploy auth zip
      copy: src=kibana_auth_plugin-6.5.0.zip dest={{kibana_home}}/ force=yes mode={{file_mask}}

    • name: remove system plugin
      shell: "{{kibana_home}}/bin/kibana-plugin remove system_portal"
      ignore_errors: True

    • name: remove auth plugin
      shell: "{{kibana_home}}/bin/kibana-plugin remove kibana_auth_plugin"
      ignore_errors: True


    • name: install system plugin
      shell: "{{kibana_home}}/bin/kibana-plugin install --no-optimize file://{{kibana_home}}/system_portal-0.0.0.zip"
      register: install_state

    • name: install auth plugin
      shell: "{{kibana_home}}/bin/kibana-plugin install --no-optimize file://{{kibana_home}}/kibana_auth_plugin-6.5.0.zip"
      register: install_state

      failed_when: "'Extraction complete' in install_state.stdout_lines"


    • name: delete old bundls
      file: dest={{kibana_home}}/optimize/bundles state=absent

    • name: delete old bundls
      unarchive:
      src: "{{kibana_home}}/optimize/bundles.zip"
      dest: "{{kibana_home}}/optimize/"
      copy: no
      group: "kibana"
      owner: "kibana"
      mode: "{{file_mask}}"

    • name: delete zip files
      file: dest={{kibana_home}}/optimize/bundles.zip state=absent

    • name: restart kibana
      become: yes
      service: name={{kibana_init_script | basename}} state=restarted enabled=yes



特殊字符处理

oceanship 回复了问题 • 3 人关注 • 1 个回复 • 3073 次浏览 • 2019-01-02 16:11 • 来自相关话题

【告警设置】如何配置watcher检测同一用户一小时内登录失败超过5次,具体的input配置怎么写?(以AD认证日志为例)

xiaoyanghapi 回复了问题 • 2 人关注 • 1 个回复 • 1854 次浏览 • 2018-12-27 16:03 • 来自相关话题

为何要通过Kibana展示promethues的数据以及如何去做

点火三周 发表了文章 • 1 个评论 • 7779 次浏览 • 2018-12-27 10:59 • 来自相关话题

Elastic stack不停的迭代中狂奔。在最新的V6.5版本发布后,我们可以发现,其路线图已经越来越倾向于成为一个全栈的,全链路的,从下至上,从底层硬件资源数据一直到上层用户数据,从资源监控,到性能监控,直至安全审计的智能化运维系统了。这其中解决的一个痛点是:企业中存在各种各样的业务系统,每个系统又存在不同的数据源和存储数据的数据库;同时在运维管理层面上,又各种不同的监控系统(资源监控,性能监控,安全和审计)以及上层的可视化系统。这样,导致运维人员需要面对繁多的系统、入口和数据维度,在处理问题时,需要登录不同的平台,并且无法对数据进行有效的关联分析,因此,是迫切需要一个强大的平台,能够快速便捷的处理这些问题的。
我们可以看到,从不停发布的beats,以及beats里面不停添加的modules:

20181227080511775.png



以及支持的各种数据指标模版:

20181227080702828.png



elastic stack在加速将越来越多的数据需要汇聚到一起,并且提供一个统一的接口进入,这就是Kibana。这里,我不打算深入的比较Kibana和Grafana,简单说一句,就是grafana的主要场景只是dashboard,并不适合将其用作一个将所有数据集中到一起,需要做各种维度的查询,分析,安全检查等功能的portal。所以,这里我们讨论的是Kibana上如何展示其他数据源的数据。

为什么是prometheus而不是beats


在这个人人上云的时代,无论是open stack还是K8S,最流行的资源监控软件我看到的是prometheus,特别是以node_exporter为基础的一系列metric采集工具,为prometheus提供了各种维度的监控数据。而对应的,elastic stack也提供了类似filebeat, metricbeat, packatbeat等一系列工具和对应的数据template。

我没有深入使用过prometheus,但作为一个beats的资深用户,我还是感觉到beats还存在诸多的问题,特别是filebeat上幽灵般存在的内存占用过多的问题,导致大规模在所有的节点上安装beats成为一种风险。并且,最主要的一个点,我觉得是beats采集的数据,是依赖于整个elastic stack进行展示的,而作为云的运维人员,其关心的重点是每个虚拟机,容器的资源监控情况,metric和alart是其重心,而非query,search,security等功能。并且安装一个prometheus,比安装整个elastic stack简便得多,消耗的资源也小的多。所以,普遍的,从主机运维人员的角度,肯定首选安装prometheus的exporter来作资源的监控,而非安装beats。

为什么Kibana上需要集成prometheus的数据


正因为之前所讲的,我们试图使用elastic stack作为一个多维度的统一的数据入口和展示工具,要求我们必须能在Kibana看到硬件资源监控级别的指标,而elastic stack提供的beats等工具,却并不为云运维人员所待见(因为他们更喜欢prometheus,而非elastic stack,原因见以上)。因此,如果我们需要将elastic stack打造为一套全栈的智能运维系统,大多数情况下,prometheus成为必须跨越的一个槛。

将prometheus上的数据转移到elasticsearch


这是我想到的第一个解决方案。可惜logstash上没有prometheus的input plugins。所以,我们还是需要beats。注意,在metricbeat上有一个prometheus的module,号称可以 fetch metric from prometheus exporter,但实际上只是一个乌龙,这个module的并不能从成千上万的云主机或者容器中拉取数据,它能做的只是获取prometheus服务器节点prometheus这个进程的基本数据,然并卵。
这里给大家介绍的是两个社区提供prometheus相关的beats:

但建议大家还是自己写一个beat吧,代码可以参考prombeat。
不过如果你仔细观看prometheus里面的数据,都是num type的,将其转存到elasticsearch绝对不是一个经济的选择:

20181227091438404.png



将grafana集成到kibana中


这是为什么我在一开始提到了grafana,虽然它不适合做portal,但是极其适合做dashboard,而kibana又是如此的开放,随便做个插件,可以轻松的跳转到grafana的dashboard上。而grafana与prometheus又是如此的登对,看看grafana上的各种专业而美丽的prometheus的dashboard吧:

20181227091946394.png



我们要做的是做一个kibana的插件,然后将关键参数传递给grafana,并跳转:

metric.gif



虽然kibana和grafana是两个不同的工具,但并不妨碍我们将它们放在一起工作。而Kibana的开放性和基于插件的独立开发模式,让我们可以更方便的将各种好用的开源工具集成到一起,这里展示的Kibana与grafana和promethues的集成,希望能给到你一些微光。







kibana query 大于值问题。

trycatchfinal 回复了问题 • 2 人关注 • 1 个回复 • 5276 次浏览 • 2018-12-26 21:13 • 来自相关话题

kibana分别使用Timelion和饼状图显示一小时的流量结果不一样

zqc0512 回复了问题 • 3 人关注 • 4 个回复 • 2832 次浏览 • 2018-12-24 08:58 • 来自相关话题

kibana可视化 中怎么 截取keyword 信息

zqc0512 回复了问题 • 5 人关注 • 4 个回复 • 4290 次浏览 • 2018-12-24 08:51 • 来自相关话题

Kibana开发环境搭建问题

juin 回复了问题 • 4 人关注 • 2 个回复 • 3855 次浏览 • 2018-12-21 16:31 • 来自相关话题

es有9台机器,3台master,6台data节点,那么kibana配置文件中elasticsearch.url怎么写?

Leeeo 回复了问题 • 5 人关注 • 2 个回复 • 1684 次浏览 • 2018-12-21 16:22 • 来自相关话题

kibana页面的Dev Tools模块为什么不断得进行两个post请求?

rochy 回复了问题 • 2 人关注 • 1 个回复 • 1853 次浏览 • 2018-12-21 14:02 • 来自相关话题

Kibana查询结果根据字段进行去重

insist_93 回复了问题 • 3 人关注 • 2 个回复 • 14402 次浏览 • 2018-12-18 09:21 • 来自相关话题

kibana visualize terms中的字段是"string",但是索引中的mapping是date

rochy 回复了问题 • 2 人关注 • 2 个回复 • 2173 次浏览 • 2018-12-15 10:06 • 来自相关话题

用elasitc stack监控kafka

点火三周 发表了文章 • 0 个评论 • 4096 次浏览 • 2018-12-12 11:28 • 来自相关话题

当我们搭建elasitc stack集群时,大多数时候会在我们的架构中加入kafka作为消息缓冲区,即从beats -> kafka -> logstash -> elasticsearch这样的一个消息流。使用kafka可以给我们带来很多便利,但是也让我们需要额外多维护一套组件,elasitc stack本身已经提供了monitoring的功能,我们可以方便的从kibana上监控各个组件中各节点的可用性,吞吐和性能等各种指标,但kafka作为架构中的组件之一却游离在监控之外,相当不合理。

幸而elastic真的是迭代的相当快,在metricbeat上很早就有了对kafka的监控,但一直没有一个直观的dashboard,终于在6.5版本上,上新了kafka dashboard。我们来看一下吧。

安装和配置metricbeat


[安装包下载地址](https://www.elastic.co/downloads/beats/metricbeat),下载后,自己安装。
然后,将/etc/metricbeat/modules.d/kafka.yml.disable文件重命名为/etc/metricbeat/modules.d/kafka.yml。(即打开kafka的监控)。稍微修改一下文件内容, 注意,这里需填入所有你需要监控的kafka服务器的地址

```

Module: kafka

Docs: https://www.elastic.co/guide/e ... .html


  • module: kafka
    metricsets:
    • partition
    • consumergroup
      period: 20s
      hosts: ["10...:9092","10...:9092","10...:9092","10...:9092"]

      client_id: metricbeat

      retries: 3

      backoff: 250ms


      List of Topics to query metadata for. If empty, all topics will be queried.

      topics: []


      Optional SSL. By default is off.

      List of root certificates for HTTPS server verifications

      ssl.certificate_authorities: ["/etc/pki/root/ca.pem"]


      Certificate for SSL client authentication

      ssl.certificate: "/etc/pki/client/cert.pem"


      Client Certificate Key

      ssl.key: "/etc/pki/client/cert.key"


      SASL authentication

      username: ""

      password: ""

      ```
      运行metricbeat,这里,一定要注意enable kibana dashboard。

      然后就可以在kibana里面看到:

      20181212112635653.png


      2018121211265464.png




      这样,我们就可以通过sentinl等类似的插件,自动做kafka的告警等功能了

Kibana优化过程(Optimize)过长或无法结束的解决方案

点火三周 发表了文章 • 5 个评论 • 5039 次浏览 • 2018-12-12 11:06 • 来自相关话题

使用过Kibana的同学应该都知道,当我们在kibana的配置文件中打开或者关闭功能,或者安装、卸载额外的插件后,重启kibana会触发一个优化的过程(optimize),如下图:


20181212101105813.png




这个过程或长或短,视你电脑的性能而定。这里简单介绍一下该过程所要完成的事情。

Kibana是一个单页Web应用

首先,Kibana是一个单页的web应用。何为单页web应用?即所有的页面的读取都是在浏览器上完成,而与后台服务器无关。与后台服务器的通信只关乎数据,而非页面。所以,应用上所有的UI都被打包在一起,一次性的发送到了浏览器端,而不是通过URL到后台进行获取。所以,我们看到kibana的首页是下面这样的:
<a href="http://localhost:5601/app/kibana#/" rel="nofollow" target="_blank">http://localhost:5601/app/kibana#/</a>
注意这里的#后,代表#后面的内容会被浏览器提取,不往服务器端进行url的情况,而是在浏览器上进行内部重新渲染。因为所有的页面都是存储在浏览器的,所有在初次访问的时候,会加载大量的代码到浏览器端,这些代码都是被压缩过的bundle文件:


20181212101741186.png




而optimize的过程,就是把这些原本可读性的源代码压缩为bundle.js的过程。因此,每当你对Kibana进行裁剪之后重启,因为前端的部分是完全由浏览器负责的,所有bundle文件需要重新生成后再发给浏览器,所以会触发optimize的过程。

Kibana在6.2.0版本之后,常规版本已经默认自带了xpack(当然,你还是可以直接下载不带xpack的开源社区版),导致Kibana的size已经到了200M左右,而且越往后的版本,功能越多,代码量越大,每次optimize的过程都会耗费更多的时间。一般来说,我们会将Kibana部署在单独的机器上,因为这仅仅是一个web后端,通常我们不会分配比较优质的资源,(2C4G都算浪费的了),这种情况下面,每次我们裁剪后重启Kibana都会耗费半个小时~1个小时的时间,更有甚者直接hang住,查看系统日志才知道OOM了。

Nodejs的内存机制

Kibana是用Nodejs编写的程序,在一般的后端语言中,基本的内存使用上基本没有什么限制,但是在nodeJs中却只能使用部分内存。在64位系统下位约为1.4G,在32位系统下约为0.7G,造成这个问题的主要原因是因为nodeJs基于V8构建,V8使用自己的方式来管理和分配内存,这一套管理方式在浏览器端使用绰绰有余,但是在nodeJs中这却限制了开发者,在应用中如果碰到了这个限制,就会造成进程退出。

Nodejs内存机制对Kibana优化的影响

因为Kibana的代码体量越来越大,将所有的代码加载到内存之后,再解析语法树,进行bundle的转换所耗费的内存已经接近1.4G的限制了,当你安装更多插件,比如sentinl的时候,系统往往已经无法为继,导致Kibana无法启动

解决方案


这种情况下,我们需要在Kibana启动的时候,指定NodeJs使用更多的内存。这个可以通过设置Node的环境变量办到。
<br /> NODE_OPTIONS="--max-old-space-size=4096"<br />
当然,我的建议是直接指定在kibana的启动脚本当中,修改/usr/share/kibana/bin/kibana文件为:
```shell

!/bin/sh

SCRIPT=$0

SCRIPT may be an arbitrarily deep series of symlinks. Loop until we have the concrete path.

while [ -h "$SCRIPT" ] ; do
ls=$(ls -ld "$SCRIPT")

Drop everything prior to ->

link=$(expr "$ls" : '.-> (.)$')
if expr "$link" : '/.*' > /dev/null; then
SCRIPT="$link"
else
SCRIPT=$(dirname "$SCRIPT")/"$link"
fi
done

DIR="$(dirname "${SCRIPT}")/.."
NODE="${DIR}/node/bin/node"
test -x "$NODE" || NODE=$(which node)
if [ ! -x "$NODE" ]; then
echo "unable to find usable node.js executable."
exit 1
fi

NODE_ENV=production exec "${NODE}" $NODE_OPTIONS --max_old_space_size=3072 --no-warnings "${DIR}/src/cli" ${@}

``<br /> 改动在最后一句:NODE_ENV=production exec "${NODE}" $NODE_OPTIONS --max_old_space_size=3072 --no-warnings "${DIR}/src/cli" ${@}`

这样,我们可以保证Kibana能顺利的完成optimize的过程