<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>errbot | 伪架构师</title>
    <link>/tags/errbot/</link>
      <atom:link href="/tags/errbot/index.xml" rel="self" type="application/rss+xml" />
    <description>errbot</description>
    <generator>Source Themes Academic (https://sourcethemes.com/academic/)</generator><language>zh</language><lastBuildDate>Wed, 07 Feb 2018 05:30:24 +0800</lastBuildDate>
    <image>
      <url>/img/logo-wide.png</url>
      <title>errbot</title>
      <link>/tags/errbot/</link>
    </image>
    
    <item>
      <title>ChatBot：在 Slack 中使用监控和告警</title>
      <link>/post/errbot-on-slack/</link>
      <pubDate>Wed, 07 Feb 2018 05:30:24 +0800</pubDate>
      <guid>/post/errbot-on-slack/</guid>
      <description>

&lt;p&gt;前面文章中我们使用 Errbot 通过 Kubernetes API 在 Slack 中进行 Kubernetes 查询。这种方式很局限。毕竟拉更多组件下水，写更多代码才是大势所趋 LOL。本文以 Istio 中的响应时间监控为例，看看 Errbot 和 Prometheus 的互动。&lt;/p&gt;

&lt;h2 id=&#34;前提&#34;&gt;前提&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Istio&lt;/li&gt;
&lt;li&gt;Prometheus&lt;/li&gt;
&lt;li&gt;公网部署&lt;/li&gt;
&lt;li&gt;接入 Slack 的 Errbot&lt;/li&gt;
&lt;li&gt;Errbot 开放 3141 端口，能够被 Alertmanager 使用。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;注意：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;这里只是介绍一下这种思路，例子要求比较高，源文件也不会很完整。要投入实际使用，需要更多配合。&lt;/li&gt;
&lt;li&gt;选择 Istio 做监控目标，只是因为目前环境方便，并无特殊含义。&lt;/li&gt;
&lt;li&gt;Errbot 的 Slack 接入在之前的文章有一些介绍可以参考。&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&#34;在-bot-中获取监控指标&#34;&gt;在 Bot 中获取监控指标&lt;/h2&gt;

&lt;p&gt;Prometheus 提供了很方便的 &lt;a href=&#34;https://prometheus.io/docs/prometheus/latest/querying/api/&#34; target=&#34;_blank&#34;&gt;HTTP API（注 1）&lt;/a&gt;，简单的使用 HTTP 客户端即可获取。下面的表达式用于从 Istio 中获取响应时间的 p99 指标：&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;    histogram_quantile(0.99,
    sum(irate(istio_request_duration_bucket[1m]))
    by (source_service, source_version,
    destination_service, destination_version, le))
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;这里为行文方便，直接硬编码，实际上可以通过查询模板、Bot 参数等方式，获得更灵活的查询。或者更加简单粗暴的，在聊天室向 Bot 提供查询公式直接查询。&lt;/p&gt;

&lt;p&gt;下面的代码，会将 Prometheus 中的指标，在 Slack 中以卡片的方式输出到指定聊天室中。&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;指定一个 &lt;code&gt;query&lt;/code&gt; 参数，取值为刚才提到的 Prometheus 查询语句，&lt;code&gt;{&amp;quot;query&amp;quot;: prom}&lt;/code&gt;的形式进行 URL Encode。&lt;/li&gt;
&lt;li&gt;API 指令发出后，Prometheus 会响应一段 JSON 报文，报文的&lt;code&gt;result&lt;/code&gt;字段包含一个列表，包含了各个服务的各个版本之间的通信响应时间。&lt;/li&gt;
&lt;li&gt;这里使用 Errbot 的 &lt;a href=&#34;http://errbot.io/en/latest/errbot.botplugin.html#errbot.botplugin.BotPlugin.send_card&#34; target=&#34;_blank&#34;&gt;send_card（注 2）&lt;/a&gt;功能，通过 Field 方式逐个输出服务记录。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;room = self.build_identifier(&amp;quot;#bot&amp;quot;)&lt;/code&gt;，使用 &lt;a href=&#34;http://errbot.io/en/latest/errbot.botplugin.html#errbot.botplugin.BotPlugin.build_identifier&#34; target=&#34;_blank&#34;&gt;self.build_identifier（注 3）&lt;/a&gt;设置发送目标。&lt;/li&gt;
&lt;li&gt;代码放入 Errbot 插件之后，私聊窗口输入&lt;code&gt;!restart&lt;/code&gt;，重启。会看到 Errbot 发出重启信息之后断线。&lt;/li&gt;
&lt;li&gt;等 Errbot 再次在线，在聊天室输入指令&lt;code&gt;!service quality&lt;/code&gt;，会看到类似如下的信息回应：&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;img src=&#34;images/errbot-prom1.png&#34; alt=&#34;metrics&#34; /&gt;&lt;/p&gt;

&lt;h2 id=&#34;使用-bot-接收-prometheus-告警&#34;&gt;使用 Bot 接收 Prometheus 告警&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;实际上 Prometheus 的 Alert Manager 提供了到 Slack 的集成，这里纯属演示，绕了个远。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&#34;配置-bot&#34;&gt;配置 Bot&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;在聊天室私信中发布命令 &lt;code&gt;!plugin config Webserver {&#39;HOST&#39;: &#39;0.0.0.0&#39;,&#39;PORT&#39;: 3141}&lt;/code&gt;，要求 Errbot 开放端口启动 Webhook 服务。&lt;/li&gt;

&lt;li&gt;&lt;p&gt;同样的使用私信发送命令 &lt;code&gt;!status&lt;/code&gt;，查询插件运行状态，可以看到 &lt;code&gt;Webserver&lt;/code&gt; 已经启动。&lt;/p&gt;

&lt;p&gt;&lt;img src=&#34;images/bot-status.png&#34; alt=&#34;Bot Status&#34; /&gt;&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;为 Bot 插件加入 Webhook 代码，并重新启动 Bot，这里定义了路径&lt;code&gt;alertmanager&lt;/code&gt;用于接受告警，同样使用卡片方式，发送告警信息到&lt;code&gt;bot&lt;/code&gt;频道，在卡片中显示告警的相关服务及其版本：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-python&#34;&gt;def alertmanager(self, data):
  &amp;quot;&amp;quot;&amp;quot;Webhook for alerts from Prometheus&amp;quot;&amp;quot;&amp;quot;
  target = self.build_identifier(&amp;quot;#bot&amp;quot;)
  self.send(target, &amp;quot;Alert!!&amp;quot;)
  for alert in data[&#39;alerts&#39;]:
      self.send_card(
          to=target,
          summary=&#39;[{}] {}&#39;.format(
              data[&#39;status&#39;].upper(),
              data[&#39;commonLabels&#39;][&#39;alertname&#39;]
          ),
          title=&amp;quot;Prometheus Alert&amp;quot;,
          fields=[(&#39;From&#39;, alert[&#39;annotations&#39;][&#39;from&#39;]),
                  (&#39;To&#39;, alert[&#39;annotations&#39;][&#39;to&#39;])],
          body=alert[&#39;annotations&#39;][&#39;summary&#39;]
      )
&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id=&#34;prometheus-配置&#34;&gt;Prometheus 配置&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;配置 Prometheus 告警规则：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;使用前面提到的同一个公式&lt;/li&gt;
&lt;li&gt;使用注解来传递应用标签&lt;/li&gt;

&lt;li&gt;&lt;p&gt;这里我们配置大于 3 秒钟的耗时发生告警&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;groups:
- name: fake
rules:
- alert: rules-alert
expr: |
    histogram_quantile(0.99,
    sum(irate(istio_request_duration_bucket[1m]))
    by (source_service, source_version,
    destination_service, destination_version, le)) &amp;gt; 3
for: 1m
labels:
    alertname: &amp;quot;request-duration-3&amp;quot;
annotations:
    summary: &amp;quot;Request duration gt 3&amp;quot;
    from: &amp;quot;{{ $labels.source_service }}:{{ $labels.source_version }}&amp;quot;
    to: &amp;quot;{{ $labels.destination_service }}:{{ $labels.destination_version }}&amp;quot;
&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;配置和重启 Alert Manager，定义使用 Web hook 通知 errbot 发送告警到 Slack：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;route:
    receiver: &#39;webhook&#39;
    group_wait: 30s
    group_interval: 5m
    repeat_interval: 4h
    group_by: [&#39;from&#39;, &#39;to&#39;]
    routes:

receivers:
- name: &#39;webhook&#39;
    webhook_configs:
    - url: &amp;quot;http://errbot.default:3141/alertmanager&amp;quot;
&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;Prometheus 连接到 AlertManager 上，用于发送告警，修改后重启 Prometheus：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;alerting:
alertmanagers:
- scheme: http
  static_configs:
  - targets:
    - &amp;quot;alertmanager:9093&amp;quot;
&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&#34;运行&#34;&gt;运行&lt;/h2&gt;

&lt;p&gt;在负载上调用耗时操作，例如持续访问&lt;code&gt;httpbin&lt;/code&gt;的&lt;code&gt;/delay/5&lt;/code&gt;指令，满足标准后，可以看到，告警的传递线路：&lt;/p&gt;

&lt;p&gt;&lt;img src=&#34;images/prom-alert.png&#34; alt=&#34;prom alert&#34; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&#34;images/alert-alert.png&#34; alt=&#34;alert alert&#34; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&#34;images/slack-alert-card.png&#34; alt=&#34;slack alert&#34; /&gt;&lt;/p&gt;

&lt;h2 id=&#34;注&#34;&gt;注&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;code&gt;https://prometheus.io/docs/prometheus/latest/querying/api/&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;http://errbot.io/en/latest/errbot.botplugin.html#errbot.botplugin.BotPlugin.send_card&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;http://errbot.io/en/latest/errbot.botplugin.html#errbot.botplugin.BotPlugin.build_identifier&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&#34;附录&#34;&gt;附录&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;查询&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-python&#34;&gt;@botcmd
def service_quality(self, message, args):
url = &amp;quot;http://prometheus-server.kube-system/api/v1/query?&amp;quot;
prom = &amp;quot;&amp;quot;&amp;quot;
histogram_quantile(0.99,
sum(irate(istio_request_duration_bucket[1m]))
by (source_service, source_version,
destination_service, destination_version, le))
&amp;quot;&amp;quot;&amp;quot;
query = {&amp;quot;query&amp;quot;: prom}
query = urlencode(query)
f = urllib.request.urlopen(url + query)
resp = f.read()
record_list = json.loads(resp)
room = self.build_identifier(&amp;quot;#bot&amp;quot;)
field_list = []
for record in record_list[&amp;quot;data&amp;quot;][&amp;quot;result&amp;quot;]:
    metric = record[&amp;quot;metric&amp;quot;]
    value = record[&amp;quot;value&amp;quot;]
    domain = &amp;quot;.svc.cluster.local&amp;quot;
    field = (&amp;quot;From {}:{} to {}:{}&amp;quot;.format(
        metric[&amp;quot;source_service&amp;quot;].replace(domain, &amp;quot;&amp;quot;),
        metric[&amp;quot;source_version&amp;quot;],
        metric[&amp;quot;destination_service&amp;quot;].replace(domain, &amp;quot;&amp;quot;),
        metric[&amp;quot;destination_version&amp;quot;],
    ), value[-1])
    field_list.append(field)
self.send_card(to=room, body=prom,
               title=&amp;quot;Query Statement&amp;quot;, summary=&amp;quot;From prometheus&amp;quot;,
               color=&amp;quot;green&amp;quot;, fields=field_list)
&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;
&lt;/ol&gt;
</description>
    </item>
    
    <item>
      <title>Errbot 入门（3）</title>
      <link>/post/errbot-startup-3/</link>
      <pubDate>Tue, 23 Jan 2018 21:29:57 +0800</pubDate>
      <guid>/post/errbot-startup-3/</guid>
      <description>

&lt;h1 id=&#34;errbot-入门-3&#34;&gt;Errbot 入门（3）&lt;/h1&gt;

&lt;h2 id=&#34;通过-errbot-控制-kubernetes&#34;&gt;通过 Errbot 控制 Kubernetes&lt;/h2&gt;

&lt;p&gt;前面两篇分别讲了 Errbot 的简单启动和 Slack 的集成。这一篇做个结尾，用 Errbot 来查询 Kubernetes 的状态。&lt;/p&gt;

&lt;p&gt;之前使用的 Docker 镜像中，已经集成了 Kubernetes 的 Python 客户端，所以这里只要在 Python 中引用，就可以操作了。&lt;/p&gt;

&lt;p&gt;这里实现两个功能，第一个是列出 kubeconfig 文件中的 context，第二个是列出集群 Node 的健康状况。&lt;/p&gt;

&lt;h2 id=&#34;准备工作&#34;&gt;准备工作&lt;/h2&gt;

&lt;p&gt;首先在 Errbot 的加载卷目录中新建目录&lt;code&gt;kubeconfig&lt;/code&gt;，并在其中放置一个可用的 kubeconfig 文件。例如：&lt;/p&gt;

&lt;p&gt;** /usr/local/var/volumes/errbot/kubeconfig/config **&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;apiVersion: v1
kind: Config
clusters:
- cluster:
    certificate-authority: ca-dummy/ca.pem
    server: https://10.211.55.11:6443
  name: default
users:
- name: default
  user:
    client-certificate: ca-dummy/admin.pem
    client-key: ca-dummy/admin-key.pem
contexts:
- context:
    cluster: default
    user: default
  name: default
current-context: default
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;当然，要确保 Errbot 到 Kubernetes 的网络连接是有效的。&lt;/p&gt;

&lt;h2 id=&#34;context-列表&#34;&gt;Context 列表&lt;/h2&gt;

&lt;pre&gt;&lt;code class=&#34;language-python&#34;&gt;from errbot import BotPlugin, botcmd, re_botcmd
import re
from kubernetes import config, client


class Kube(BotPlugin):
  @botcmd
  def context_list(self, msg, args):
      &amp;quot;&amp;quot;&amp;quot; List all contexts in the kubeconfig file.
      &amp;quot;&amp;quot;&amp;quot;
      yield(&amp;quot;Context in the kubeconfig:&amp;quot;)
      for context_name in list_context():
          yield(context_name)


def list_context():
    (context_list, context_current) = config.list_kube_config_contexts(
        &amp;quot;/errbot/kubeconfig/config&amp;quot;)
    result = []
    for context in context_list:
        result.append(context[&amp;quot;name&amp;quot;])
    return result
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;code&gt;import&lt;/code&gt; 部分引入了几个常用的 Bot 开发支持库，以及 Kubernetes API 库。&lt;/p&gt;

&lt;p&gt;接下来创建新的 Bot 插件 &lt;code&gt;Kube&lt;/code&gt;。&lt;/p&gt;

&lt;p&gt;&lt;code&gt;@botcmd&lt;/code&gt; 修饰其中的方法 &lt;code&gt;context_list&lt;/code&gt;，也就是生成了一个 &lt;code&gt;!context list&lt;/code&gt; 命令。&lt;/p&gt;

&lt;p&gt;注释内容会出现在命令列表的说明中。&lt;/p&gt;

&lt;p&gt;内容很简单，调用 kubernetes API 的 &lt;code&gt;config.list_kube_config_contexts&lt;/code&gt; 方法，列出其中所有的 context。&lt;/p&gt;

&lt;p&gt;&lt;code&gt;yield&lt;/code&gt; 在这里用于输出多行数据到聊天室。&lt;/p&gt;

&lt;p&gt;使用 &lt;code&gt;!restart&lt;/code&gt; 命令重启 Bot 之后，输入 &lt;code&gt;!help&lt;/code&gt; 查看我们的插件，会看到列表中多出这样的内容：&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;Kube
This is a simple plugin example to get you started.
• !context list - List all contexts in the kubeconfig file.
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;执行 &lt;code&gt;!context list&lt;/code&gt;，Bot 读取配置文件，返回了其中的 Context 名称列表：&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;Context in the kubeconfig:
default
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;接下来加入列出 Node，并查看健康状态代码&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-python&#34;&gt;@botcmd(split_args_with=None)
def cluster_health(self, msg, args):
    &amp;quot;&amp;quot;&amp;quot;Simpler checker nodes, pods and workload controllers.
    &amp;quot;&amp;quot;&amp;quot;
    if len(args) != 1:
        yield(&amp;quot;This command need context name as the only parameter.&amp;quot;)
        yield(&amp;quot;Here is the context list:&amp;quot;)
        for context_name in list_context():
            yield(context_name)
        return

    context_name = args[0]
    api_instance = get_instance(context_name)
    node_list = api_instance.list_node()
    # Node
    yield(&amp;quot;Checking Nodes...&amp;quot;)
    for node in node_list.items:
        name = node.metadata.name
        status = &amp;quot;NotReady&amp;quot;
        last_condition = node.status.conditions[-1:][0]
        if (last_condition.type == &amp;quot;Ready&amp;quot; and
                last_condition.status == &amp;quot;True&amp;quot;):
            status = &amp;quot;Ready&amp;quot;
        if status != &amp;quot;Ready&amp;quot;:
            yield(&amp;quot;{} {}\n&amp;quot;.format(name, status))

def get_instance(context_name, api_version=&amp;quot;core_v1&amp;quot;):
    api_client = config.load_kube_config(
        config_file=&amp;quot;/errbot/kubeconfig/config&amp;quot;,
        context=context_name)
    api_instance = client.CoreV1Api(api_client)
    return api_instance

&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;code&gt;@botcmd(split_args_with=None)&lt;/code&gt;，这一注解的意思是对聊天内容进行分拆，分拆产生的列表保存在&lt;code&gt;args&lt;/code&gt; 之中。&lt;/p&gt;

&lt;p&gt;对 Node 的 Status 对象的 Conditions 列表进行解析，如果最后一个状态不是 Ready，则输出不健康 Node。&lt;/p&gt;

&lt;h2 id=&#34;打完收工&#34;&gt;打完收工&lt;/h2&gt;

&lt;p&gt;在我们常见的工作场景中，结合各种系统的 API，可以利用 Errbot 在同一个聊天室中做很多操作，例如：&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;触发 Jenkins 构建&lt;/li&gt;
&lt;li&gt;对 ElasticSearch、Zabbix、Prometheus 进行查询&lt;/li&gt;
&lt;li&gt;管理 Kubernetes 负载。&lt;/li&gt;
&lt;li&gt;等等等等。&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;实际上除了这两种看起来比较古板的交流方式之外，还有看起来舒服一点的正则表达式匹配方式，然而，目前更大的热点是 AI，有了这种支持，个人觉得就不必挖空心思的琢磨分词和模式的问题了，做好和第三方的链接就可以了。&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Errbot 入门（2）</title>
      <link>/post/errbot-startup-2/</link>
      <pubDate>Thu, 18 Jan 2018 00:25:37 +0800</pubDate>
      <guid>/post/errbot-startup-2/</guid>
      <description>

&lt;p&gt;上一篇中，大致理解了一点 Errbot 的基础指令，这里尝试把 Errbot 接入到聊天室之中。&lt;/p&gt;

&lt;h2 id=&#34;slack-接入&#34;&gt;Slack 接入&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;首先去 &lt;a href=&#34;https://my.slack.com/services/new/bot&#34; target=&#34;_blank&#34;&gt;Slack 网站&lt;/a&gt; 注册一个机器人。&lt;/li&gt;
&lt;li&gt;注册完成后，会得到一个 Token。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;回到 Errbot 的配置文件，下面是一个样例。这里我们设置机器人接收 &amp;ldquo;@dustise&amp;rdquo; 这一 ID 的管理，&lt;code&gt;BOT_IDENTITY&lt;/code&gt; 写入我们刚刚创建的 Bot 账号的 Token：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-python&#34;&gt;import logging

BACKEND = &#39;Slack&#39;

BOT_DATA_DIR = r&#39;/errbot/data&#39;
BOT_EXTRA_PLUGIN_DIR = r&#39;/errbot/plugins&#39;

BOT_LOG_FILE = r&#39;/errbot/errbot.log&#39;
BOT_LOG_LEVEL = logging.WARNING

BOT_ADMINS = (&#39;@dustise&#39;, )  # !! Don&#39;t leave that to &amp;quot;@CHANGE_ME&amp;quot; if you connect your errbot to a chat system !!

BOT_IDENTITY = {
    &#39;token&#39;: &#39;......&#39;,
}

&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;接下来启动机器人，打开 Slack，进入频道，随意&lt;code&gt;@newbot&lt;/code&gt;邀请其加入频道，输入&lt;code&gt;!help&lt;/code&gt;，就能看到机器人输出的帮助指令了。输入&lt;code&gt;!tryme&lt;/code&gt;指令，会看到机器人的回复。&lt;/p&gt;

&lt;p&gt;&lt;img src=&#34;images/errbot-slack1.png&#34; alt=&#34;tryme&#34; /&gt;&lt;/p&gt;

&lt;p&gt;如果使用的是 Errbot 指定的管理账号，可通过私聊的方式为其发送&lt;code&gt;!restart&lt;/code&gt;等管理指令。&lt;/p&gt;

&lt;p&gt;在聊天室中输入&lt;code&gt;!whoami&lt;/code&gt;指令，会看到 Errbot 对当前用户的识别情况。&lt;/p&gt;

&lt;p&gt;&lt;img src=&#34;images/errbot-slack2.png&#34; alt=&#34;whoami&#34; /&gt;&lt;/p&gt;

&lt;h2 id=&#34;指令&#34;&gt;&lt;code&gt;@&lt;/code&gt; 指令&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;!&lt;/code&gt; 指令一般用于固定格式的命令，而 &lt;code&gt;@&lt;/code&gt; 也就是 &amp;ldquo;Mention&amp;rdquo; 就随意的多了，Errbot 同样提供了这种支持。&lt;/p&gt;

&lt;p&gt;在插件的&lt;code&gt;.py&lt;/code&gt;文件中加入如下方法：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-python&#34;&gt;    def callback_mention(self, message, mentioned_people):
        if self.bot_identifier in mentioned_people:
            self.send(message.frm, &#39;Errbot has been mentioned !&#39;)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;在私聊窗口输入 &lt;code&gt;!restart&lt;/code&gt; 重新载入 Errbot 之后，在房间中输入 &lt;code&gt;@newbot hello&lt;/code&gt;，会看到 Errbot 在私聊窗口中进行了回复。&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Errbot 入门（1）</title>
      <link>/post/errbot-startup-1/</link>
      <pubDate>Thu, 11 Jan 2018 12:08:53 +0800</pubDate>
      <guid>/post/errbot-startup-1/</guid>
      <description>

&lt;h2 id=&#34;简介&#34;&gt;简介&lt;/h2&gt;

&lt;p&gt;ChatBot，也就是聊天机器人，是近期偷偷热起来的东西之一，个人觉得原因很简单——太多系统需要运维了。&lt;/p&gt;

&lt;p&gt;使用 Grafana 可以将各种监控、日志的东西进行跟踪，在同一个 Dashboard 进行展示，但是缺点也比较明显：&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Dashboard 需要定制，不够灵活，难于满足突发的个性化需要。&lt;/li&gt;
&lt;li&gt;信息是单向流动的，无法进行远程干预。&lt;/li&gt;
&lt;li&gt;插件开发需要兼顾前后端，前端漂亮的界面对运维来说，并非必要。&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;聊天机器人简单说来是一个需要&lt;strong&gt;很多二次开发&lt;/strong&gt;的控制台，这个控制台的不同之处在于，可以和多种聊天室之类的东西进行集成，另外部分产品提供了认证、授权等功能；另外还有不少开源插件，用来同其他系统进行集成。称为机器人，应该说是一个历史遗留，跟 AI 大概有半毛钱的关系吧。&lt;/p&gt;

&lt;p&gt;目前最流行的同类产品大概是 Github 的 Hubot，不过个人爱好问题，还是选择了 Python 的 Errbot。官方网站 &lt;a href=&#34;http://errbot.io/&#34; target=&#34;_blank&#34;&gt;http://errbot.io/&lt;/a&gt; ，大致功能：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;内置多后端支持：

&lt;ul&gt;
&lt;li&gt;Slack&lt;/li&gt;
&lt;li&gt;Telegram&lt;/li&gt;
&lt;li&gt;XMPP&lt;/li&gt;
&lt;li&gt;IRC&lt;/li&gt;
&lt;li&gt;HipChat&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;第三方后端支持：

&lt;ul&gt;
&lt;li&gt;Skype&lt;/li&gt;
&lt;li&gt;Gitter&lt;/li&gt;
&lt;li&gt;Cisco Spark&lt;/li&gt;
&lt;li&gt;&amp;hellip;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;内置访问控制&lt;/li&gt;
&lt;li&gt;聊天室支持&lt;/li&gt;
&lt;li&gt;输出模板支持&lt;/li&gt;
&lt;li&gt;本地存储支持&lt;/li&gt;
&lt;li&gt;消息回调功能&lt;/li&gt;
&lt;li&gt;Webhook 支持&lt;/li&gt;
&lt;li&gt;自带文本终端&lt;/li&gt;
&lt;li&gt;&amp;hellip;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;下面会写一点教程，尝试&lt;strong&gt;在 Slack 上，通过 Errbot 来和 Kubernetes 集群进行交互&lt;/strong&gt;。大概分为三部分：&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;安装运行和一些基本操作&lt;/li&gt;
&lt;li&gt;Slack 的集成&lt;/li&gt;
&lt;li&gt;插件编写入门&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&#34;安装和运行&#34;&gt;安装和运行&lt;/h2&gt;

&lt;p&gt;安装过程还是有点点烦的，所以我做了个 Docker 镜像，源码见后。&lt;/p&gt;

&lt;p&gt;镜像已经在 DockerHub 上构建，Tag 为 &lt;code&gt;dustise/errbot-image&lt;/code&gt;，简单运行&lt;code&gt;docker run -it --rm dustise/errbot-image&lt;/code&gt;，就进入了文本调试界面，如图所示：&lt;/p&gt;

&lt;p&gt;&lt;img src=&#34;images/errbot-startup.png&#34; alt=&#34;startup&#34; /&gt;&lt;/p&gt;

&lt;p&gt;输入&lt;code&gt;!help&lt;/code&gt;（注意，要输入两次回车）会列出当前支持的命令列表。感叹号是 errbot 的命令前缀。输入&lt;code&gt;!shutdown --confirm&lt;/code&gt;，会提示关机字样，errbot 进程退出。&lt;/p&gt;

&lt;p&gt;接下来我们将其中的存储卷进行映射：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;mkdir -p /var/volume/errbot

docker run -it --rm --name=errbot \
-v /var/volume/errbot:/errbot \
dustise/errbot-image
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;运行之后，我们可以在宿主机系统上看到 errbot 的 Home 文件夹，其中&lt;code&gt;plugins/err-example&lt;/code&gt;中包含了一个样板插件，我们可以查看一下其中的内容：&lt;/p&gt;

&lt;p&gt;** err-example.plug**&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-ini&#34;&gt;[Core]
Name = Example
Module = example

[Documentation]
Description = This is a simple plugin example to get you started.

[Python]
Version = 2+
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;** err-example.py**&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-python&#34;&gt;from errbot import BotPlugin, botcmd
class Example(BotPlugin):
....
    @botcmd  # flags a command
    def tryme(self, msg, args):  # a command callable with !tryme
        return &#39;It *works* !&#39;  # This string format is markdown.
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;字面上看来，这个 Example 中提供了一条叫&lt;code&gt;tryme&lt;/code&gt;的命令，我们回到 bot 控制台，输入&lt;code&gt;!tryme&lt;/code&gt;看一下结果，会发现系统返回了&lt;code&gt;It works&lt;/code&gt;字样。&lt;/p&gt;

&lt;p&gt;接下来我们添加一个新的命令，在 err-example.py 中加入：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-python&#34;&gt;    @botcmd(split_args_with=None)
    def who_are_you(self, msg, args):
       return &amp;quot;you are &amp;quot; + args[0]
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;这一个比上面的稍微复杂一些：&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;botcmd 的 &lt;code&gt;split_args_with&lt;/code&gt; 代表拆分参数&lt;/li&gt;
&lt;li&gt;函数中的下划线，代表子命令，输入时可以使用&lt;code&gt;!who are you&lt;/code&gt;的形式&lt;/li&gt;
&lt;li&gt;拆分参数的结果，以数组形式保存在 args 中。&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;修改存盘之后，使用&lt;code&gt;!restart&lt;/code&gt;命令重启 errbot。输入&lt;code&gt;!who are you ali&lt;/code&gt;，会看到回显内容：&lt;code&gt;you are ali&lt;/code&gt;。&lt;/p&gt;

&lt;h2 id=&#34;源代码&#34;&gt;源代码&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Dockerfile&lt;/strong&gt;：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-dockerfile&#34;&gt;FROM alpine
COPY prepare.sh /usr/local/bin
ENV CLIENT_VER=&amp;quot;&amp;gt;=3.0.0,&amp;lt;4.0.0&amp;quot;
RUN /usr/local/bin/prepare.sh
WORKDIR /errbot
VOLUME [&amp;quot;/errbot&amp;quot;]
CMD [&amp;quot;/usr/local/bin/entry.sh&amp;quot;]
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;prepare.sh&lt;/strong&gt;：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;#!/bin/sh
set -xe
env
apk update
apk upgrade
apk add python3
apk add python3-dev musl-dev gcc libffi-dev openssl-dev
pip3 install errbot
pip3 install &amp;quot;kubernetes$CLIENT_VER&amp;quot;
pip3 install sleekxmpp pyasn1 pyasn1-modules irc hypchat \
  slackclient python-telegram-bot prometheus_client

apk del musl-dev gcc libffi-dev --purge

cat &amp;gt;&amp;gt; /usr/local/bin/entry.sh &amp;lt;&amp;lt; EOF
#!/bin/sh
if [ ! -f /errbot/config.py ]; then
    errbot --init
fi
errbot
EOF

chmod a+x /usr/local/bin/entry.sh
&lt;/code&gt;&lt;/pre&gt;
</description>
    </item>
    
  </channel>
</rss>
